diff --git a/mac/hid.c b/mac/hid.c index eadd7455..7a458ff9 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -108,8 +108,21 @@ struct input_report { struct input_report *next; }; +static struct hid_api_version api_version = { + .major = HID_API_VERSION_MAJOR, + .minor = HID_API_VERSION_MINOR, + .patch = HID_API_VERSION_PATCH +}; + +/* - Run context - */ +static IOHIDManagerRef hid_mgr = 0x0; +static int is_macos_10_10_or_greater = 0; +static IOOptionBits device_open_options = 0; +/* --- */ + struct hid_device_ { IOHIDDeviceRef device_handle; + IOOptionBits open_options; int blocking; int uses_numbered_reports; int disconnected; @@ -132,6 +145,7 @@ static hid_device *new_hid_device(void) { hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); dev->device_handle = NULL; + dev->open_options = device_open_options; dev->blocking = 1; dev->uses_numbered_reports = 0; dev->disconnected = 0; @@ -184,23 +198,6 @@ static void free_hid_device(hid_device *dev) free(dev); } -static struct hid_api_version api_version = { - .major = HID_API_VERSION_MAJOR, - .minor = HID_API_VERSION_MINOR, - .patch = HID_API_VERSION_PATCH -}; - -static IOHIDManagerRef hid_mgr = 0x0; -static int is_macos_10_10_or_greater = 0; - - -#if 0 -static void register_error(hid_device *dev, const char *op) -{ - -} -#endif - static CFArrayRef get_array_property(IOHIDDeviceRef device, CFStringRef key) { CFTypeRef ref = IOHIDDeviceGetProperty(device, key); @@ -345,6 +342,7 @@ int HID_API_EXPORT hid_init(void) { if (!hid_mgr) { is_macos_10_10_or_greater = (NSAppKitVersionNumber >= 1343); /* NSAppKitVersionNumber10_10 */ + hid_darwin_set_open_exclusive(1); /* Backward compatibility */ return init_hid_manager(); } @@ -830,7 +828,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) } /* Open the IOHIDDevice */ - ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + ret = IOHIDDeviceOpen(dev->device_handle, dev->open_options); if (ret == kIOReturnSuccess) { char str[32]; @@ -1147,7 +1145,7 @@ void HID_API_EXPORT hid_close(hid_device *dev) Not leaking a resource in all tested environments. */ if (is_macos_10_10_or_greater || !dev->disconnected) { - IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + IOHIDDeviceClose(dev->device_handle, dev->open_options); } /* 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 } } +void HID_API_EXPORT_CALL hid_darwin_set_open_exclusive(int open_exclusive) +{ + device_open_options = (open_exclusive == 0) ? kIOHIDOptionsTypeNone : kIOHIDOptionsTypeSeizeDevice; +} + +int HID_API_EXPORT_CALL hid_darwin_get_open_exclusive(void) +{ + return (device_open_options == kIOHIDOptionsTypeSeizeDevice) ? 1 : 0; +} + +int HID_API_EXPORT_CALL hid_darwin_is_device_open_exclusive(hid_device *dev) +{ + if (!dev) + return -1; + + return (dev->open_options == kIOHIDOptionsTypeSeizeDevice) ? 1 : 0; +} HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) { diff --git a/mac/hidapi_darwin.h b/mac/hidapi_darwin.h index cd3331c4..adae9352 100644 --- a/mac/hidapi_darwin.h +++ b/mac/hidapi_darwin.h @@ -43,6 +43,44 @@ extern "C" { */ int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *location_id); + + /** @brief Changes the behavior of all further calls to @ref hid_open or @ref hid_open_path. + + By default on Darwin platform all devices opened by HIDAPI with @ref hid_open or @ref hid_open_path + are opened in exclusive mode (see kIOHIDOptionsTypeSeizeDevice). + + @ingroup API + @param open_exclusive When set to 0 - all further devices will be opened + in non-exclusive mode. Otherwise - all further devices will be opened + in exclusive mode. + + @note During the initialisation by @ref hid_init - this property is set to 1 (TRUE). + This is done to preserve full backward compatibility with previous behavior. + + @note Calling this function before @ref hid_init or after @ref hid_exit has no effect. + */ + void HID_API_EXPORT_CALL hid_darwin_set_open_exclusive(int open_exclusive); + + /** @brief Getter for option set by @ref hid_darwin_set_open_exclusive. + + @ingroup API + @return 1 if all further devices will be opened in exclusive mode. + + @note Value returned by this function before calling to @ref hid_init or after @ref hid_exit + is not reliable. + */ + int HID_API_EXPORT_CALL hid_darwin_get_open_exclusive(void); + + /** @brief Check how the device was opened. + + @ingroup API + @param dev A device to get property from. + + @return 1 if the device is opened in exclusive mode, 0 - opened in non-exclusive, + -1 - if dev is invalid. + */ + int HID_API_EXPORT_CALL hid_darwin_is_device_open_exclusive(hid_device *dev); + #ifdef __cplusplus } #endif