Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection callback: merged feature for all platforms #667

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1b0b6ac
hotplug: Add ability to register device connection/disconnection call…
DJm00n May 1, 2023
79a3516
Merge branch 'master' into connection-callback
Youw Mar 11, 2024
4d851df
Hotplug implementation for MacOS (HidManager approach)
k1-801 Nov 28, 2023
5937ba8
Linux Hotplug: Connection-callback implementation for hidraw
k1-801 Nov 21, 2023
c5c2379
Fix typo
k1-801 Nov 28, 2023
9d344eb
Fix some mutex-related errors
k1-801 Dec 1, 2023
ed26429
Fix space
k1-801 Dec 1, 2023
953e1d4
Named constant for handle
k1-801 Dec 1, 2023
7830967
Fix compilation errors
k1-801 Dec 3, 2023
46f6784
Linux Hotplug: Connection callback support for libusb backend (Squash…
k1-801 Nov 20, 2023
a015e6e
Added a mutex for hotplug callback actions (squashed)
k1-801 Nov 21, 2023
c839de5
Remove unused arg warning
k1-801 Mar 11, 2024
147548c
Fix rebase error
k1-801 Mar 11, 2024
f3bc39c
Fix duplicate line
k1-801 Mar 11, 2024
758e966
Make cygwin happy (fix copied from libusb)
k1-801 Mar 11, 2024
5725356
A background thread for libusb was added
k1-801 Mar 12, 2024
3f600b4
Wait for background thread to end
k1-801 Mar 12, 2024
ac3c377
Rewrote the queue
k1-801 Mar 12, 2024
71d6e4f
Wake up the queue thread
k1-801 Mar 12, 2024
6727b7d
Spaces
k1-801 Mar 12, 2024
3fd25f4
Make cygwin happy (fix copied from libusb)
k1-801 Mar 11, 2024
2966ede
Make cygwin happy (fix copied from libusb)
k1-801 Mar 11, 2024
3330fe9
Merge branch 'connection-callback-mac' into connection-callback-merged
k1-801 Mar 13, 2024
545aceb
Merge branch 'connection-callback-libusb' into connection-callback-me…
k1-801 Mar 13, 2024
11650f2
Merge branch 'connection-callback-udev' into connection-callback-merged
k1-801 Mar 13, 2024
975cbfd
netbsd hotplug stubs
k1-801 Mar 14, 2024
4ef94aa
Make cygwin happy (fix copied from libusb)
k1-801 Mar 11, 2024
871bf87
Merge branch 'connection-callback-netbsd' into connection-callback-me…
k1-801 Mar 14, 2024
6618c11
Fix cleanup order
k1-801 Mar 28, 2024
157ffdb
Add a cleanup call in the callback
k1-801 Apr 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions hidapi/hidapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,112 @@ extern "C" {
*/
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);

/** @brief Callback handle.

Callbacks handles are generated by hid_hotplug_register_callback()
and can be used to deregister callbacks. Callback handles are unique
and it is safe to call hid_hotplug_deregister_callback() on
an already deregistered callback.

@ingroup API
*/
typedef int hid_hotplug_callback_handle;

/**
Hotplug events

@ingroup API
*/
typedef enum {
/** A device has been plugged in and is ready to use */
HID_API_HOTPLUG_EVENT_DEVICE_ARRIVED = (1 << 0),

/** A device has left and is no longer available.
It is the user's responsibility to call hid_close with a disconnected device.
*/
HID_API_HOTPLUG_EVENT_DEVICE_LEFT = (1 << 1)
} hid_hotplug_event;

/**
Hotplug flags

@ingroup API
*/
typedef enum {
/** Arm the callback and fire it for all matching currently attached devices. */
HID_API_HOTPLUG_ENUMERATE = (1 << 0)
} hid_hotplug_flag;

/** @brief Hotplug callback function type. When requesting hotplug event notifications,
you pass a pointer to a callback function of this type.

This callback may be called by an internal event thread and as such it is
recommended the callback do minimal processing before returning.

hidapi will call this function later, when a matching event had happened on
a matching device.

Note that when callbacks are called from hid_hotplug_register_callback()
because of the \ref HID_API_HOTPLUG_ENUMERATE flag, the callback return
value is ignored. In other words, you cannot cause a callback to be
deregistered by returning 1 when it is called from hid_hotplug_register_callback().

@ingroup API

@param callback_handle The hid_hotplug_callback_handle callback handle.
@param device The hid_device_info of device this event occurred on event that occurred.
@param event Event that occurred.
@param user_data User data provided when this callback was registered.
(Optionally NULL).

@returns bool
Whether this callback is finished processing events.
Returning non-zero value will cause this callback to be deregistered.
*/
typedef int (HID_API_CALL *hid_hotplug_callback_fn)(
hid_hotplug_callback_handle callback_handle,
struct hid_device_info *device,
hid_hotplug_event event,
void *user_data);

/** @brief Register a HID hotplug callback function.

If @p vendor_id is set to 0 then any vendor matches.
If @p product_id is set to 0 then any product matches.
If @p vendor_id and @p product_id are both set to 0, then all HID devices will be notified.

@ingroup API

@param vendor_id The Vendor ID (VID) of the types of device to notify about.
@param product_id The Product ID (PID) of the types of device to notify about.
@param events Bitwise or of hotplug events that will trigger this callback.
See \ref hid_hotplug_event.
@param flags Bitwise or of hotplug flags that affect registration.
See \ref hid_hotplug_flag.
@param callback The callback function that will be called on device connection/disconnection.
See \ref hid_hotplug_callback_fn.
@param user_data The user data you wanted to provide to your callback function.
@param callback_handle Pointer to store the handle of the allocated callback
(Optionally NULL).

@returns
This function returns 0 on success or -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_hotplug_register_callback(unsigned short vendor_id, unsigned short product_id, int events, int flags, hid_hotplug_callback_fn callback, void *user_data, hid_hotplug_callback_handle *callback_handle);

/** @brief Deregister a callback from a HID hotplug.

This function is safe to call from within a hotplug callback.

@ingroup API

@param callback_handle The handle of the callback to deregister.

@returns
This function returns 0 on success or -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_hotplug_deregister_callback(hid_hotplug_callback_handle callback_handle);

/** @brief Open a HID device using a Vendor ID (VID), Product ID
(PID) and optionally a serial number.

Expand Down
43 changes: 43 additions & 0 deletions hidtest/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,37 @@ void print_devices_with_descriptor(struct hid_device_info *cur_dev) {
}
}

int device_callback(
hid_hotplug_callback_handle callback_handle,
struct hid_device_info* device,
hid_hotplug_event event,
void* user_data)
{
(void)user_data;

if (event & HID_API_HOTPLUG_EVENT_DEVICE_ARRIVED)
printf("Handle %d: New device is connected: %s.\n", callback_handle, device->path);
else
printf("Handle %d: Device was disconnected: %s.\n", callback_handle, device->path);

printf("type: %04hx %04hx\n serial_number: %ls", device->vendor_id, device->product_id, device->serial_number);
printf("\n");
printf(" Manufacturer: %ls\n", device->manufacturer_string);
printf(" Product: %ls\n", device->product_string);
printf(" Release: %hx\n", device->release_number);
printf(" Interface: %d\n", device->interface_number);
printf(" Usage (page): 0x%hx (0x%hx)\n", device->usage, device->usage_page);
printf("\n");

/* Printed data might not show on the screen - force it out */
fflush(stdout);

//if (device->product_id == 0x0ce6)
// return 1;

return 0;
}

