Skip to content

Commit

Permalink
darwin: add option to open device in non-exclusive mode (signal11#397)
Browse files Browse the repository at this point in the history
Resolves: signal11#27
Resolves: signal11#344
  • Loading branch information
Youw committed Apr 23, 2022
1 parent 75aafc3 commit 05f0588
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 19 deletions.
53 changes: 34 additions & 19 deletions mac/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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)
{
Expand Down
38 changes: 38 additions & 0 deletions mac/hidapi_darwin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 05f0588

Please sign in to comment.