Skip to content

Commit 05f0588

Browse files
authored
darwin: add option to open device in non-exclusive mode (signal11#397)
Resolves: signal11#27 Resolves: signal11#344
1 parent 75aafc3 commit 05f0588

File tree

2 files changed

+72
-19
lines changed

2 files changed

+72
-19
lines changed

mac/hid.c

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,21 @@ struct input_report {
108108
struct input_report *next;
109109
};
110110

111+
static struct hid_api_version api_version = {
112+
.major = HID_API_VERSION_MAJOR,
113+
.minor = HID_API_VERSION_MINOR,
114+
.patch = HID_API_VERSION_PATCH
115+
};
116+
117+
/* - Run context - */
118+
static IOHIDManagerRef hid_mgr = 0x0;
119+
static int is_macos_10_10_or_greater = 0;
120+
static IOOptionBits device_open_options = 0;
121+
/* --- */
122+
111123
struct hid_device_ {
112124
IOHIDDeviceRef device_handle;
125+
IOOptionBits open_options;
113126
int blocking;
114127
int uses_numbered_reports;
115128
int disconnected;
@@ -132,6 +145,7 @@ static hid_device *new_hid_device(void)
132145
{
133146
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
134147
dev->device_handle = NULL;
148+
dev->open_options = device_open_options;
135149
dev->blocking = 1;
136150
dev->uses_numbered_reports = 0;
137151
dev->disconnected = 0;
@@ -184,23 +198,6 @@ static void free_hid_device(hid_device *dev)
184198
free(dev);
185199
}
186200

187-
static struct hid_api_version api_version = {
188-
.major = HID_API_VERSION_MAJOR,
189-
.minor = HID_API_VERSION_MINOR,
190-
.patch = HID_API_VERSION_PATCH
191-
};
192-
193-
static IOHIDManagerRef hid_mgr = 0x0;
194-
static int is_macos_10_10_or_greater = 0;
195-
196-
197-
#if 0
198-
static void register_error(hid_device *dev, const char *op)
199-
{
200-
201-
}
202-
#endif
203-
204201
static CFArrayRef get_array_property(IOHIDDeviceRef device, CFStringRef key)
205202
{
206203
CFTypeRef ref = IOHIDDeviceGetProperty(device, key);
@@ -345,6 +342,7 @@ int HID_API_EXPORT hid_init(void)
345342
{
346343
if (!hid_mgr) {
347344
is_macos_10_10_or_greater = (NSAppKitVersionNumber >= 1343); /* NSAppKitVersionNumber10_10 */
345+
hid_darwin_set_open_exclusive(1); /* Backward compatibility */
348346
return init_hid_manager();
349347
}
350348

@@ -830,7 +828,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
830828
}
831829

832830
/* Open the IOHIDDevice */
833-
ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
831+
ret = IOHIDDeviceOpen(dev->device_handle, dev->open_options);
834832
if (ret == kIOReturnSuccess) {
835833
char str[32];
836834

@@ -1147,7 +1145,7 @@ void HID_API_EXPORT hid_close(hid_device *dev)
11471145
Not leaking a resource in all tested environments.
11481146
*/
11491147
if (is_macos_10_10_or_greater || !dev->disconnected) {
1150-
IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
1148+
IOHIDDeviceClose(dev->device_handle, dev->open_options);
11511149
}
11521150

11531151
/* Clear out the queue of received reports. */
@@ -1199,6 +1197,23 @@ int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *lo
11991197
}
12001198
}
12011199

1200+
void HID_API_EXPORT_CALL hid_darwin_set_open_exclusive(int open_exclusive)
1201+
{
1202+
device_open_options = (open_exclusive == 0) ? kIOHIDOptionsTypeNone : kIOHIDOptionsTypeSeizeDevice;
1203+
}
1204+
1205+
int HID_API_EXPORT_CALL hid_darwin_get_open_exclusive(void)
1206+
{
1207+
return (device_open_options == kIOHIDOptionsTypeSeizeDevice) ? 1 : 0;
1208+
}
1209+
1210+
int HID_API_EXPORT_CALL hid_darwin_is_device_open_exclusive(hid_device *dev)
1211+
{
1212+
if (!dev)
1213+
return -1;
1214+
1215+
return (dev->open_options == kIOHIDOptionsTypeSeizeDevice) ? 1 : 0;
1216+
}
12021217

12031218
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
12041219
{

mac/hidapi_darwin.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,44 @@ extern "C" {
4343
*/
4444
int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *location_id);
4545

46+
47+
/** @brief Changes the behavior of all further calls to @ref hid_open or @ref hid_open_path.
48+
49+
By default on Darwin platform all devices opened by HIDAPI with @ref hid_open or @ref hid_open_path
50+
are opened in exclusive mode (see kIOHIDOptionsTypeSeizeDevice).
51+
52+
@ingroup API
53+
@param open_exclusive When set to 0 - all further devices will be opened
54+
in non-exclusive mode. Otherwise - all further devices will be opened
55+
in exclusive mode.
56+
57+
@note During the initialisation by @ref hid_init - this property is set to 1 (TRUE).
58+
This is done to preserve full backward compatibility with previous behavior.
59+
60+
@note Calling this function before @ref hid_init or after @ref hid_exit has no effect.
61+
*/
62+
void HID_API_EXPORT_CALL hid_darwin_set_open_exclusive(int open_exclusive);
63+
64+
/** @brief Getter for option set by @ref hid_darwin_set_open_exclusive.
65+
66+
@ingroup API
67+
@return 1 if all further devices will be opened in exclusive mode.
68+
69+
@note Value returned by this function before calling to @ref hid_init or after @ref hid_exit
70+
is not reliable.
71+
*/
72+
int HID_API_EXPORT_CALL hid_darwin_get_open_exclusive(void);
73+
74+
/** @brief Check how the device was opened.
75+
76+
@ingroup API
77+
@param dev A device to get property from.
78+
79+
@return 1 if the device is opened in exclusive mode, 0 - opened in non-exclusive,
80+
-1 - if dev is invalid.
81+
*/
82+
int HID_API_EXPORT_CALL hid_darwin_is_device_open_exclusive(hid_device *dev);
83+
4684
#ifdef __cplusplus
4785
}
4886
#endif

0 commit comments

Comments
 (0)