diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2012-07-02 15:25:51 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2012-07-04 07:58:52 +1000 |
commit | d049b8001798e89a85923a207a976aaf7de6ed1c (patch) | |
tree | 2847992f7fdfe2a2779eaa5286bcb0a41c670f43 | |
parent | 3ef95005f4bd24191c52532fc161f23b0ffa4ff3 (diff) |
Add Device::GetDeviceNode() to return device node path from an evemu devicedevel-version-1
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@who-t.net>
-rw-r--r-- | include/xorg/gtest/evemu/xorg-gtest-device.h | 13 | ||||
-rw-r--r-- | src/device.cpp | 65 |
2 files changed, 77 insertions, 1 deletions
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_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..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); |