int main(int argc, char* argv[])
{
(void)argc;
Expand All @@ -137,6 +168,7 @@ int main(int argc, char* argv[])
wchar_t wstr[MAX_STR];
hid_device *handle;
int i;
hid_hotplug_callback_handle token1, token2;

struct hid_device_info *devs;

Expand All @@ -161,6 +193,17 @@ int main(int argc, char* argv[])
print_devices_with_descriptor(devs);
hid_free_enumeration(devs);

hid_hotplug_register_callback(0, 0, HID_API_HOTPLUG_EVENT_DEVICE_ARRIVED | HID_API_HOTPLUG_EVENT_DEVICE_LEFT, HID_API_HOTPLUG_ENUMERATE, device_callback, NULL, &token1);
hid_hotplug_register_callback(0x054c, 0x0ce6, HID_API_HOTPLUG_EVENT_DEVICE_ARRIVED | HID_API_HOTPLUG_EVENT_DEVICE_LEFT, HID_API_HOTPLUG_ENUMERATE, device_callback, NULL, &token2);

while (1)
{

}

hid_hotplug_deregister_callback(token2);
hid_hotplug_deregister_callback(token1);

// Set up the command buffer.
memset(buf,0x00,sizeof(buf));
buf[0] = 0x01;
Expand Down
Loading