Skip to content

Commit 0a0ad0c

Browse files
skortelanikias
authored andcommitted
win32: Improve irecv_event_handler to make sure events get delivered properly
1 parent 345ac62 commit 0a0ad0c

1 file changed

Lines changed: 43 additions & 7 deletions

File tree

src/libirecovery.c

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2491,9 +2491,12 @@ static void *_irecv_event_handler(void* data)
24912491
{
24922492
struct _irecv_event_handler_info* info = (struct _irecv_event_handler_info*)data;
24932493
#ifdef WIN32
2494+
struct collection newDevices;
24942495
const GUID *guids[] = { &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL };
24952496
int running = 1;
24962497

2498+
collection_init(&newDevices);
2499+
24972500
mutex_lock(&(info->startup_mutex));
24982501
cond_signal(&(info->startup_cond));
24992502
mutex_unlock(&(info->startup_mutex));
@@ -2512,6 +2515,13 @@ static void *_irecv_event_handler(void* data)
25122515
usbDevices = SetupDiGetClassDevs(guids[k], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
25132516
if (!usbDevices) {
25142517
debug("%s: ERROR: SetupDiGetClassDevs failed\n", __func__);
2518+
// cleanup/free newDevices
2519+
FOREACH(struct irecv_win_dev_ctx *win_ctx, &newDevices) {
2520+
free(win_ctx->details);
2521+
collection_remove(&newDevices, win_ctx);
2522+
free(win_ctx);
2523+
} ENDFOREACH
2524+
collection_free(&newDevices);
25152525
return NULL;
25162526
}
25172527

@@ -2564,11 +2574,27 @@ static void *_irecv_event_handler(void* data)
25642574
}
25652575
} ENDFOREACH
25662576
2567-
if (!found) {
2568-
struct irecv_win_dev_ctx win_ctx;
2569-
win_ctx.details = details;
2570-
win_ctx.location = location;
2571-
_irecv_handle_device_add(&win_ctx);
2577+
unsigned int pid = 0;
2578+
if (sscanf(details->DevicePath, "\\\\?\\usb#vid_05ac&pid_%04x", &pid)!= 1) {
2579+
debug("%s: ERROR: failed to parse PID! path: %s\n", __func__, details->DevicePath);
2580+
free(details);
2581+
continue;
2582+
}
2583+
// make sure the current device is actually in the right mode for the given driver interface
2584+
int skip = 0;
2585+
if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE)
2586+
|| (guids[k] == &GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4))
2587+
) {
2588+
skip = 1;
2589+
}
2590+
2591+
if (!found && !skip) {
2592+
// Add device to newDevices list, and deliver the notification later, when removed devices are first handled.
2593+
struct irecv_win_dev_ctx *win_ctx = (struct irecv_win_dev_ctx*)malloc(sizeof(struct irecv_win_dev_ctx));
2594+
win_ctx->details = details;
2595+
win_ctx->location = location;
2596+
collection_add(&newDevices, win_ctx);
2597+
details = NULL;
25722598
}
25732599
free(details);
25742600
}
@@ -2577,19 +2603,29 @@ static void *_irecv_event_handler(void* data)
25772603

25782604
FOREACH(struct irecv_usb_device_info *devinfo, &devices) {
25792605
if (!devinfo->alive) {
2606+
debug("%s: removed ecid: %016" PRIx64 ", location: %d\n",__func__, (uint64_t)devinfo->device_info.ecid, devinfo->location);
25802607
_irecv_handle_device_remove(devinfo);
25812608
}
25822609
} ENDFOREACH
25832610

2611+
// handle newly added devices and remove from local list
2612+
FOREACH(struct irecv_win_dev_ctx *win_ctx, &newDevices) {
2613+
debug("%s: found new: %s, location: %d\n", __func__, win_ctx->details->DevicePath, win_ctx->location);
2614+
_irecv_handle_device_add(win_ctx);
2615+
free(win_ctx->details);
2616+
collection_remove(&newDevices, win_ctx);
2617+
free(win_ctx);
2618+
} ENDFOREACH
2619+
2620+
Sleep(500);
25842621
mutex_lock(&listener_mutex);
25852622
if (collection_count(&listeners) == 0) {
25862623
running = 0;
25872624
}
25882625
mutex_unlock(&listener_mutex);
2589-
2590-
Sleep(500);
25912626
} while (running);
25922627

2628+
collection_free(&newDevices);
25932629
#else /* !WIN32 */
25942630
#ifdef HAVE_IOKIT
25952631
kern_return_t kr;

0 commit comments

Comments
 (0)