Skip to content

Commit 1b0b6ac

Browse files
authored
hotplug: Add ability to register device connection/disconnection callback (#299)
- initial API; - Windows backend implementation;
1 parent 45a4ba5 commit 1b0b6ac

7 files changed

Lines changed: 559 additions & 3 deletions

File tree

hidapi/hidapi.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,112 @@ extern "C" {
254254
*/
255255
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
256256

257+
/** @brief Callback handle.
258+
259+
Callbacks handles are generated by hid_hotplug_register_callback()
260+
and can be used to deregister callbacks. Callback handles are unique
261+
and it is safe to call hid_hotplug_deregister_callback() on
262+
an already deregistered callback.
263+
264+
@ingroup API
265+
*/
266+
typedef int hid_hotplug_callback_handle;
267+
268+
/**
269+
Hotplug events
270+
271+
@ingroup API
272+
*/
273+
typedef enum {
274+
/** A device has been plugged in and is ready to use */
275+
HID_API_HOTPLUG_EVENT_DEVICE_ARRIVED = (1 << 0),
276+
277+
/** A device has left and is no longer available.
278+
It is the user's responsibility to call hid_close with a disconnected device.
279+
*/
280+
HID_API_HOTPLUG_EVENT_DEVICE_LEFT = (1 << 1)
281+
} hid_hotplug_event;
282+
283+
/**
284+
Hotplug flags
285+
286+
@ingroup API
287+
*/
288+
typedef enum {
289+
/** Arm the callback and fire it for all matching currently attached devices. */
290+
HID_API_HOTPLUG_ENUMERATE = (1 << 0)
291+
} hid_hotplug_flag;
292+
293+
/** @brief Hotplug callback function type. When requesting hotplug event notifications,
294+
you pass a pointer to a callback function of this type.
295+
296+
This callback may be called by an internal event thread and as such it is
297+
recommended the callback do minimal processing before returning.
298+
299+
hidapi will call this function later, when a matching event had happened on
300+
a matching device.
301+
302+
Note that when callbacks are called from hid_hotplug_register_callback()
303+
because of the \ref HID_API_HOTPLUG_ENUMERATE flag, the callback return
304+
value is ignored. In other words, you cannot cause a callback to be
305+
deregistered by returning 1 when it is called from hid_hotplug_register_callback().
306+
307+
@ingroup API
308+
309+
@param callback_handle The hid_hotplug_callback_handle callback handle.
310+
@param device The hid_device_info of device this event occurred on event that occurred.
311+
@param event Event that occurred.
312+
@param user_data User data provided when this callback was registered.
313+
(Optionally NULL).
314+
315+
@returns bool
316+
Whether this callback is finished processing events.
317+
Returning non-zero value will cause this callback to be deregistered.
318+
*/
319+
typedef int (HID_API_CALL *hid_hotplug_callback_fn)(
320+
hid_hotplug_callback_handle callback_handle,
321+
struct hid_device_info *device,
322+
hid_hotplug_event event,
323+
void *user_data);
324+
325+
/** @brief Register a HID hotplug callback function.
326+
327+
If @p vendor_id is set to 0 then any vendor matches.
328+
If @p product_id is set to 0 then any product matches.
329+
If @p vendor_id and @p product_id are both set to 0, then all HID devices will be notified.
330+
331+
@ingroup API
332+
333+
@param vendor_id The Vendor ID (VID) of the types of device to notify about.
334+
@param product_id The Product ID (PID) of the types of device to notify about.
335+
@param events Bitwise or of hotplug events that will trigger this callback.
336+
See \ref hid_hotplug_event.
337+
@param flags Bitwise or of hotplug flags that affect registration.
338+
See \ref hid_hotplug_flag.
339+
@param callback The callback function that will be called on device connection/disconnection.
340+
See \ref hid_hotplug_callback_fn.
341+
@param user_data The user data you wanted to provide to your callback function.
342+
@param callback_handle Pointer to store the handle of the allocated callback
343+
(Optionally NULL).
344+
345+
@returns
346+
This function returns 0 on success or -1 on error.
347+
*/
348+
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);
349+
350+
/** @brief Deregister a callback from a HID hotplug.
351+
352+
This function is safe to call from within a hotplug callback.
353+
354+
@ingroup API
355+
356+
@param callback_handle The handle of the callback to deregister.
357+
358+
@returns
359+
This function returns 0 on success or -1 on error.
360+
*/
361+
int HID_API_EXPORT HID_API_CALL hid_hotplug_deregister_callback(hid_hotplug_callback_handle callback_handle);
362+
257363
/** @brief Open a HID device using a Vendor ID (VID), Product ID
258364
(PID) and optionally a serial number.
259365

hidtest/test.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,34 @@ void print_devices_with_descriptor(struct hid_device_info *cur_dev) {
109109
}
110110
}
111111

112+
int device_callback(
113+
hid_hotplug_callback_handle callback_handle,
114+
struct hid_device_info* device,
115+
hid_hotplug_event event,
116+
void* user_data)
117+
{
118+
(void)user_data;
119+
120+
if (event & HID_API_HOTPLUG_EVENT_DEVICE_ARRIVED)
121+
printf("Handle %d: New device is connected: %s.\n", callback_handle, device->path);
122+
else
123+
printf("Handle %d: Device was disconnected: %s.\n", callback_handle, device->path);
124+
125+
printf("type: %04hx %04hx\n serial_number: %ls", device->vendor_id, device->product_id, device->serial_number);
126+
printf("\n");
127+
printf(" Manufacturer: %ls\n", device->manufacturer_string);
128+
printf(" Product: %ls\n", device->product_string);
129+
printf(" Release: %hx\n", device->release_number);
130+
printf(" Interface: %d\n", device->interface_number);
131+
printf(" Usage (page): 0x%hx (0x%hx)\n", device->usage, device->usage_page);
132+
printf("\n");
133+
134+
//if (device->product_id == 0x0ce6)
135+
// return 1;
136+
137+
return 0;
138+
}
139+
112140
int main(int argc, char* argv[])
113141
{
114142
(void)argc;
@@ -120,6 +148,7 @@ int main(int argc, char* argv[])
120148
wchar_t wstr[MAX_STR];
121149
hid_device *handle;
122150
int i;
151+
hid_hotplug_callback_handle token1, token2;
123152

124153
struct hid_device_info *devs;
125154

@@ -144,6 +173,17 @@ int main(int argc, char* argv[])
144173
print_devices_with_descriptor(devs);
145174
hid_free_enumeration(devs);
146175

176+
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);
177+
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);
178+
179+
while (1)
180+
{
181+
182+
}
183+
184+
hid_hotplug_deregister_callback(token2);
185+
hid_hotplug_deregister_callback(token1);
186+
147187
// Set up the command buffer.
148188
memset(buf,0x00,sizeof(buf));
149189
buf[0] = 0x01;

libusb/hid.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,28 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
863863
}
864864
}
865865

866+
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)
867+
{
868+
/* Stub */
869+
(void)vendor_id;
870+
(void)product_id;
871+
(void)events;
872+
(void)flags;
873+
(void)callback;
874+
(void)user_data;
875+
(void)callback_handle;
876+
877+
return -1;
878+
}
879+
880+
int HID_API_EXPORT HID_API_CALL hid_hotplug_deregister_callback(hid_hotplug_callback_handle callback_handle)
881+
{
882+
/* Stub */
883+
(void)callback_handle;
884+
885+
return -1;
886+
}
887+
866888
hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
867889
{
868890
struct hid_device_info *devs, *cur_dev;

linux/hid.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,28 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
942942
}
943943
}
944944

