diff options
-rw-r--r-- | src/libirecovery.c | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c index 16330d2..2491b66 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c | |||
@@ -2491,9 +2491,12 @@ static void *_irecv_event_handler(void* data) | |||
2491 | { | 2491 | { |
2492 | struct _irecv_event_handler_info* info = (struct _irecv_event_handler_info*)data; | 2492 | struct _irecv_event_handler_info* info = (struct _irecv_event_handler_info*)data; |
2493 | #ifdef WIN32 | 2493 | #ifdef WIN32 |
2494 | struct collection newDevices; | ||
2494 | const GUID *guids[] = { &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL }; | 2495 | const GUID *guids[] = { &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL }; |
2495 | int running = 1; | 2496 | int running = 1; |
2496 | 2497 | ||
2498 | collection_init(&newDevices); | ||
2499 | |||
2497 | mutex_lock(&(info->startup_mutex)); | 2500 | mutex_lock(&(info->startup_mutex)); |
2498 | cond_signal(&(info->startup_cond)); | 2501 | cond_signal(&(info->startup_cond)); |
2499 | mutex_unlock(&(info->startup_mutex)); | 2502 | mutex_unlock(&(info->startup_mutex)); |
@@ -2512,6 +2515,13 @@ static void *_irecv_event_handler(void* data) | |||
2512 | usbDevices = SetupDiGetClassDevs(guids[k], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); | 2515 | usbDevices = SetupDiGetClassDevs(guids[k], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); |
2513 | if (!usbDevices) { | 2516 | if (!usbDevices) { |
2514 | debug("%s: ERROR: SetupDiGetClassDevs failed\n", __func__); | 2517 | 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); | ||
2515 | return NULL; | 2525 | return NULL; |
2516 | } | 2526 | } |
2517 | 2527 | ||
@@ -2564,11 +2574,27 @@ static void *_irecv_event_handler(void* data) | |||
2564 | } | 2574 | } |
2565 | } ENDFOREACH | 2575 | } ENDFOREACH |
2566 | 2576 | ||
2567 | if (!found) { | 2577 | unsigned int pid = 0; |
2568 | struct irecv_win_dev_ctx win_ctx; | 2578 | if (sscanf(details->DevicePath, "\\\\?\\usb#vid_05ac&pid_%04x", &pid)!= 1) { |
2569 | win_ctx.details = details; | 2579 | debug("%s: ERROR: failed to parse PID! path: %s\n", __func__, details->DevicePath); |
2570 | win_ctx.location = location; | 2580 | free(details); |
2571 | _irecv_handle_device_add(&win_ctx); | 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; | ||
2572 | } | 2598 | } |
2573 | free(details); | 2599 | free(details); |
2574 | } | 2600 | } |
@@ -2577,19 +2603,29 @@ static void *_irecv_event_handler(void* data) | |||
2577 | 2603 | ||
2578 | FOREACH(struct irecv_usb_device_info *devinfo, &devices) { | 2604 | FOREACH(struct irecv_usb_device_info *devinfo, &devices) { |
2579 | if (!devinfo->alive) { | 2605 | if (!devinfo->alive) { |
2606 | debug("%s: removed ecid: %016" PRIx64 ", location: %d\n",__func__, (uint64_t)devinfo->device_info.ecid, devinfo->location); | ||
2580 | _irecv_handle_device_remove(devinfo); | 2607 | _irecv_handle_device_remove(devinfo); |
2581 | } | 2608 | } |
2582 | } ENDFOREACH | 2609 | } ENDFOREACH |
2583 | 2610 | ||
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); | ||
2584 | mutex_lock(&listener_mutex); | 2621 | mutex_lock(&listener_mutex); |
2585 | if (collection_count(&listeners) == 0) { | 2622 | if (collection_count(&listeners) == 0) { |
2586 | running = 0; | 2623 | running = 0; |
2587 | } | 2624 | } |
2588 | mutex_unlock(&listener_mutex); | 2625 | mutex_unlock(&listener_mutex); |
2589 | |||
2590 | Sleep(500); | ||
2591 | } while (running); | 2626 | } while (running); |
2592 | 2627 | ||
2628 | collection_free(&newDevices); | ||
2593 | #else /* !WIN32 */ | 2629 | #else /* !WIN32 */ |
2594 | #ifdef HAVE_IOKIT | 2630 | #ifdef HAVE_IOKIT |
2595 | kern_return_t kr; | 2631 | kern_return_t kr; |