Amended based on comments from last commit.

This commit is contained in:
binary1248 2014-07-16 10:17:26 +02:00
parent 86c81f7458
commit eec9f7750f
2 changed files with 71 additions and 55 deletions

View File

@ -169,17 +169,17 @@ void JoystickImpl::initialize()
updatePluggedList(); updatePluggedList();
// Map of hat values // Map of hat values
hatValueMap[0] = std::make_pair<int, int>(0, 0); // center hatValueMap[0] = std::make_pair( 0, 0); // center
hatValueMap[1] = std::make_pair<int, int>(0, -100); // top hatValueMap[1] = std::make_pair( 0, -100); // top
hatValueMap[3] = std::make_pair<int, int>(100, 0); // right hatValueMap[3] = std::make_pair( 100, 0); // right
hatValueMap[5] = std::make_pair<int, int>(0, 100); // bottom hatValueMap[5] = std::make_pair( 0, 100); // bottom
hatValueMap[7] = std::make_pair<int, int>(-100, 0); // left hatValueMap[7] = std::make_pair(-100, 0); // left
hatValueMap[2] = std::make_pair<int, int>(100, -100); // top-right hatValueMap[2] = std::make_pair( 100, -100); // top-right
hatValueMap[4] = std::make_pair<int, int>(100, 100); // bottom-right hatValueMap[4] = std::make_pair( 100, 100); // bottom-right
hatValueMap[6] = std::make_pair<int, int>(-100, 100); // bottom-left hatValueMap[6] = std::make_pair(-100, 100); // bottom-left
hatValueMap[8] = std::make_pair<int, int>(-100, -100); // top-left hatValueMap[8] = std::make_pair(-100, -100); // top-left
} }

View File

