Re: [PATCH xorg-gtest 16/16] Add Device::GetDeviceNode() to return device node path from an evemu device
On Fri, Jul 06, 2012 at 11:11:55AM -0700, Chase Douglas wrote: On 07/05/2012 04:41 PM, Peter Hutterer wrote: On Thu, Jul 05, 2012 at 02:19:33PM -0700, Chase Douglas wrote: On 07/03/2012 11:03 PM, Peter Hutterer wrote: On Tue, Jul 03, 2012 at 11:40:25AM -0700, Chase Douglas wrote: On 07/02/2012 11:44 PM, Peter Hutterer wrote: evemu doesn't export this information and even evemu-device just trawls through the file system to print this info. So do the same here, noting the time before evemu_create() and the ctime of the new device file. If the latter is later than the former and the device names match, we can assume this is our device. I just want to point out that it's a deficiency in uinput, not in evemu, in case anyone had any thoughts of trying to fix evemu instead. I did try. This could easily be part of evemu, running this exact same code right after the UI_DEV_CREATE call. Unfortunately evemu_create() takes a const struct so we can't save it easily without breaking ABI. Well, evemu could try to guess, just as this code does. What I meant was more that uinput is deficient in that there's no way to be 100% sure. That's the main reason why we didn't bother putting code like this into evemu directly. the one advantage evemu has though is that it's in the best position to guess given that it just created the device and has easy access to all other information. plus, it wouldn't require duplicating the code across other projects. Yeah, good point. Maybe I should just take the find_newest_device_node_with_name function in evemu-device.c and copy it into the library proper? yeah, it wouldn't hurt to have it there. Cheers, Peter ___ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
Re: [PATCH xorg-gtest 16/16] Add Device::GetDeviceNode() to return device node path from an evemu device
On 07/05/2012 04:41 PM, Peter Hutterer wrote: On Thu, Jul 05, 2012 at 02:19:33PM -0700, Chase Douglas wrote: On 07/03/2012 11:03 PM, Peter Hutterer wrote: On Tue, Jul 03, 2012 at 11:40:25AM -0700, Chase Douglas wrote: On 07/02/2012 11:44 PM, Peter Hutterer wrote: evemu doesn't export this information and even evemu-device just trawls through the file system to print this info. So do the same here, noting the time before evemu_create() and the ctime of the new device file. If the latter is later than the former and the device names match, we can assume this is our device. I just want to point out that it's a deficiency in uinput, not in evemu, in case anyone had any thoughts of trying to fix evemu instead. I did try. This could easily be part of evemu, running this exact same code right after the UI_DEV_CREATE call. Unfortunately evemu_create() takes a const struct so we can't save it easily without breaking ABI. Well, evemu could try to guess, just as this code does. What I meant was more that uinput is deficient in that there's no way to be 100% sure. That's the main reason why we didn't bother putting code like this into evemu directly. the one advantage evemu has though is that it's in the best position to guess given that it just created the device and has easy access to all other information. plus, it wouldn't require duplicating the code across other projects. Yeah, good point. Maybe I should just take the find_newest_device_node_with_name function in evemu-device.c and copy it into the library proper? -- Chase ___ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
Re: [PATCH xorg-gtest 16/16] Add Device::GetDeviceNode() to return device node path from an evemu device
On 07/03/2012 11:03 PM, Peter Hutterer wrote: On Tue, Jul 03, 2012 at 11:40:25AM -0700, Chase Douglas wrote: On 07/02/2012 11:44 PM, Peter Hutterer wrote: evemu doesn't export this information and even evemu-device just trawls through the file system to print this info. So do the same here, noting the time before evemu_create() and the ctime of the new device file. If the latter is later than the former and the device names match, we can assume this is our device. I just want to point out that it's a deficiency in uinput, not in evemu, in case anyone had any thoughts of trying to fix evemu instead. I did try. This could easily be part of evemu, running this exact same code right after the UI_DEV_CREATE call. Unfortunately evemu_create() takes a const struct so we can't save it easily without breaking ABI. Well, evemu could try to guess, just as this code does. What I meant was more that uinput is deficient in that there's no way to be 100% sure. That's the main reason why we didn't bother putting code like this into evemu directly. -- Chase ___ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
Re: [PATCH xorg-gtest 16/16] Add Device::GetDeviceNode() to return device node path from an evemu device
On Thu, Jul 05, 2012 at 02:19:33PM -0700, Chase Douglas wrote: On 07/03/2012 11:03 PM, Peter Hutterer wrote: On Tue, Jul 03, 2012 at 11:40:25AM -0700, Chase Douglas wrote: On 07/02/2012 11:44 PM, Peter Hutterer wrote: evemu doesn't export this information and even evemu-device just trawls through the file system to print this info. So do the same here, noting the time before evemu_create() and the ctime of the new device file. If the latter is later than the former and the device names match, we can assume this is our device. I just want to point out that it's a deficiency in uinput, not in evemu, in case anyone had any thoughts of trying to fix evemu instead. I did try. This could easily be part of evemu, running this exact same code right after the UI_DEV_CREATE call. Unfortunately evemu_create() takes a const struct so we can't save it easily without breaking ABI. Well, evemu could try to guess, just as this code does. What I meant was more that uinput is deficient in that there's no way to be 100% sure. That's the main reason why we didn't bother putting code like this into evemu directly. the one advantage evemu has though is that it's in the best position to guess given that it just created the device and has easy access to all other information. plus, it wouldn't require duplicating the code across other projects. Cheers, Peter ___ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
[PATCH xorg-gtest 16/16] Add Device::GetDeviceNode() to return device node path from an evemu device
evemu doesn't export this information and even evemu-device just trawls through the file system to print this info. So do the same here, noting the time before evemu_create() and the ctime of the new device file. If the latter is later than the former and the device names match, we can assume this is our device. Signed-off-by: Peter Hutterer peter.hutte...@who-t.net --- include/xorg/gtest/evemu/xorg-gtest-device.h | 13 ++ src/device.cpp | 65 +- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/include/xorg/gtest/evemu/xorg-gtest-device.h b/include/xorg/gtest/evemu/xorg-gtest-device.h index 5f8faa2..359e65b 100644 --- a/include/xorg/gtest/evemu/xorg-gtest-device.h +++ b/include/xorg/gtest/evemu/xorg-gtest-device.h @@ -75,6 +75,17 @@ class Device { */ void Play(const std::string path) const; + /** + * Return the /dev/input/eventX device node for this device. + * + * Note that evemu doesn't know the device node, so we traverse the file + * system looking for it. There is a tiny chance of the device node being + * wrong. + * + * @return The string representing the device node + */ + const char* GetDeviceNode(void); + private: struct Private; std::auto_ptrPrivate d_; @@ -82,6 +93,8 @@ class Device { /* Disable copy constructor assignment operator */ Device(const Device); Device operator=(const Device); + + void GuessDeviceNode(time_t ctime); }; } // namespace evemu diff --git a/src/device.cpp b/src/device.cpp index 226d4e0..555e3e0 100644 --- a/src/device.cpp +++ b/src/device.cpp @@ -28,18 +28,74 @@ #include xorg/gtest/evemu/xorg-gtest-device.h #include fcntl.h +#include dirent.h #include stdexcept #include gtest/gtest.h +#define SYS_INPUT_DIR /sys/class/input +#define DEV_INPUT_DIR /dev/input/ + struct xorg::testing::evemu::Device::Private { - Private() : fd(-1), device(NULL) {} + Private() : fd(-1), device(NULL), device_node() {} int fd; struct evemu_device* device; + std::string device_node; }; +static int _event_device_compare(const struct dirent **a, + const struct dirent **b) { + int na, nb; + + sscanf((*a)-d_name, event%d, na); + sscanf((*b)-d_name, event%d, nb); + + return (na nb) ? 1 : (na nb) ? -1 : 0; + +} + +static int _event_device_filter(const struct dirent *d) { + return (strncmp(event, d-d_name, sizeof(event) - 1) == 0); +} + +void xorg::testing::evemu::Device::GuessDeviceNode(time_t ctime) { + struct dirent **event_devices; + int n_event_devices; + + n_event_devices = scandir(SYS_INPUT_DIR, event_devices, +_event_device_filter, _event_device_compare); + + if (n_event_devices 0) { +std::cerr Failed to guess device node. std::endl; +return; + } + + bool found = false; + for (int i = 0; i n_event_devices !found; i++) { +std::stringstream s; +s DEV_INPUT_DIR event_devices[i]-d_name; + +int fd = open(s.str().c_str(), O_RDONLY); +char device_name[256]; + +ioctl(fd, EVIOCGNAME(sizeof(device_name)), device_name); +if (strcmp(device_name, evemu_get_name(d_-device)) == 0) { + struct stat buf; + if (fstat(fd, buf) == 0) { +if (buf.st_ctime = ctime) { + d_-device_node = s.str(); + found = true; +} + } +} +close(fd); +free(event_devices[i]); + } + free(event_devices); +} + xorg::testing::evemu::Device::Device(const std::string path) : d_(new Private) { static const char UINPUT_NODE[] = /dev/uinput; @@ -68,11 +124,14 @@ xorg::testing::evemu::Device::Device(const std::string path) throw std::runtime_error(Failed to open uinput node); } + time_t ctime = time(NULL); if (evemu_create(d_-device, d_-fd) 0) { close(d_-fd); evemu_delete(d_-device); throw std::runtime_error(Failed to create evemu device); } + + GuessDeviceNode(ctime); } void xorg::testing::evemu::Device::Play(const std::string path) const { @@ -88,6 +147,10 @@ void xorg::testing::evemu::Device::Play(const std::string path) const { fclose(file); } +const char* xorg::testing::evemu::Device::GetDeviceNode(void) { + return d_-device_node.length() 0 ? d_-device_node.c_str() : NULL; +} + xorg::testing::evemu::Device::~Device() { close(d_-fd); evemu_delete(d_-device); -- 1.7.10.4 ___ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
Re: [PATCH xorg-gtest 16/16] Add Device::GetDeviceNode() to return device node path from an evemu device
On 07/02/2012 11:44 PM, Peter Hutterer wrote: evemu doesn't export this information and even evemu-device just trawls through the file system to print this info. So do the same here, noting the time before evemu_create() and the ctime of the new device file. If the latter is later than the former and the device names match, we can assume this is our device. I just want to point out that it's a deficiency in uinput, not in evemu, in case anyone had any thoughts of trying to fix evemu instead. Signed-off-by: Peter Hutterer peter.hutte...@who-t.net --- include/xorg/gtest/evemu/xorg-gtest-device.h | 13 ++ src/device.cpp | 65 +- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/include/xorg/gtest/evemu/xorg-gtest-device.h b/include/xorg/gtest/evemu/xorg-gtest-device.h index 5f8faa2..359e65b 100644 --- a/include/xorg/gtest/evemu/xorg-gtest-device.h +++ b/include/xorg/gtest/evemu/xorg-gtest-device.h @@ -75,6 +75,17 @@ class Device { */ void Play(const std::string path) const; + /** + * Return the /dev/input/eventX device node for this device. + * + * Note that evemu doesn't know the device node, so we traverse the file + * system looking for it. There is a tiny chance of the device node being + * wrong. + * + * @return The string representing the device node + */ + const char* GetDeviceNode(void); + private: struct Private; std::auto_ptrPrivate d_; @@ -82,6 +93,8 @@ class Device { /* Disable copy constructor assignment operator */ Device(const Device); Device operator=(const Device); + + void GuessDeviceNode(time_t ctime); }; } // namespace evemu diff --git a/src/device.cpp b/src/device.cpp index 226d4e0..555e3e0 100644 --- a/src/device.cpp +++ b/src/device.cpp @@ -28,18 +28,74 @@ #include xorg/gtest/evemu/xorg-gtest-device.h #include fcntl.h +#include dirent.h #include stdexcept #include gtest/gtest.h +#define SYS_INPUT_DIR /sys/class/input +#define DEV_INPUT_DIR /dev/input/ + struct xorg::testing::evemu::Device::Private { - Private() : fd(-1), device(NULL) {} + Private() : fd(-1), device(NULL), device_node() {} int fd; struct evemu_device* device; + std::string device_node; }; +static int _event_device_compare(const struct dirent **a, + const struct dirent **b) { + int na, nb; + + sscanf((*a)-d_name, event%d, na); + sscanf((*b)-d_name, event%d, nb); + + return (na nb) ? 1 : (na nb) ? -1 : 0; + +} + +static int _event_device_filter(const struct dirent *d) { + return (strncmp(event, d-d_name, sizeof(event) - 1) == 0); +} + +void xorg::testing::evemu::Device::GuessDeviceNode(time_t ctime) { + struct dirent **event_devices; + int n_event_devices; + + n_event_devices = scandir(SYS_INPUT_DIR, event_devices, +_event_device_filter, _event_device_compare); + + if (n_event_devices 0) { +std::cerr Failed to guess device node. std::endl; +return; + } + + bool found = false; + for (int i = 0; i n_event_devices !found; i++) { +std::stringstream s; +s DEV_INPUT_DIR event_devices[i]-d_name; + +int fd = open(s.str().c_str(), O_RDONLY); +char device_name[256]; + +ioctl(fd, EVIOCGNAME(sizeof(device_name)), device_name); +if (strcmp(device_name, evemu_get_name(d_-device)) == 0) { + struct stat buf; + if (fstat(fd, buf) == 0) { +if (buf.st_ctime = ctime) { + d_-device_node = s.str(); + found = true; +} + } +} +close(fd); +free(event_devices[i]); We need to free each event device entry, but if we break out of the loops early because we've found a matching device, then we won't free the rest of the devices in the array. + } + free(event_devices); +} + xorg::testing::evemu::Device::Device(const std::string path) : d_(new Private) { static const char UINPUT_NODE[] = /dev/uinput; @@ -68,11 +124,14 @@ xorg::testing::evemu::Device::Device(const std::string path) throw std::runtime_error(Failed to open uinput node); } + time_t ctime = time(NULL); if (evemu_create(d_-device, d_-fd) 0) { close(d_-fd); evemu_delete(d_-device); throw std::runtime_error(Failed to create evemu device); } + + GuessDeviceNode(ctime); } void xorg::testing::evemu::Device::Play(const std::string path) const { @@ -88,6 +147,10 @@ void xorg::testing::evemu::Device::Play(const std::string path) const { fclose(file); } +const char* xorg::testing::evemu::Device::GetDeviceNode(void) { + return d_-device_node.length() 0 ? d_-device_node.c_str() : NULL; +} + xorg::testing::evemu::Device::~Device() { close(d_-fd); evemu_delete(d_-device); ___ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
Re: [PATCH xorg-gtest 16/16] Add Device::GetDeviceNode() to return device node path from an evemu device
On Tue, Jul 03, 2012 at 11:40:25AM -0700, Chase Douglas wrote: On 07/02/2012 11:44 PM, Peter Hutterer wrote: evemu doesn't export this information and even evemu-device just trawls through the file system to print this info. So do the same here, noting the time before evemu_create() and the ctime of the new device file. If the latter is later than the former and the device names match, we can assume this is our device. I just want to point out that it's a deficiency in uinput, not in evemu, in case anyone had any thoughts of trying to fix evemu instead. I did try. This could easily be part of evemu, running this exact same code right after the UI_DEV_CREATE call. Unfortunately evemu_create() takes a const struct so we can't save it easily without breaking ABI. [memleak fixed, thanks for pointing this out] Cheers, Peter Signed-off-by: Peter Hutterer peter.hutte...@who-t.net --- include/xorg/gtest/evemu/xorg-gtest-device.h | 13 ++ src/device.cpp | 65 +- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/include/xorg/gtest/evemu/xorg-gtest-device.h b/include/xorg/gtest/evemu/xorg-gtest-device.h index 5f8faa2..359e65b 100644 --- a/include/xorg/gtest/evemu/xorg-gtest-device.h +++ b/include/xorg/gtest/evemu/xorg-gtest-device.h @@ -75,6 +75,17 @@ class Device { */ void Play(const std::string path) const; + /** + * Return the /dev/input/eventX device node for this device. + * + * Note that evemu doesn't know the device node, so we traverse the file + * system looking for it. There is a tiny chance of the device node being + * wrong. + * + * @return The string representing the device node + */ + const char* GetDeviceNode(void); + private: struct Private; std::auto_ptrPrivate d_; @@ -82,6 +93,8 @@ class Device { /* Disable copy constructor assignment operator */ Device(const Device); Device operator=(const Device); + + void GuessDeviceNode(time_t ctime); }; } // namespace evemu diff --git a/src/device.cpp b/src/device.cpp index 226d4e0..555e3e0 100644 --- a/src/device.cpp +++ b/src/device.cpp @@ -28,18 +28,74 @@ #include xorg/gtest/evemu/xorg-gtest-device.h #include fcntl.h +#include dirent.h #include stdexcept #include gtest/gtest.h +#define SYS_INPUT_DIR /sys/class/input +#define DEV_INPUT_DIR /dev/input/ + struct xorg::testing::evemu::Device::Private { - Private() : fd(-1), device(NULL) {} + Private() : fd(-1), device(NULL), device_node() {} int fd; struct evemu_device* device; + std::string device_node; }; +static int _event_device_compare(const struct dirent **a, + const struct dirent **b) { + int na, nb; + + sscanf((*a)-d_name, event%d, na); + sscanf((*b)-d_name, event%d, nb); + + return (na nb) ? 1 : (na nb) ? -1 : 0; + +} + +static int _event_device_filter(const struct dirent *d) { + return (strncmp(event, d-d_name, sizeof(event) - 1) == 0); +} + +void xorg::testing::evemu::Device::GuessDeviceNode(time_t ctime) { + struct dirent **event_devices; + int n_event_devices; + + n_event_devices = scandir(SYS_INPUT_DIR, event_devices, +_event_device_filter, _event_device_compare); + + if (n_event_devices 0) { +std::cerr Failed to guess device node. std::endl; +return; + } + + bool found = false; + for (int i = 0; i n_event_devices !found; i++) { +std::stringstream s; +s DEV_INPUT_DIR event_devices[i]-d_name; + +int fd = open(s.str().c_str(), O_RDONLY); +char device_name[256]; + +ioctl(fd, EVIOCGNAME(sizeof(device_name)), device_name); +if (strcmp(device_name, evemu_get_name(d_-device)) == 0) { + struct stat buf; + if (fstat(fd, buf) == 0) { +if (buf.st_ctime = ctime) { + d_-device_node = s.str(); + found = true; +} + } +} +close(fd); +free(event_devices[i]); We need to free each event device entry, but if we break out of the loops early because we've found a matching device, then we won't free the rest of the devices in the array. + } + free(event_devices); +} + xorg::testing::evemu::Device::Device(const std::string path) : d_(new Private) { static const char UINPUT_NODE[] = /dev/uinput; @@ -68,11 +124,14 @@ xorg::testing::evemu::Device::Device(const std::string path) throw std::runtime_error(Failed to open uinput node); } + time_t ctime = time(NULL); if (evemu_create(d_-device, d_-fd) 0) { close(d_-fd); evemu_delete(d_-device); throw std::runtime_error(Failed to create evemu device); } + + GuessDeviceNode(ctime); } void xorg::testing::evemu::Device::Play(const std::string path) const { @@ -88,6 +147,10 @@ void xorg::testing::evemu::Device::Play(const