Skip to content

Commit 3e957dd

Browse files
DJm00nk1-801
authored andcommitted
hotplug: Add ability to register device connection/disconnection callback (libusb#299)
- initial API; - Windows backend implementation;
1 parent d0732cd commit 3e957dd

7 files changed

Lines changed: 558 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
@@ -126,6 +126,34 @@ void print_devices_with_descriptor(struct hid_device_info *cur_dev) {
126126
}
127127
}
128128

129+
int device_callback(
130+
hid_hotplug_callback_handle callback_handle,
131+
struct hid_device_info* device,
132+
hid_hotplug_event event,
133+
void* user_data)
134+
{
135+
(void)user_data;
136+
137+
if (event & HID_API_HOTPLUG_EVENT_DEVICE_ARRIVED)
138+
printf("Handle %d: New device is connected: %s.\n", callback_handle, device->path);
139+
else
140+
printf("Handle %d: Device was disconnected: %s.\n", callback_handle, device->path);
141+
142+
printf("type: %04hx %04hx\n serial_number: %ls", device->vendor_id, device->product_id, device->serial_number);
143+
printf("\n");
144+
printf(" Manufacturer: %ls\n", device->manufacturer_string);
145+
printf(" Product: %ls\n", device->product_string);
146+
printf(" Release: %hx\n", device->release_number);
147+
printf(" Interface: %d\n", device->interface_number);
148+
printf(" Usage (page): 0x%hx (0x%hx)\n", device->usage, device->usage_page);
149+
printf("\n");
150+
151+
//if (device->product_id == 0x0ce6)
152+
// return 1;
153+
154+
return 0;
155+
}
156+
129157
int main(int argc, char* argv[])
130158
{
131159
(void)argc;
@@ -137,6 +165,7 @@ int main(int argc, char* argv[])
137165
wchar_t wstr[MAX_STR];
138166
hid_device *handle;
139167
int i;
168+
hid_hotplug_callback_handle token1, token2;
140169

141170
struct hid_device_info *devs;
142171

@@ -161,6 +190,17 @@ int main(int argc, char* argv[])
161190
print_devices_with_descriptor(devs);
162191
hid_free_enumeration(devs);
163192

193+
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);
194+
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);
195+
196+
while (1)
197+
{
198+
199+
}
200+
201+
hid_hotplug_deregister_callback(token2);
202+
hid_hotplug_deregister_callback(token1);
203+
164204
// Set up the command buffer.
165205
memset(buf,0x00,sizeof(buf));
166206
buf[0] = 0x01;

libusb/hid.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,28 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
912912
}
913913
}
914914

915+
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)
916+
{
917+
/* Stub */
918+
(void)vendor_id;
919+
(void)product_id;
920+
(void)events;
921+
(void)flags;
922+
(void)callback;
923+
(void)user_data;
924+
(void)callback_handle;
925+
926+
return -1;
927+
}
928+
929+
int HID_API_EXPORT HID_API_CALL hid_hotplug_deregister_callback(hid_hotplug_callback_handle callback_handle)
930+
{
931+
/* Stub */
932+
(void)callback_handle;
933+
934+
return -1;
935+
}
936+
915937
hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
916938
{
917939
struct hid_device_info *devs, *cur_dev;

linux/hid.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,28 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
10041004
}
10051005
}
10061006

1007+
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)
1008+
{
1009+
/* Stub */
1010+
(void)vendor_id;
1011+
(void)product_id;
1012+
(void)events;
1013+
(void)flags;
1014+
(void)callback;
1015+
(void)user_data;
1016+
(void)callback_handle;
1017+
1018+
return -1;
1019+
}
1020+
1021+
int HID_API_EXPORT HID_API_CALL hid_hotplug_deregister_callback(hid_hotplug_callback_handle callback_handle)
1022+
{
1023+
/* Stub */
1024+
(void)callback_handle;
1025+
1026+
return -1;
1027+
}
1028+
10071029
hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
10081030
{
10091031
struct hid_device_info *devs, *cur_dev;

mac/hid.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,28 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
804804
}
805805
}
806806

807+
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)
808+
{
809+
/* Stub */
810+
(void)vendor_id;
811+
(void)product_id;
812+
(void)events;
813+
(void)flags;
814+
(void)callback;
815+
(void)user_data;
816+
(void)callback_handle;
817+
818+
return -1;
819+
}
820+
821+
int HID_API_EXPORT HID_API_CALL hid_hotplug_deregister_callback(hid_hotplug_callback_handle callback_handle)
822+
{
823+
/* Stub */
824+
(void)callback_handle;
825+
826+
return -1;
827+
}
828+
807829
hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
808830
{
809831
/* This function is identical to the Linux version. Platform independent. */

0 commit comments

Comments
 (0)