Re: [PATCH xorg-gtest 16/16] Add Device::GetDeviceNode() to return device node path from an evemu device

2012-07-08 Thread Peter Hutterer
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

2012-07-06 Thread Chase Douglas

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

2012-07-05 Thread Chase Douglas

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

2012-07-05 Thread Peter Hutterer
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

2012-07-03 Thread Peter Hutterer
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

2012-07-03 Thread Chase Douglas

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

2012-07-03 Thread Peter Hutterer
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