Complete enumeration of evdev.
authorbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 18 Apr 2014 04:14:12 +0000 (04:14 +0000)
committerbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 18 Apr 2014 04:14:12 +0000 (04:14 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1500 01035d8c-6547-0410-b346-abe4f91aad63

freedv-server/source/platform/linux/evdev.cpp
freedv-server/source/platform/linux/evdev.h

index d23bb5dd98cfcae97ca83d4ed64e267526bdac2f..073436ef5dad849f334271a454bc7f2b1bde502c 100644 (file)
 #include "evdev.h"
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <linux/input.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sstream>
 
-const struct EvDev::device_enumeration *
-EvDev::enumerate(std::size_t &)
+// Remove extra spaces from string, in place.
+char *
+clean_string(char * string)
 {
-  return 0;
+  char * s = string;
+
+  while ( *s != 0 ) {
+    if ( *s == ' ' && s[1] == ' ' ) {
+      s++;
+      char * end = s;
+      while ( *end == ' ' )
+        end++;
+      memmove(s, end, strlen(end) + 1);
+    }
+    s++;
+  }
+
+  const std::size_t length = strlen(string);
+
+  if ( length > 1 && string[length - 1] == ' ' )
+    string[length - 1] = '\0';
+
+  return string;
+}
+
+void
+EvDev::delete_enumeration(
+ EvDev::device_enumeration *   data,
+ std::size_t                   count)
+{
+  for ( std::size_t i = 0; i < count; i++ ) {
+    delete data[i].special_file;
+    delete data[i].name;
+  }
+  delete data;
+}
+
+struct EvDev::device_enumeration *
+EvDev::enumerate(std::size_t & count)
+{
+  struct device_enumeration    devices[100];
+
+  count = 0;
+
+  for ( int i = 0; sizeof(devices) / sizeof(*devices); i++ ) {
+    std::ostringstream str;
+
+    str << "/dev/input/event" << i;
+
+    const char * const special_file = str.str().c_str();
+
+    const int fd = open(special_file, O_RDONLY);
+
+    if ( fd >= 0 ) {
+      if ( enumerate_device(special_file, fd, devices[count]) )
+        count++;
+      close(fd);
+    }
+  }
+  device_enumeration * const r = new device_enumeration[count];
+  
+  memcpy(r, devices, count * sizeof(*r));
+
+  return r;
+}
+
+bool
+EvDev::enumerate_device(
+ const char *          special_file,
+ int                   fd,
+ device_enumeration &  device)
+{
+  char                 buf[100];
+  std::ostringstream   str;
+
+  device.special_file = strdup(special_file);
+
+  if ( ioctl(fd, EVIOCGNAME(sizeof(buf)), buf) < 0
+  ||   ioctl(fd, EVIOCGBIT(0, sizeof(device.event_types)), device.event_types)
+   < 0 )
+    return false;
+
+  str << clean_string(buf);
+
+  if ( ioctl(fd, EVIOCGUNIQ(sizeof(buf)), buf) >= 0 )
+    str << ' ' << clean_string(buf);
+
+  if ( ioctl(fd, EVIOCGPHYS(sizeof(buf)), buf) >= 0 )
+    str << " at " << clean_string(buf);
+
+  device.name = strdup(str.str().c_str());
+
+  return true;
 }
 
 const char * const *
 EvDev::EnumerateButtonDevices()
 {
+  std::size_t                  count = 0;
+  std::size_t                  length = 0;
+  device_enumeration * const   devices = enumerate(count);
+
+  for ( std::size_t i = 0; i < count; i++ ) {
+    if ( test_bit(EV_KEY, devices[i].event_types) )
+      length++;
+  }
+
+  delete_enumeration(devices, count);
   return 0;
 }
 
index 3a46be9383fa9499c92a0584e634e5af4c2c066e..e4491ef7e80e581537f41b5396f0e5dc7df02b13 100644 (file)
@@ -9,20 +9,30 @@
 #define test_bit(bit, array)   ((array[LONG(bit)] >> OFF(bit)) & 1)
 
 class EvDev {
+protected:
+  struct device_enumeration {
+    const char *       special_file;
+    const char *       name;
+    uint8_t            event_types[(EV_MAX + 7) / 8];
+  };
+
 private:
 
                        EvDev(const EvDev &);
   EvDev &              operator =(const EvDev &);
 
+  static bool          enumerate_device(
+                        const char *                   name,
+                        int                            fd,
+                        struct device_enumeration &    device);
+
 protected:
-  struct device_enumeration {
-    const char *       device;
-    const char *       name;
-    uint8_t            event_types[(EV_MAX + 7) / 8];
-  };
+  static void          delete_enumeration(
+                        device_enumeration *   data,
+                        std::size_t            count);
 
-  static const device_enumeration *
-                       enumerate(std::size_t & size);
+  static device_enumeration *
+                       enumerate(std::size_t & count);
 
 public:
   static const char * const *