Skip to content

Commit 9f5a238

Browse files
committed
Introduce a Report Retry timeout for hotplug events
1 parent 19112a2 commit 9f5a238

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

linux/hid.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ static int parse_uevent_info(const char *uevent, unsigned *bus_type,
637637
}
638638

639639

640-
static struct hid_device_info * create_device_info_for_device(struct udev_device *raw_dev)
640+
static struct hid_device_info * create_device_info_for_device(struct udev_device *raw_dev, long report_timeout_msec)
641641
{
642642
struct hid_device_info *root = NULL;
643643
struct hid_device_info *cur_dev = NULL;
@@ -792,8 +792,29 @@ static struct hid_device_info * create_device_info_for_device(struct udev_device
792792

793793
/* Usage Page and Usage */
794794

795-
if (sysfs_path) {
796-
result = get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc);
795+
if (sysfs_path) {
796+
struct timeval tv_start;
797+
struct timezone tz;
798+
long time_diff_usec = -1;
799+
result = -1;
800+
801+
gettimeofday(&tv_start, &tz);
802+
long report_timeout_usec = report_timeout_msec * 1000L;
803+
804+
while(time_diff_usec < report_timeout_usec && result < 0)
805+
{
806+
result = get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc);
807+
808+
struct timeval tv_end;
809+
gettimeofday(&tv_end, &tz);
810+
time_diff_usec = (tv_end.tv_sec - tv_start.tv_sec) * 1000000L + (tv_end.tv_usec - tv_start.tv_usec);
811+
812+
if((result < 0) && (report_timeout_usec > 0L))
813+
{
814+
// Make a short sleep before retrying (1 millisecond is ok)
815+
usleep(1000);
816+
}
817+
}
797818
}
798819
else {
799820
result = -1;
@@ -876,7 +897,7 @@ static struct hid_device_info * create_device_info_for_hid_device(hid_device *de
876897
/* Open a udev device from the dev_t. 'c' means character device. */
877898
udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev);
878899
if (udev_dev) {
879-
root = create_device_info_for_device(udev_dev);
900+
root = create_device_info_for_device(udev_dev, 0);
880901
}
881902

882903
if (!root) {
@@ -1113,7 +1134,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
11131134
if (!raw_dev)
11141135
continue;
11151136

1116-
tmp = create_device_info_for_device(raw_dev);
1137+
tmp = create_device_info_for_device(raw_dev, 0);
11171138
if (tmp) {
11181139
if (cur_dev) {
11191140
cur_dev->next = tmp;
@@ -1237,7 +1258,9 @@ static void* hotplug_thread(void* user_data)
12371258
const char* action = udev_device_get_action(raw_dev);
12381259
if (!strcmp(action, "add")) {
12391260
// We create a list of all usages on this UDEV device
1240-
struct hid_device_info *info = create_device_info_for_device(raw_dev);
1261+
// NOTE: The device may not be ready to work immediately when the event is received
1262+
// We let the device up to 4 seconds to become ready to provide the descriptor
1263+
struct hid_device_info *info = create_device_info_for_device(raw_dev, 4000L);
12411264
struct hid_device_info *info_cur = info;
12421265
while (info_cur) {
12431266
/* For each device, call all matching callbacks */

0 commit comments

Comments
 (0)