@ -101,47 +101,65 @@ namespace
udev_unref(udevContext); udev_unref(udevContext);
} }
bool canRead(int descriptor) bool hasInotifyEvent()
{ {
if (descriptor >= 0) fd_set descriptorSet;
{ FD_ZERO(&descriptorSet);
fd_set descriptorSet; FD_SET(notifyFd, &descriptorSet);
FD_ZERO(&descriptorSet); timeval timeout = {0, 0};
FD_SET(descriptor, &descriptorSet);
timeval timeout = {0, 0};
return (select(descriptor + 1, &descriptorSet, NULL, NULL, &timeout) > 0) && return (select(notifyFd + 1, &descriptorSet, NULL, NULL, &timeout) > 0) &&
FD_ISSET(notifyFd, &descriptorSet); FD_ISSET(notifyFd, &descriptorSet);
}
return false;
} }
// Get the joystick name // Get the joystick name
std::string getJoystickName(int file, unsigned int index) std::string getJoystickName(int file, unsigned int index)
{ {
// Get the name // Get the name
char joyname[128]; char name[128];
if (ioctl(file, JSIOCGNAME(sizeof(joyname)), joyname) >= 0) if (ioctl(file, JSIOCGNAME(sizeof(name)), name) >= 0)
return std::string(joyname); return std::string(name);
sf::err() << "Unable to get name for joystick at index " << index << std::endl; sf::err() << "Unable to get name for joystick at index " << index << std::endl;
return std::string("Unknown Joystick"); return std::string("Unknown Joystick");
} }
// Get a system attribute from a udev device as an unsigned int
// Get a system attribute from udev as an unsigned int unsigned int getUdevAttributeUint(udev_device* device, unsigned int index, const std::string& attributeName)
unsigned int getUdevAttributeUint(unsigned int index, std::string attributeName) {
udev_device* udevDeviceParent = udev_device_get_parent_with_subsystem_devtype(device, "usb", "usb_device");
if (!udevDeviceParent)
{
sf::err() << "Unable to get joystick attribute. "
<< "Could not find parent USB device for joystick at index " << index << "." << std::endl;
return 0;
}
const char* attributeString = udev_device_get_sysattr_value(udevDeviceParent, attributeName.c_str());
if (!attributeString)
{
sf::err() << "Unable to get joystick attribute '" << attributeName << "'. "
<< "Attribute does not exist for joystick at index " << index << "." << std::endl;
return 0;
}
return static_cast<unsigned int>(std::strtoul(attributeString, NULL, 16));
}
// Get a system attribute for a joystick at index as an unsigned int
unsigned int getAttributeUint(unsigned int index, const std::string& attributeName)
{ {
unsigned int attribute = 0;
udev* udevContext = udev_new(); udev* udevContext = udev_new();
if (!udevContext) if (!udevContext)
{ {
sf::err() << "Unable to get attribute '" << attributeName << "'. Cannot create udev for reading info for joystick at index " << index << std::endl; sf::err() << "Unable to get joystick attribute. "
return attribute; << "Could not create udev context." << std::endl;
return 0;
} }
std::ostringstream sysname("js"); std::ostringstream sysname("js");
@ -151,21 +169,13 @@ namespace
if (!udevDevice) if (!udevDevice)
{ {
sf::err() << "Unable to get attribute '" << attributeName << "'. Could not find USB device for joystick at index " << index << std::endl; sf::err() << "Unable to get joystick attribute. "
<< "Could not find USB device for joystick at index " << index << "." << std::endl;
udev_unref(udevContext); udev_unref(udevContext);
return attribute; return 0;
} }
udev_device* udevDeviceParent = udev_device_get_parent_with_subsystem_devtype(udevDevice, "usb", "usb_device"); unsigned int attribute = getUdevAttributeUint(udevDevice, index, attributeName);
if (!udevDeviceParent)
{
sf::err() << "Unable to get attribute '" << attributeName << "'. Could not find parent USB device for joystick at index " << index << std::endl;
}
else
{
attribute = static_cast<unsigned int>(strtoul(udev_device_get_sysattr_value(udevDeviceParent, attributeName.c_str()), NULL, 16));
}
udev_device_unref(udevDevice); udev_device_unref(udevDevice);
udev_unref(udevContext); udev_unref(udevContext);
@ -184,6 +194,9 @@ void JoystickImpl::initialize()
// Reset the array of plugged joysticks // Reset the array of plugged joysticks
std::fill(plugged, plugged + Joystick::Count, false); std::fill(plugged, plugged + Joystick::Count, false);
// Do an initial scan
updatePluggedList();
// Create the inotify instance // Create the inotify instance
notifyFd = inotify_init(); notifyFd = inotify_init();
if (notifyFd < 0) if (notifyFd < 0)
@ -197,11 +210,11 @@ void JoystickImpl::initialize()
if (inputFd < 0) if (inputFd < 0)
{ {
err() << "Failed to initialize inotify, joystick connections and disconnections won't be notified" << std::endl; err() << "Failed to initialize inotify, joystick connections and disconnections won't be notified" << std::endl;
return;
}
// Do an initial scan // No need to hang on to the inotify handle in this case
updatePluggedList(); ::close(notifyFd);
notifyFd = -1;
}
} }
@ -221,18 +234,21 @@ void JoystickImpl::cleanup()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool JoystickImpl::isConnected(unsigned int index) bool JoystickImpl::isConnected(unsigned int index)
{ {
// First check if new joysticks were added/removed since last update // See if we can skip scanning if inotify is available
if (canRead(notifyFd)) if (notifyFd < 0)
{ {
// inotify is not available, perform a scan every query
updatePluggedList();
}
else if (hasInotifyEvent())
{
// Check if new joysticks were added/removed since last update
// Don't bother decomposing and interpreting the filename, just do a full scan // Don't bother decomposing and interpreting the filename, just do a full scan
updatePluggedList(); updatePluggedList();
// Flush all the pending events // Flush all the pending events
while (canRead(notifyFd)) if (lseek(notifyFd, 0, SEEK_END) < 0)
{ err() << "Failed to flush inotify of all pending joystick events." << std::endl;
char buffer[128];
(void)read(notifyFd, buffer, sizeof(buffer));
}
} }
// Then check if the joystick is connected // Then check if the joystick is connected
@ -256,8 +272,8 @@ bool JoystickImpl::open(unsigned int index)
// Get info // Get info
m_identification.name = getJoystickName(m_file, index); m_identification.name = getJoystickName(m_file, index);
m_identification.vendorId = getUdevAttributeUint(index, "idVendor"); m_identification.vendorId = getAttributeUint(index, "idVendor");
m_identification.productId = getUdevAttributeUint(index, "idProduct"); m_identification.productId = getAttributeUint(index, "idProduct");
// Reset the joystick state // Reset the joystick state
m_state = JoystickState(); m_state = JoystickState();