[PATCH xorg-gtest 3/4] Add Device::GetDeviceNode() to return device node path from an evemu device
Chase Douglas
chase.douglas at canonical.com
Wed Jul 11 12:35:45 PDT 2012
On 07/10/2012 06:51 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.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> include/xorg/gtest/evemu/xorg-gtest-device.h | 13 +++++
> src/device.cpp | 67 +++++++++++++++++++++++++-
> 2 files changed, 79 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.
Need to add a comment that if the device couldn't be determined, the
returned string will be empty.
> + *
> + * @return The string representing the device node
> + */
> + const char* GetDeviceNode(void);
We should use std::string:
const std::string& GetDeviceNode(void);
We're already storing the path as a string.
> +
> private:
> struct Private;
> std::auto_ptr<Private> 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..1d9f6fc 100644
> --- a/src/device.cpp
> +++ b/src/device.cpp
> @@ -28,18 +28,76 @@
> #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);
> + }
> +
> + for (int i = 0; i < n_event_devices; i++)
> + 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 +126,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 +149,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);
>
With the fixes:
Reviewed-by: Chase Douglas <chase.douglas at canonical.com>
More information about the xorg-devel
mailing list