From 3da32b7b7cd00ba5dfe9abbe251848665d105c61 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 25 Jan 2018 20:14:35 +0100 Subject: [PATCH] input: split out LinuxInputDeviceManager from InputDeviceManager --- panda/src/device/evdevInputDevice.cxx | 10 +- panda/src/device/evdevInputDevice.h | 9 +- panda/src/device/inputDeviceManager.cxx | 283 +----------------- panda/src/device/inputDeviceManager.h | 3 - panda/src/device/linuxInputDeviceManager.cxx | 294 +++++++++++++++++++ panda/src/device/linuxInputDeviceManager.h | 45 +++ panda/src/device/linuxJoystickDevice.cxx | 9 +- panda/src/device/linuxJoystickDevice.h | 8 +- panda/src/device/p3device_composite1.cxx | 1 + panda/src/x11display/x11GraphicsWindow.cxx | 2 +- 10 files changed, 371 insertions(+), 293 deletions(-) create mode 100644 panda/src/device/linuxInputDeviceManager.cxx create mode 100644 panda/src/device/linuxInputDeviceManager.h diff --git a/panda/src/device/evdevInputDevice.cxx b/panda/src/device/evdevInputDevice.cxx index 6855685084..a4bdc43806 100644 --- a/panda/src/device/evdevInputDevice.cxx +++ b/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 #include @@ -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); + } } } } diff --git a/panda/src/device/evdevInputDevice.h b/panda/src/device/evdevInputDevice.h index 0a6baa058a..8f73d04a20 100644 --- a/panda/src/device/evdevInputDevice.h +++ b/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; diff --git a/panda/src/device/inputDeviceManager.cxx b/panda/src/device/inputDeviceManager.cxx index 31f7f93934..a4ee1c4c8e 100644 --- a/panda/src/device/inputDeviceManager.cxx +++ b/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 -#include -#include -#include -#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 diff --git a/panda/src/device/inputDeviceManager.h b/panda/src/device/inputDeviceManager.h index c6c50a33d9..5f827cd3a9 100644 --- a/panda/src/device/inputDeviceManager.h +++ b/panda/src/device/inputDeviceManager.h @@ -62,9 +62,6 @@ protected: LightMutex _lock; #ifdef PHAVE_LINUX_INPUT_H - int _inotify_fd; - - pvector _evdev_devices; InputDeviceSet _inactive_devices; #endif diff --git a/panda/src/device/linuxInputDeviceManager.cxx b/panda/src/device/linuxInputDeviceManager.cxx new file mode 100644 index 0000000000..61eed54b42 --- /dev/null +++ b/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 +#include +#include +#include + +/** + * 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 diff --git a/panda/src/device/linuxInputDeviceManager.h b/panda/src/device/linuxInputDeviceManager.h new file mode 100644 index 0000000000..fd82efc689 --- /dev/null +++ b/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 _evdev_devices; + + friend class InputDeviceManager; +}; + +#endif // PHAVE_LINUX_INPUT_H + +#endif diff --git a/panda/src/device/linuxJoystickDevice.cxx b/panda/src/device/linuxJoystickDevice.cxx index f510e02f6a..d3fea162bd 100644 --- a/panda/src/device/linuxJoystickDevice.cxx +++ b/panda/src/device/linuxJoystickDevice.cxx @@ -17,6 +17,7 @@ #ifdef PHAVE_LINUX_INPUT_H #include "gamepadButton.h" +#include "linuxInputDeviceManager.h" #include #include @@ -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); + } } } } diff --git a/panda/src/device/linuxJoystickDevice.h b/panda/src/device/linuxJoystickDevice.h index ab97dd5293..fad69730c1 100644 --- a/panda/src/device/linuxJoystickDevice.h +++ b/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; diff --git a/panda/src/device/p3device_composite1.cxx b/panda/src/device/p3device_composite1.cxx index 65a03ccc48..0067579474 100644 --- a/panda/src/device/p3device_composite1.cxx +++ b/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" diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index a0bd1013a4..8e4776e292 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/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()) {