Panda3D
ioKitInputDeviceManager.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file ioKitInputDeviceManager.cxx
10 * @author rdb
11 * @date 2018-02-04
12 */
13
15#include "ioKitInputDevice.h"
16
17#if defined(__APPLE__) && !defined(CPPPARSER)
18
19/**
20 * Initializes the input device manager by scanning which devices are currently
21 * connected and setting up any platform-dependent structures necessary for
22 * listening for future device connect events.
23 */
24IOKitInputDeviceManager::
25IOKitInputDeviceManager() {
26 _hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
27 if (!_hid_manager) {
28 device_cat.error()
29 << "Failed to create an IOHIDManager.\n";
30 return;
31 }
32
33 // The types of devices we're interested in.
34 int page = kHIDPage_GenericDesktop;
35 int usages[] = {kHIDUsage_GD_GamePad,
36 kHIDUsage_GD_Joystick,
37 kHIDUsage_GD_Mouse,
38 kHIDUsage_GD_Keyboard,
39 kHIDUsage_GD_MultiAxisController, 0};
40 int *usage = usages;
41
42 // This giant mess is necessary to create an array of match dictionaries
43 // that will match the devices we're interested in.
44 CFMutableArrayRef match = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
45 nassertv(match);
46 while (*usage) {
47 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
48 CFNumberRef page_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page);
49 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), page_ref);
50 CFRelease(page_ref);
51 CFNumberRef usage_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, usage);
52 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), usage_ref);
53 CFRelease(usage_ref);
54 CFArrayAppendValue(match, dict);
55 CFRelease(dict);
56 ++usage;
57 }
58 IOHIDManagerSetDeviceMatchingMultiple(_hid_manager, match);
59 CFRelease(match);
60
61 IOHIDManagerRegisterDeviceMatchingCallback(_hid_manager, on_match_device, this);
62 IOHIDManagerRegisterDeviceRemovalCallback(_hid_manager, on_remove_device, this);
63 IOHIDManagerScheduleWithRunLoop(_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes);
64 IOHIDManagerOpen(_hid_manager, kIOHIDOptionsTypeNone);
65}
66
67/**
68 * Closes any resources that the device manager was using to listen for events.
69 */
70IOKitInputDeviceManager::
71~IOKitInputDeviceManager() {
72 IOHIDManagerUnscheduleFromRunLoop(_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes);
73 IOHIDManagerClose(_hid_manager, kIOHIDOptionsTypeNone);
74 CFRelease(_hid_manager);
75}
76
77/**
78 * Called by IOKit when an input device matching our filters has been found.
79 */
80void IOKitInputDeviceManager::
81on_match_device(void *ctx, IOReturn result, void *sender, IOHIDDeviceRef device) {
82 IOKitInputDeviceManager *mgr = (IOKitInputDeviceManager *)ctx;
83 nassertv(mgr != nullptr);
84 nassertv(device);
85
86 IOKitInputDevice *input_device = new IOKitInputDevice(device);
87 if (device_cat.is_debug()) {
88 device_cat.debug()
89 << "Discovered input device " << *input_device << "\n";
90 }
91 mgr->add_device(input_device);
92 mgr->_devices_by_hidref[device] = input_device;
93}
94
95/**
96 * Called by IOKit when an input device has disappeared.
97 */
98void IOKitInputDeviceManager::
99on_remove_device(void *ctx, IOReturn result, void *sender, IOHIDDeviceRef device) {
100 IOKitInputDeviceManager *mgr = (IOKitInputDeviceManager *)ctx;
101 nassertv(mgr != nullptr);
102 nassertv(device);
103
104 auto it = mgr->_devices_by_hidref.find(device);
105 nassertv(it != mgr->_devices_by_hidref.end());
106 IOKitInputDevice *input_device = it->second;
107
108 input_device->set_connected(false);
109
110 mgr->_devices_by_hidref.erase(device);
111
112 IOHIDDeviceClose(device, kIOHIDOptionsTypeNone);
113
114 if (device_cat.is_debug()) {
115 device_cat.debug()
116 << "Removed input device " << *input_device << "\n";
117 }
118
119 mgr->remove_device(input_device);
120}
121#endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.