Browse Source

input: split out LinuxInputDeviceManager from InputDeviceManager

rdb 8 years ago
parent
commit
3da32b7b7c

+ 6 - 4
panda/src/device/evdevInputDevice.cxx

@@ -18,7 +18,7 @@
 #include "gamepadButton.h"
 #include "keyboardButton.h"
 #include "mouseButton.h"
-#include "inputDeviceManager.h"
+#include "linuxInputDeviceManager.h"
 
 #include <fcntl.h>
 #include <linux/input.h>
@@ -79,7 +79,8 @@ TypeHandle EvdevInputDevice::_type_handle;
  * Creates a new device representing the evdev device with the given index.
  */
 EvdevInputDevice::
-EvdevInputDevice(int index) :
+EvdevInputDevice(LinuxInputDeviceManager *manager, int index) :
+  _manager(manager),
   _index(index),
   _fd(-1),
   _can_write(false),
@@ -203,8 +204,9 @@ do_poll() {
     // If we got events, we are obviously connected.  Mark us so.
     if (!_is_connected) {
       _is_connected = true;
-      InputDeviceManager *mgr = InputDeviceManager::get_global_ptr();
-      mgr->add_device(this);
+      if (_manager != nullptr) {
+        _manager->add_device(this);
+      }
     }
   }
 }

+ 7 - 2
panda/src/device/evdevInputDevice.h

@@ -18,6 +18,8 @@
 
 #ifdef PHAVE_LINUX_INPUT_H
 