945+
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)
946+
{
947+
/* Stub */
948+
(void)vendor_id;
949+
(void)product_id;
950+
(void)events;
951+
(void)flags;
952+
(void)callback;
953+
(void)user_data;
954+
(void)callback_handle;
955+
956+
return -1;
957+
}
958+
959+
int HID_API_EXPORT HID_API_CALL hid_hotplug_deregister_callback(hid_hotplug_callback_handle callback_handle)
960+
{
961+
/* Stub */
962+
(void)callback_handle;
963+
964+
return -1;
965+
}
966+
945967
hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
946968
{
947969
struct hid_device_info *devs, *cur_dev;

mac/hid.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,28 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
726726
}
727727
}
728728

729+
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)
730+
{
731+
/* Stub */
732+
(void)vendor_id;
733+
(void)product_id;
734+
(void)events;
735+
(void)flags;
736+
(void)callback;
737+
(void)user_data;
738+
(void)callback_handle;
739+
740+
return -1;
741+
}
742+
743+
int HID_API_EXPORT HID_API_CALL hid_hotplug_deregister_callback(hid_hotplug_callback_handle callback_handle)
744+
{
745+
/* Stub */
746+
(void)callback_handle;
747+
748+
return -1;
749+
}
750+
729751
hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
730752
{
731753
/* This function is identical to the Linux version. Platform independent. */

0 commit comments

Comments
 (0)