Amended based on comments from last commit.
This commit is contained in:
parent
86c81f7458
commit
eec9f7750f
@ -169,17 +169,17 @@ void JoystickImpl::initialize()
|
||||
updatePluggedList();
|
||||
|
||||
// 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[3] = std::make_pair<int, int>(100, 0); // right
|
||||
hatValueMap[5] = std::make_pair<int, int>(0, 100); // bottom
|
||||
hatValueMap[7] = std::make_pair<int, int>(-100, 0); // left
|
||||
hatValueMap[1] = std::make_pair( 0, -100); // top
|
||||
hatValueMap[3] = std::make_pair( 100, 0); // right
|
||||
hatValueMap[5] = std::make_pair( 0, 100); // bottom
|
||||
hatValueMap[7] = std::make_pair(-100, 0); // left
|
||||
|
||||
hatValueMap[2] = std::make_pair<int, int>(100, -100); // top-right
|
||||
hatValueMap[4] = std::make_pair<int, int>(100, 100); // bottom-right
|
||||
hatValueMap[6] = std::make_pair<int, int>(-100, 100); // bottom-left
|
||||
hatValueMap[8] = std::make_pair<int, int>(-100, -100); // top-left
|
||||
hatValueMap[2] = std::make_pair( 100, -100); // top-right
|
||||
hatValueMap[4] = std::make_pair( 100, 100); // bottom-right
|
||||
hatValueMap[6] = std::make_pair(-100, 100); // bottom-left
|
||||
hatValueMap[8] = std::make_pair(-100, -100); // top-left
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,47 +101,65 @@ namespace
|
||||
udev_unref(udevContext);
|
||||
}
|
||||
|
||||
bool canRead(int descriptor)
|
||||
bool hasInotifyEvent()
|
||||
{
|
||||
if (descriptor >= 0)
|
||||
{
|
||||
fd_set descriptorSet;
|
||||
FD_ZERO(&descriptorSet);
|
||||
FD_SET(descriptor, &descriptorSet);
|
||||
timeval timeout = {0, 0};
|
||||
fd_set descriptorSet;
|
||||
FD_ZERO(&descriptorSet);
|
||||
FD_SET(notifyFd, &descriptorSet);
|
||||
timeval timeout = {0, 0};
|
||||
|
||||
return (select(descriptor + 1, &descriptorSet, NULL, NULL, &timeout) > 0) &&
|
||||
FD_ISSET(notifyFd, &descriptorSet);
|
||||
}
|
||||
|
||||
return false;
|
||||
return (select(notifyFd + 1, &descriptorSet, NULL, NULL, &timeout) > 0) &&
|
||||
FD_ISSET(notifyFd, &descriptorSet);
|
||||
}
|
||||
|
||||
// Get the joystick name
|
||||
std::string getJoystickName(int file, unsigned int index)
|
||||
{
|
||||
// Get the name
|
||||
char joyname[128];
|
||||
char name[128];
|
||||
|
||||
if (ioctl(file, JSIOCGNAME(sizeof(joyname)), joyname) >= 0)
|
||||
return std::string(joyname);
|
||||
if (ioctl(file, JSIOCGNAME(sizeof(name)), name) >= 0)
|
||||
return std::string(name);
|
||||
|
||||
sf::err() << "Unable to get name for joystick at index " << index << std::endl;
|
||||
|
||||
return std::string("Unknown Joystick");
|
||||
}
|
||||
|
||||
|
||||
// Get a system attribute from udev as an unsigned int
|
||||
unsigned int getUdevAttributeUint(unsigned int index, std::string attributeName)
|
||||
// Get a system attribute from a udev device as an unsigned int
|
||||
unsigned int getUdevAttributeUint(udev_device* device, unsigned int index, const 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();
|
||||
|
||||
if (!udevContext)
|
||||
{
|
||||
sf::err() << "Unable to get attribute '" << attributeName << "'. Cannot create udev for reading info for joystick at index " << index << std::endl;
|
||||
return attribute;
|
||||
sf::err() << "Unable to get joystick attribute. "
|
||||
<< "Could not create udev context." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::ostringstream sysname("js");
|
||||
@ -151,21 +169,13 @@ namespace
|
||||
|
||||
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);
|
||||
return attribute;
|
||||
return 0;
|
||||
}
|
||||
|
||||
udev_device* udevDeviceParent = udev_device_get_parent_with_subsystem_devtype(udevDevice, "usb", "usb_device");
|
||||
|
||||
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));
|
||||
}
|
||||
unsigned int attribute = getUdevAttributeUint(udevDevice, index, attributeName);
|
||||
|
||||
udev_device_unref(udevDevice);
|
||||
udev_unref(udevContext);
|
||||
@ -184,6 +194,9 @@ void JoystickImpl::initialize()
|
||||
// Reset the array of plugged joysticks
|
||||
std::fill(plugged, plugged + Joystick::Count, false);
|
||||
|
||||
// Do an initial scan
|
||||
updatePluggedList();
|
||||
|
||||
// Create the inotify instance
|
||||
notifyFd = inotify_init();
|
||||
if (notifyFd < 0)
|
||||
@ -197,11 +210,11 @@ void JoystickImpl::initialize()
|
||||
if (inputFd < 0)
|
||||
{
|
||||
err() << "Failed to initialize inotify, joystick connections and disconnections won't be notified" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do an initial scan
|
||||
updatePluggedList();
|
||||
// No need to hang on to the inotify handle in this case
|
||||
::close(notifyFd);
|
||||
notifyFd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -221,18 +234,21 @@ void JoystickImpl::cleanup()
|
||||
////////////////////////////////////////////////////////////
|
||||
bool JoystickImpl::isConnected(unsigned int index)
|
||||
{
|
||||
// First check if new joysticks were added/removed since last update
|
||||
if (canRead(notifyFd))
|
||||
// See if we can skip scanning if inotify is available
|
||||
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
|
||||
updatePluggedList();
|
||||
|
||||
// Flush all the pending events
|
||||
while (canRead(notifyFd))
|
||||
{
|
||||
char buffer[128];
|
||||
(void)read(notifyFd, buffer, sizeof(buffer));
|
||||
}
|
||||
if (lseek(notifyFd, 0, SEEK_END) < 0)
|
||||
err() << "Failed to flush inotify of all pending joystick events." << std::endl;
|
||||
}
|
||||
|
||||
// Then check if the joystick is connected
|
||||
@ -256,8 +272,8 @@ bool JoystickImpl::open(unsigned int index)
|
||||
|
||||
// Get info
|
||||
m_identification.name = getJoystickName(m_file, index);
|
||||
m_identification.vendorId = getUdevAttributeUint(index, "idVendor");
|
||||
m_identification.productId = getUdevAttributeUint(index, "idProduct");
|
||||
m_identification.vendorId = getAttributeUint(index, "idVendor");
|
||||
m_identification.productId = getAttributeUint(index, "idProduct");
|
||||
|
||||
// Reset the joystick state
|
||||
m_state = JoystickState();
|
||||
|
Loading…
Reference in New Issue
Block a user