+class LinuxInputDeviceManager;
+
 /**
  * This is a type of device that uses the Linux /dev/input/event# API to read
  * data from a raw mouse or other input device.  Unlike the joystick API, the
@@ -25,7 +27,7 @@
  */
 class EXPCL_PANDA_DEVICE EvdevInputDevice : public InputDevice {
 public:
-  EvdevInputDevice(int index);
+  EvdevInputDevice(LinuxInputDeviceManager *manager, int index);
   virtual ~EvdevInputDevice();
 
 private:
@@ -36,8 +38,11 @@ private:
   bool process_events();
 
 private:
-  int _index;
+  LinuxInputDeviceManager *_manager;
+
   int _fd;
+  int _index;
+
   bool _can_write;
   int _ff_id;
   bool _ff_playing;

+ 5 - 278
panda/src/device/inputDeviceManager.cxx

@@ -13,17 +13,10 @@
 
 #include "inputDeviceManager.h"
 #include "ioKitInputDevice.h"
-#include "linuxJoystickDevice.h"
+#include "linuxInputDeviceManager.h"
 #include "winInputDeviceManager.h"
 #include "throw_event.h"
 
-#ifdef PHAVE_LINUX_INPUT_H
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/inotify.h>
-#include <sys/ioctl.h>
-#endif
-
 InputDeviceManager *InputDeviceManager::_global_ptr = NULL;
 
 /**
@@ -31,51 +24,7 @@ InputDeviceManager *InputDeviceManager::_global_ptr = NULL;
  * connected and setting up any platform-dependent structures necessary for
  * listening for future device connect events.
  */
-#ifdef PHAVE_LINUX_INPUT_H
-InputDeviceManager::
-InputDeviceManager() : _inotify_fd(-1) {
-  // Use inotify to watch /dev/input for hotplugging of devices.
-  _inotify_fd = inotify_init1(O_NONBLOCK);
-
-  if (_inotify_fd < 0) {
-    device_cat.error()
-      << "Error initializing inotify: " << strerror(errno) << "\n";
-
-  } else if (inotify_add_watch(_inotify_fd, "/dev/input", IN_CREATE | IN_ATTRIB | IN_DELETE) < 0) {
-    device_cat.error()
-      << "Error adding inotify watch on /dev/input: " << strerror(errno) << "\n";
-  }
-
-  // Scan /dev/input for a list of input devices.
-  DIR *dir = opendir("/dev/input");
-  if (dir) {
-    vector_int indices;
-    dirent *entry = readdir(dir);
-    while (entry != NULL) {
-      int index = -1;
-      if (entry->d_type == DT_CHR && sscanf(entry->d_name, "event%d", &index) == 1) {
-        indices.push_back(index);
-      }
-      entry = readdir(dir);
-    }
-    closedir(dir);
-
-    // We'll want to sort the devices by index, since the order may be
-    // meaningful (eg. for the Xbox wireless receiver).
-    std::sort(indices.begin(), indices.end());
-    _evdev_devices.resize(indices.back() + 1, NULL);
-
-    vector_int::const_iterator it;
-    for (it = indices.begin(); it != indices.end(); ++it) {
-      consider_add_evdev_device(*it);
-    }
-  } else {
-    device_cat.error()
-      << "Error opening directory /dev/input: " << strerror(errno) << "\n";
-    return;
-  }
-}
-#elif defined(__APPLE__)
+#if defined(__APPLE__)
 InputDeviceManager::
 InputDeviceManager() {
   _hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
@@ -128,12 +77,7 @@ InputDeviceManager() : _lock("InputDeviceManager") {
  */
 InputDeviceManager::
 ~InputDeviceManager() {
-#ifdef PHAVE_LINUX_INPUT_H
-  if (_inotify_fd >= 0) {
-    close(_inotify_fd);
-    _inotify_fd = -1;
-  }
-#elif defined(__APPLE__)
+#if defined(__APPLE__)
   IOHIDManagerUnscheduleFromRunLoop(_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes);
   IOHIDManagerClose(_hid_manager, kIOHIDOptionsTypeNone);
   CFRelease(_hid_manager);
@@ -147,129 +91,13 @@ void InputDeviceManager::
 make_global_ptr() {
 #ifdef _WIN32
   _global_ptr = new WinInputDeviceManager;
+#elif defined(PHAVE_LINUX_INPUT_H)
+  _global_ptr = new LinuxInputDeviceManager;
 #else
   _global_ptr = new InputDeviceManager;
 #endif
 }
 
-#ifdef PHAVE_LINUX_INPUT_H
-/**
- * Checks whether the event device with the given index is accessible, and if
- * so, adds it.  Returns the device if it was newly connected.
- *
- * This is the preferred interface for input devices on Linux.
- */
-InputDevice *InputDeviceManager::
-consider_add_evdev_device(int ev_index) {
-  if (ev_index < _evdev_devices.size()) {
-    if (_evdev_devices[ev_index] != NULL) {
-      // We already have this device.  FIXME: probe it and add it to the
-      // list of connected devices?
-      return NULL;
-    }
-  } else {
-    // Make room to store this index.
-    _evdev_devices.resize(ev_index + 1, NULL);
-  }
-
-  // Check if we can directly read the event device.
-  char path[64];
-  sprintf(path, "/dev/input/event%d", ev_index);
-
-  if (access(path, R_OK) == 0) {
-    PT(InputDevice) device = new EvdevInputDevice(ev_index);
-    if (device_cat.is_debug()) {
-      device_cat.debug()
-        << "Discovered evdev input device " << *device << "\n";
-    }
-
-    _evdev_devices[ev_index] = device;
-
-    if (device->is_connected()) {
-      _connected_devices.add_device(MOVE(device));
-    } else {
-      // Wait for activity on the device before it is considered connected.
-      _inactive_devices.add_device(MOVE(device));
-    }
-    return _evdev_devices[ev_index];
-  }
-
-  // Nope.  The permissions haven't been configured to allow it.  Check if this
-  // corresponds to a /dev/input/jsX interface, which has a better chance of
-  // having read permissions set, but doesn't export all of the features
-  // (notably, force feedback).
-
-  // We do this by checking for a js# directory inside the sysfs directory.
-  sprintf(path, "/sys/class/input/event%d/device", ev_index);
-
-  DIR *dir = opendir(path);
-  if (dir == NULL) {
-    if (device_cat.is_debug()) {
-      device_cat.debug()
-        << "Error opening directory " << path << ": " << strerror(errno) << "\n";
-    }
-    return NULL;
-  }
-
-  dirent *entry = readdir(dir);
-  while (entry != NULL) {
-    int js_index = -1;
-    if (sscanf(entry->d_name, "js%d", &js_index) == 1) {
-      // Yes, we fonud a corresponding js device.  Try adding it.
-      closedir(dir);
-
-      InputDevice *device = consider_add_js_device(js_index);
-      if (device != NULL && device_cat.is_warning()) {
-        // This seemed to work.  Display a warning to the user indicating
-        // that they might want to configure udev properly.
-        device_cat.warning()
-          << "/dev/input/event" << ev_index << " is not readable, some "
-             "features will be unavailable.\n";
-      }
-      _evdev_devices[ev_index] = device;
-      return device;
-    }
-    entry = readdir(dir);
-  }
-
-  closedir(dir);
-  return NULL;
-}
-
-/**
- * Checks whether the joystick device with the given index is accessible, and
- * if so, adds it.  Returns the device if it was newly connected.
- *
- * This is only used on Linux as a fallback interface for when an evdev device
- * cannot be accessed.
- */
-InputDevice *InputDeviceManager::
-consider_add_js_device(int js_index) {
-  char path[64];
-  sprintf(path, "/dev/input/js%d", js_index);
-
-  if (access(path, R_OK) == 0) {
-    PT(LinuxJoystickDevice) device = new LinuxJoystickDevice(js_index);
-    if (device_cat.is_debug()) {
-      device_cat.debug()
-        << "Discovered joydev input device " << *device << "\n";
-    }
-    InputDevice *device_p = device.p();
-
-    if (device->is_connected()) {
-      _connected_devices.add_device(MOVE(device));
-    } else {
-      // Wait for activity on the device before it is considered connected.
-      _inactive_devices.add_device(MOVE(device));
-    }
-    return device_p;
-  }
-
-  return NULL;
-}
-
-#endif
-
 /**
  * Description: Returns all currently connected devices.
  */
@@ -348,105 +176,4 @@ remove_device(InputDevice *device) {
  */
 void InputDeviceManager::
 update() {
-#ifdef PHAVE_LINUX_INPUT_H
-  // Check for any devices that may be disconnected and need to be probed in
-  // order to see whether they have been reconnected.
-  InputDeviceSet inactive_devices;
-  {
-    LightMutexHolder holder(_lock);
-    inactive_devices = _inactive_devices;
-  }
-  for (size_t i = 0; i < inactive_devices.size(); ++i) {
-    InputDevice *device = inactive_devices[i];
-    if (device != NULL && !device->is_connected()) {
-      device->poll();
-    }
-  }
-
-  // We use inotify to tell us whether a device was added, removed, or has
-  // changed permissions to allow us to access it.
-  unsigned int avail = 0;
-  ioctl(_inotify_fd, FIONREAD, &avail);
-  if (avail == 0) {
-    return;
-  }
-
-  char buffer[avail];
-  int n_read = read(_inotify_fd, buffer, avail);
-  if (n_read < 0) {
-    if (errno == EAGAIN || errno == EWOULDBLOCK) {
-      // No data available for now.
-
-    } else {
-      device_cat.error() << "read: " << strerror(errno) << "\n";
-    }
-    return;
-  }
-
-  LightMutexHolder holder(_lock);
-
-  // Iterate over the events in the buffer.
-  char *ptr = buffer;
-  char *end = buffer + avail;
-  while (ptr < end) {
-    inotify_event *event = (inotify_event *)ptr;
-
-    string name(event->name);
-
-    if (event->mask & IN_DELETE) {
-      // The device was deleted.  If we have it, remove it.
-
-      int index = -1;
-      if (sscanf(event->name, "event%d", &index) == 1) {
-        // Check if we have this evdev device.  If so, disconnect it.
-        if (index < _evdev_devices.size()) {
-          PT(InputDevice) device = _evdev_devices[index];
-          if (device != NULL) {
-            _evdev_devices[index] = NULL;
-            _inactive_devices.remove_device(device);
-            if (_connected_devices.remove_device(device)) {
-              throw_event("disconnect-device", device.p());
-            }
-
-            if (device_cat.is_debug()) {
-              device_cat.debug()
-                << "Removed input device " << *device << "\n";
-            }
-          }
-        }
-      }
-
-    } else if (event->mask & (IN_CREATE | IN_ATTRIB)) {
-      // The device was created, or it was chmodded to be accessible.  We need
-      // to check for the latter since it seems that the device may get the
-      // IN_CREATE event before the driver gets the permissions set properly.
-
-      int index = -1;
-      if (sscanf(event->name, "event%d", &index) == 1) {
-        InputDevice *device = consider_add_evdev_device(index);
-        if (device != NULL && device->is_connected()) {
-          throw_event("connect-device", device);
-        }
-      }
-    }
-
-    ptr += sizeof(inotify_event) + event->len;
-  }
-#endif
 }
-
-#if defined(__APPLE__) && !defined(CPPPARSER)
-void InputDeviceManager::
-on_match_device(void *ctx, IOReturn result, void *sender, IOHIDDeviceRef device) {
-  InputDeviceManager *mgr = (InputDeviceManager *)ctx;
-  nassertv(mgr != nullptr);
-  nassertv(device);
-
-  PT(InputDevice) input_device = new IOKitInputDevice(device);
-  if (device_cat.is_debug()) {
-    device_cat.debug()
-      << "Discovered input device " << *input_device << "\n";
-  }
-  mgr->add_device(input_device);
-}
-#endif

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

@@ -62,9 +62,6 @@ protected:
   LightMutex _lock;
 
 #ifdef PHAVE_LINUX_INPUT_H
-  int _inotify_fd;
-
-  pvector<InputDevice *> _evdev_devices;
   InputDeviceSet _inactive_devices;
 #endif
 

+ 294 - 0
panda/src/device/linuxInputDeviceManager.cxx

@@ -0,0 +1,294 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file linuxInputDeviceManager.cxx
+ * @author rdb
+ * @date 2018-01-25
+ */
+
+#include "inputDeviceManager.h"
+#include "throw_event.h"
+
+#ifdef PHAVE_LINUX_INPUT_H
+
+#include "evdevInputDevice.h"
+#include "linuxJoystickDevice.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/inotify.h>
+#include <sys/ioctl.h>
+
+/**
+ * Initializes the device manager by scanning which devices are currently
+ * connected and setting up any platform-dependent structures necessary for
+ * listening for future device connect events.
+ */
+LinuxInputDeviceManager::
+LinuxInputDeviceManager() {
+  // Use inotify to watch /dev/input for hotplugging of devices.
+  _inotify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+
+  if (_inotify_fd < 0) {
+    device_cat.error()
+      << "Error initializing inotify: " << strerror(errno) << "\n";
+
+  } else if (inotify_add_watch(_inotify_fd, "/dev/input", IN_CREATE | IN_ATTRIB | IN_DELETE) < 0) {
+    device_cat.error()
+      << "Error adding inotify watch on /dev/input: " << strerror(errno) << "\n";
+  }
+
+  // Scan /dev/input for a list of input devices.
+  DIR *dir = opendir("/dev/input");
+  if (dir) {
+    vector_int indices;
+    dirent *entry = readdir(dir);
+    while (entry != nullptr) {
+      int index = -1;
+      if (entry->d_type == DT_CHR && sscanf(entry->d_name, "event%d", &index) == 1) {
+        indices.push_back(index);
+      }
+      entry = readdir(dir);
+    }
+    closedir(dir);
+
+    // We'll want to sort the devices by index, since the order may be
+    // meaningful (eg. for the Xbox wireless receiver).
+    std::sort(indices.begin(), indices.end());
+    _evdev_devices.resize(indices.back() + 1, nullptr);
+
+    vector_int::const_iterator it;
+    for (it = indices.begin(); it != indices.end(); ++it) {
+      consider_add_evdev_device(*it);
+    }
+  } else {
+    device_cat.error()
+      << "Error opening directory /dev/input: " << strerror(errno) << "\n";
+    return;
+  }
+}
+
+/**
+ * Closes any resources that the device manager was using to listen for events.
+ */
+LinuxInputDeviceManager::
+~LinuxInputDeviceManager() {
+  if (_inotify_fd >= 0) {
+    close(_inotify_fd);
+    _inotify_fd = -1;
+  }
+}
+
+/**
+ * Checks whether the event device with the given index is accessible, and if
+ * so, adds it.  Returns the device if it was newly connected.
+ *
+ * This is the preferred interface for input devices on Linux.
+ */
+InputDevice *LinuxInputDeviceManager::
+consider_add_evdev_device(int ev_index) {
+  if (ev_index < _evdev_devices.size()) {
+    if (_evdev_devices[ev_index] != nullptr) {
+      // We already have this device.  FIXME: probe it and add it to the
+      // list of connected devices?
+      return nullptr;
+    }
+  } else {
+    // Make room to store this index.
+    _evdev_devices.resize(ev_index + 1, nullptr);
+  }
+
+  // Check if we can directly read the event device.
+  char path[64];
+  sprintf(path, "/dev/input/event%d", ev_index);
+
+  if (access(path, R_OK) == 0) {
+    PT(InputDevice) device = new EvdevInputDevice(this, ev_index);
+    if (device_cat.is_debug()) {
+      device_cat.debug()
+        << "Discovered evdev input device " << *device << "\n";
+    }
+
+    _evdev_devices[ev_index] = device;
+
+    if (device->is_connected()) {
+      _connected_devices.add_device(MOVE(device));
+    } else {
+      // Wait for activity on the device before it is considered connected.
+      _inactive_devices.add_device(MOVE(device));
+    }
+    return _evdev_devices[ev_index];
+  }
+
+  // Nope.  The permissions haven't been configured to allow it.  Check if this
+  // corresponds to a /dev/input/jsX interface, which has a better chance of
+  // having read permissions set, but doesn't export all of the features
+  // (notably, force feedback).
+
+  // We do this by checking for a js# directory inside the sysfs directory.
+  sprintf(path, "/sys/class/input/event%d/device", ev_index);
+
+  DIR *dir = opendir(path);
+  if (dir == nullptr) {
+    if (device_cat.is_debug()) {
+      device_cat.debug()
+        << "Error opening directory " << path << ": " << strerror(errno) << "\n";
+    }
+    return nullptr;
+  }
+
+  dirent *entry = readdir(dir);
+  while (entry != nullptr) {
+    int js_index = -1;
+    if (sscanf(entry->d_name, "js%d", &js_index) == 1) {
+      // Yes, we fonud a corresponding js device.  Try adding it.
+      closedir(dir);
+
+      InputDevice *device = consider_add_js_device(js_index);
+      if (device != nullptr && device_cat.is_warning()) {
+        // This seemed to work.  Display a warning to the user indicating
+        // that they might want to configure udev properly.
+        device_cat.warning()
+          << "/dev/input/event" << ev_index << " is not readable, some "
+             "features will be unavailable.\n";
+      }
+      _evdev_devices[ev_index] = device;
+      return device;
+    }
+    entry = readdir(dir);
+  }
+
+  closedir(dir);
+  return nullptr;
+}
+
+/**
+ * Checks whether the joystick device with the given index is accessible, and
+ * if so, adds it.  Returns the device if it was newly connected.
+ *
+ * This is only used on Linux as a fallback interface for when an evdev device
+ * cannot be accessed.
+ */
+InputDevice *LinuxInputDeviceManager::
+consider_add_js_device(int js_index) {
+  char path[64];
+  sprintf(path, "/dev/input/js%d", js_index);
+
+  if (access(path, R_OK) == 0) {
+    PT(LinuxJoystickDevice) device = new LinuxJoystickDevice(this, js_index);
+    if (device_cat.is_debug()) {
+      device_cat.debug()
+        << "Discovered joydev input device " << *device << "\n";
+    }
+    InputDevice *device_p = device.p();
+
+    if (device->is_connected()) {
+      _connected_devices.add_device(MOVE(device));
+    } else {
+      // Wait for activity on the device before it is considered connected.
+      _inactive_devices.add_device(MOVE(device));
+    }
+    return device_p;
+  }
+
+  return nullptr;
+}
+
+/**
+ * Polls the system to see if there are any new devices.  In some
+ * implementations this is a no-op.
+ */
+void LinuxInputDeviceManager::
+update() {
+  // Check for any devices that may be disconnected and need to be probed in
+  // order to see whether they have been reconnected.
+  InputDeviceSet inactive_devices;
+  {
+    LightMutexHolder holder(_lock);
+    inactive_devices = _inactive_devices;
+  }
+  for (size_t i = 0; i < inactive_devices.size(); ++i) {
+    InputDevice *device = inactive_devices[i];
+    if (device != nullptr && !device->is_connected()) {
+      device->poll();
+    }
+  }
+
+  // We use inotify to tell us whether a device was added, removed, or has
+  // changed permissions to allow us to access it.
+  unsigned int avail = 0;
+  ioctl(_inotify_fd, FIONREAD, &avail);
+  if (avail == 0) {
+    return;
+  }
+
+  char buffer[avail];
+  int n_read = read(_inotify_fd, buffer, avail);
+  if (n_read < 0) {
+    if (errno == EAGAIN || errno == EWOULDBLOCK) {
+      // No data available for now.
+
+    } else {
+      device_cat.error() << "read: " << strerror(errno) << "\n";
+    }
+    return;
+  }
+
+  LightMutexHolder holder(_lock);
+
+  // Iterate over the events in the buffer.
+  char *ptr = buffer;
+  char *end = buffer + avail;
+  while (ptr < end) {
+    inotify_event *event = (inotify_event *)ptr;
+
+    string name(event->name);
+
+    if (event->mask & IN_DELETE) {
+      // The device was deleted.  If we have it, remove it.
+
+      int index = -1;
+      if (sscanf(event->name, "event%d", &index) == 1) {
+        // Check if we have this evdev device.  If so, disconnect it.
+        if (index < _evdev_devices.size()) {
+          PT(InputDevice) device = _evdev_devices[index];
+          if (device != nullptr) {
+            device->set_connected(false);
+            _evdev_devices[index] = nullptr;
+            _inactive_devices.remove_device(device);
+            if (_connected_devices.remove_device(device)) {
+              throw_event("disconnect-device", device.p());
+            }
+
+            if (device_cat.is_debug()) {
+              device_cat.debug()
+                << "Removed input device " << *device << "\n";
+            }
+          }
+        }
+      }
+
+    } else if (event->mask & (IN_CREATE | IN_ATTRIB)) {
+      // The device was created, or it was chmodded to be accessible.  We need
+      // to check for the latter since it seems that the device may get the
+      // IN_CREATE event before the driver gets the permissions set properly.
+
+      int index = -1;
+      if (sscanf(event->name, "event%d", &index) == 1) {
+        InputDevice *device = consider_add_evdev_device(index);
+        if (device != nullptr && device->is_connected()) {
+          throw_event("connect-device", device);
+        }
+      }
+    }
+
+    ptr += sizeof(inotify_event) + event->len;
+  }
+}
+
+#endif  // PHAVE_LINUX_INPUT_H

+ 45 - 0
panda/src/device/linuxInputDeviceManager.h

@@ -0,0 +1,45 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file linuxInputDeviceManager.h
+ * @author rdb
+ * @date 2018-01-25
+ */
+
+#ifndef LINUXINPUTDEVICEMANAGER_H
+#define LINUXINPUTDEVICEMANAGER_H
+
+#include "inputDeviceManager.h"
+
+#ifdef PHAVE_LINUX_INPUT_H
+
+/**
+ * This class keeps track of all the devices on a system, and sends out events
+ * when a device has been hot-plugged.
+ */
+class EXPCL_PANDA_DEVICE LinuxInputDeviceManager FINAL : public InputDeviceManager {
+private:
+  LinuxInputDeviceManager();
+  ~LinuxInputDeviceManager();
+
+  InputDevice *consider_add_evdev_device(int index);
+  InputDevice *consider_add_js_device(int index);
+
+  virtual void update();
+
+protected:
+  int _inotify_fd;
+
+  pvector<InputDevice *> _evdev_devices;
+
+  friend class InputDeviceManager;
+};
+
+#endif  // PHAVE_LINUX_INPUT_H
+
+#endif

+ 6 - 3
panda/src/device/linuxJoystickDevice.cxx

@@ -17,6 +17,7 @@
 #ifdef PHAVE_LINUX_INPUT_H
 
 #include "gamepadButton.h"
+#include "linuxInputDeviceManager.h"
 
 #include <fcntl.h>
 #include <linux/joystick.h>
@@ -27,7 +28,8 @@ TypeHandle LinuxJoystickDevice::_type_handle;
  * Creates a new device using the Linux joystick device with the given index.
  */
 LinuxJoystickDevice::
-LinuxJoystickDevice(int index) :
+LinuxJoystickDevice(LinuxInputDeviceManager *manager, int index) :
+  _manager(manager),
   _fd(-1),
   _index(index),
   _dpad_x_axis(-1),
@@ -79,8 +81,9 @@ do_poll() {
     // If we got events, we are obviously connected.  Mark us so.
     if (!_is_connected) {
       _is_connected = true;
-      InputDeviceManager *mgr = InputDeviceManager::get_global_ptr();
-      mgr->add_device(this);
+      if (_manager != nullptr) {
+        _manager->add_device(this);
+      }
     }
   }
 }

+ 6 - 2
panda/src/device/linuxJoystickDevice.h

@@ -18,13 +18,15 @@
 
 #ifdef PHAVE_LINUX_INPUT_H
 
+class LinuxInputDeviceManager;
+
 /**
  * This is a type of device that uses the Linux /dev/input/js# API to read
  * data from a game controller.
  */
 class EXPCL_PANDA_DEVICE LinuxJoystickDevice : public InputDevice {
-public:
-  LinuxJoystickDevice(int index);
+PUBLISHED:
+  LinuxJoystickDevice(LinuxInputDeviceManager *manager, int index);
   virtual ~LinuxJoystickDevice();
 
   bool check_events() const;
@@ -36,6 +38,8 @@ private:
   bool process_events();
 
 private:
+  LinuxInputDeviceManager *_manager;
+
   int _fd;
   int _index;
 

+ 1 - 0
panda/src/device/p3device_composite1.cxx

@@ -11,6 +11,7 @@
 #include "inputDeviceNode.cxx"
 #include "inputDeviceSet.cxx"
 #include "ioKitInputDevice.cxx"
+#include "linuxInputDeviceManager.cxx"
 #include "linuxJoystickDevice.cxx"
 #include "winInputDeviceManager.cxx"
 #include "winRawInputDevice.cxx"

+ 1 - 1
panda/src/x11display/x11GraphicsWindow.cxx

@@ -1245,7 +1245,7 @@ open_raw_mice() {
     string fn = fnb.str();
     int fd = open(fn.c_str(), O_RDONLY | O_NONBLOCK, 0);
     if (fd >= 0) {
-      EvdevInputDevice *device = new EvdevInputDevice(fd);
+      EvdevInputDevice *device = new EvdevInputDevice(nullptr, fd);
       nassertd(device != NULL) continue;
 
       if (device->has_pointer()) {