Browse Source

Support gamepads (and other devices) via evdev interface, query axis+button availability

rdb 10 years ago
parent
commit
58ddd77d5e
2 changed files with 56 additions and 5 deletions
  1. 45 5
      panda/src/device/evdevInputDevice.cxx
  2. 11 0
      panda/src/device/inputDevice.cxx

+ 45 - 5
panda/src/device/evdevInputDevice.cxx

@@ -25,6 +25,11 @@
 
 
 #define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)&7)))
 #define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)&7)))
 
 
+static InputDevice::ControlAxis axis_map[] = {
+  InputDevice::C_left_x, InputDevice::C_left_y, InputDevice::C_left_trigger,
+  InputDevice::C_right_x, InputDevice::C_right_y, InputDevice::C_right_trigger
+};
+
 TypeHandle EvdevInputDevice::_type_handle;
 TypeHandle EvdevInputDevice::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -95,12 +100,15 @@ do_poll() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool EvdevInputDevice::
 bool EvdevInputDevice::
 init_device() {
 init_device() {
-  uint8_t evtypes[EV_MAX/8 + 1];
+  nassertr(_fd >= 0, false);
+
+  uint8_t evtypes[(EV_CNT + 7) >> 3];
+  memset(evtypes, 0, sizeof(evtypes));
   char name[256];
   char name[256];
   char uniq[256];
   char uniq[256];
   if (ioctl(_fd, EVIOCGNAME(sizeof(name)), name) < 0 ||
   if (ioctl(_fd, EVIOCGNAME(sizeof(name)), name) < 0 ||
       ioctl(_fd, EVIOCGPHYS(sizeof(uniq)), uniq) < 0 ||
       ioctl(_fd, EVIOCGPHYS(sizeof(uniq)), uniq) < 0 ||
-      ioctl(_fd, EVIOCGBIT(0, EV_MAX), &evtypes) < 0) {
+      ioctl(_fd, EVIOCGBIT(0, sizeof(evtypes)), evtypes) < 0) {
     close(_fd);
     close(_fd);
     _fd = -1;
     _fd = -1;
     _is_connected = false;
     _is_connected = false;
@@ -121,6 +129,35 @@ init_device() {
 
 
   _name = ((string)name) + "." + uniq;
   _name = ((string)name) + "." + uniq;
 
 
+  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));
+
+    int num_bits = ioctl(_fd, EVIOCGBIT(EV_ABS, sizeof(axes)), axes) << 3;
+    for (int i = 0; i < num_bits; ++i) {
+      if (test_bit(i, axes)) {
+        if (i >= 0 && i < 6) {
+          set_control_map(i, axis_map[i]);
+        }
+      }
+    }
+  }
+
+  if (test_bit(EV_KEY, evtypes)) {
+    // Check which buttons are on the device.
+    uint8_t keys[(KEY_CNT + 7) >> 3];
+    memset(keys, 0, sizeof(keys));
+
+    int num_bits = ioctl(_fd, EVIOCGBIT(EV_KEY, sizeof(keys)), keys) << 3;
+    int bi = 0;
+    for (int i = 0; i < num_bits; ++i) {
+      if (test_bit(i, keys)) {
+        set_button_map(bi++, map_button(i));
+      }
+    }
+  }
+
   if (test_bit(EV_REL, evtypes)) {
   if (test_bit(EV_REL, evtypes)) {
     _flags |= IDF_has_pointer;
     _flags |= IDF_has_pointer;
   }
   }
@@ -169,6 +206,7 @@ process_events() {
 
 
   int x = _pointer_data.get_x();
   int x = _pointer_data.get_x();
   int y = _pointer_data.get_y();
   int y = _pointer_data.get_y();
+  bool have_pointer = false;
   double time = ClockObject::get_global_clock()->get_frame_time();
   double time = ClockObject::get_global_clock()->get_frame_time();
   ButtonHandle button;
   ButtonHandle button;
 
 
@@ -180,11 +218,11 @@ process_events() {
     case EV_REL:
     case EV_REL:
       if (events[i].code == REL_X) x += events[i].value;
       if (events[i].code == REL_X) x += events[i].value;
       if (events[i].code == REL_Y) y += events[i].value;
       if (events[i].code == REL_Y) y += events[i].value;
+      have_pointer = true;
       break;
       break;
 
 
     case EV_ABS:
     case EV_ABS:
-      if (events[i].code == ABS_X) x = events[i].value;
-      if (events[i].code == ABS_Y) y = events[i].value;
+      set_control_state(events[i].code, events[i].value / 32767.0);
       break;
       break;
 
 
     case EV_KEY:
     case EV_KEY:
@@ -198,7 +236,9 @@ process_events() {
     }
     }
   }
   }
 
 
-  set_pointer(true, x, y, time);
+  if (have_pointer) {
+    set_pointer(true, x, y, time);
+  }
 
 
   return true;
   return true;
 }
 }

+ 11 - 0
panda/src/device/inputDevice.cxx

@@ -239,6 +239,17 @@ set_control_state(int index, double state) {
     _controls.resize(index + 1, AnalogState());
     _controls.resize(index + 1, AnalogState());
   }
   }
 
 
+  if (device_cat.is_spam()) {
+    device_cat.spam()
+      << "Changed control " << index;
+
+    if (_controls[index]._axis != C_none) {
+      device_cat.spam(false) << " (" << _controls[index]._axis << ")";
+    }
+
+    device_cat.spam(false) << " to " << state << "\n";
+  }
+
   _controls[index]._state = state;
   _controls[index]._state = state;
   _controls[index]._known = true;
   _controls[index]._known = true;
 }
 }