Browse Source

Extended device class heuristics

Extended and partly restructured the way how the device class gets set
Added DC_COUNT to the DeviceClass enum to simplify loop checks
fireclawthefox 9 years ago
parent
commit
670efb9e64
2 changed files with 108 additions and 32 deletions
  1. 105 32
      panda/src/device/evdevInputDevice.cxx
  2. 3 0
      panda/src/device/inputDevice.h

+ 105 - 32
panda/src/device/evdevInputDevice.cxx

@@ -227,6 +227,7 @@ init_device() {
   }
   }
 
 
   _name.assign(name);
   _name.assign(name);
+  //cerr << "##### Now initializing device " << name << "\n";
 
 
   struct input_id id;
   struct input_id id;
   if (ioctl(_fd, EVIOCGID, &id) >= 0) {
   if (ioctl(_fd, EVIOCGID, &id) >= 0) {
@@ -237,12 +238,111 @@ init_device() {
   bool all_values_zero = true;
   bool all_values_zero = true;
   bool emulate_dpad = true;
   bool emulate_dpad = true;
 
 
+  bool has_keys = false;
+  bool has_axes = false;
+
+  uint8_t keys[(KEY_CNT + 7) >> 3];
   if (test_bit(EV_KEY, evtypes)) {
   if (test_bit(EV_KEY, evtypes)) {
     // Check which buttons are on the device.
     // Check which buttons are on the device.
-    uint8_t keys[(KEY_CNT + 7) >> 3];
     memset(keys, 0, sizeof(keys));
     memset(keys, 0, sizeof(keys));
     ioctl(_fd, EVIOCGBIT(EV_KEY, sizeof(keys)), keys);
     ioctl(_fd, EVIOCGBIT(EV_KEY, sizeof(keys)), keys);
+    has_keys = true;
+
+    if (test_bit(KEY_A, keys) && test_bit(KEY_Z, keys)) {
+      _flags |= IDF_has_keyboard;
+    }
+  }
+
+  int num_bits = 0;
+  uint8_t axes[(ABS_CNT + 7) >> 3];
+  if (test_bit(EV_ABS, evtypes)) {
+    // Check which axes are on the device.
+    memset(axes, 0, sizeof(axes));
+    num_bits = ioctl(_fd, EVIOCGBIT(EV_ABS, sizeof(axes)), axes) << 3;
+    has_axes = true;
+  }
+
+
+  // Try to detect which type of device we have here
+  int device_scores[DC_COUNT];
+  memset(device_scores, 0, sizeof(device_scores));
+
+  // Test for specific keys
+  if (test_bit(BTN_GAMEPAD, keys)) {
+    device_scores[DC_gamepad] += 5;
+    device_scores[DC_steering_wheel] += 5;
+    device_scores[DC_flight_stick] += 5;
+  }
 
 
+  if (test_bit(ABS_WHEEL, axes) && test_bit(ABS_GAS, axes) && test_bit(ABS_BRAKE, axes)) {
+    device_scores[DC_steering_wheel] += 10;
+  }
+  if (test_bit(BTN_GEAR_DOWN, keys) && test_bit(BTN_GEAR_UP, keys)) {
+    device_scores[DC_steering_wheel] += 10;
+  }
+  if (test_bit(BTN_JOYSTICK, keys)) {
+    device_scores[DC_flight_stick] += 10;
+  }
+  if (test_bit(BTN_MOUSE, keys)) {
+    device_scores[DC_mouse] += 20;
+  }
+  uint8_t unknown_keys[] = {KEY_POWER};
+  for (int i = 0; i < 1; i++) {
+    if (test_bit(unknown_keys[i], keys)) {
+      if (unknown_keys[i] == KEY_POWER) {
+      }
+      device_scores[DC_unknown] += 20;
+    }
+  }
+  if (_flags & IDF_has_keyboard) {
+    device_scores[DC_keyboard] += 20;
+  }
+
+  // Test for specific name tags
+  string lowercase_name = _name;
+  for(int x=0; x<_name.length(); x++) {
+    lowercase_name[x]=tolower(lowercase_name[x]);
+  }
+  if (lowercase_name.find("gamepad") != string::npos) {
+    device_scores[DC_gamepad] += 10;
+  }
+  if (lowercase_name.find("wheel") != string::npos) {
+    device_scores[DC_steering_wheel] += 10;
+  }
+  if (lowercase_name.find("mouse") != string::npos || lowercase_name.find("touchpad") != string::npos) {
+    device_scores[DC_mouse] += 10;
+  }
+  if (lowercase_name.find("keyboard") != string::npos) {
+    device_scores[DC_keyboard] += 10;
+  }
+  // List of lowercase names that occur in unknown devices
+  string unknown_names[] = {"video bus", "power button", "sleep button"};
+  for(int i = 0; i < 3; i++) {
+    if (lowercase_name.find(unknown_names[i]) != string::npos) {
+      device_scores[DC_unknown] += 20;
+    }
+  }
+
+  // Check which device type got the most points
+  bool highscore_found = false;
+  size_t highest_score = 0;
+  while (!highscore_found) {
+    highscore_found = true;
+    for (size_t i = 0; i < DC_COUNT; i++) {
+      if (device_scores[i] > highest_score) {
+        highest_score = device_scores[i];
+        _device_class = (DeviceClass)i;
+        highscore_found = false;
+      }
+    }
+  }
+  //cerr << "Found highscore class " << _device_class << " with this score: " << highest_score << "\n";
+
+  if (_device_class != DC_gamepad) {
+    emulate_dpad = false;
+  }
+
+  if (has_keys) {
     // Also check whether the buttons are currently pressed.
     // Also check whether the buttons are currently pressed.
     uint8_t states[(KEY_CNT + 7) >> 3];
     uint8_t states[(KEY_CNT + 7) >> 3];
     memset(states, 0, sizeof(states));
     memset(states, 0, sizeof(states));
@@ -252,6 +352,7 @@ init_device() {
     for (int i = 0; i < KEY_CNT; ++i) {
     for (int i = 0; i < KEY_CNT; ++i) {
       if (test_bit(i, keys)) {
       if (test_bit(i, keys)) {
         set_button_map(bi, map_button(i));
         set_button_map(bi, map_button(i));
+        //cerr << "Button " << bi << " is mapped by the driver to " << i << "\n";
         if (test_bit(i, states)) {
         if (test_bit(i, states)) {
           _buttons[bi]._state = S_down;
           _buttons[bi]._state = S_down;
           all_values_zero = false;
           all_values_zero = false;
@@ -264,44 +365,15 @@ init_device() {
         ++bi;
         ++bi;
       }
       }
     }
     }
-
-    if (test_bit(KEY_A, keys) && test_bit(KEY_Z, keys)) {
-      _flags |= IDF_has_keyboard;
-    }
-
-    // Check device type.
-    if (test_bit(BTN_GAMEPAD, keys)) {
-      _device_class = DC_gamepad;
-
-    } else if (test_bit(BTN_JOYSTICK, keys)) {
-      _device_class = DC_flight_stick;
-
-    } else if (test_bit(BTN_MOUSE, keys)) {
-      _device_class = DC_mouse;
-
-    } else if (test_bit(BTN_WHEEL, keys)) {
-      _device_class = DC_steering_wheel;
-
-    } else if (_flags & IDF_has_keyboard) {
-      _device_class = DC_keyboard;
-    }
-  }
-
-  if (_device_class != DC_gamepad) {
-    emulate_dpad = false;
   }
   }
 
 
-  if (test_bit(EV_ABS, evtypes)) {
-    // Check which axes are on the device.
-    uint8_t axes[(ABS_CNT + 7) >> 3];
-    memset(axes, 0, sizeof(axes));
-
+  if (has_axes) {
     AxisRange range;
     AxisRange range;
     range._scale = 1.0;
     range._scale = 1.0;
     range._bias = 0.0;
     range._bias = 0.0;
     _axis_ranges.resize(ABS_CNT, range);
     _axis_ranges.resize(ABS_CNT, range);
 
 
-    int num_bits = ioctl(_fd, EVIOCGBIT(EV_ABS, sizeof(axes)), axes) << 3;
+
     for (int i = 0; i < num_bits; ++i) {
     for (int i = 0; i < num_bits; ++i) {
       if (test_bit(i, axes)) {
       if (test_bit(i, axes)) {
         if (i >= ABS_HAT0X) {
         if (i >= ABS_HAT0X) {
@@ -322,6 +394,7 @@ init_device() {
           }
           }
         } else {
         } else {
           set_control_map(i, axis_map[i]);
           set_control_map(i, axis_map[i]);
+          //cerr << "Axis " << axis_map[i] << " is mapped by the driver to " << i << "\n";
         }
         }
 
 
         // Check the initial value and ranges.
         // Check the initial value and ranges.

+ 3 - 0
panda/src/device/inputDevice.h

@@ -77,6 +77,9 @@ PUBLISHED:
 
 
     // Head-mounted display.
     // Head-mounted display.
     DC_hmd,
     DC_hmd,
+
+    // Count of this enum, used for loops
+    DC_COUNT,
   };
   };
 
 
 protected:
 protected: