diff options
-rw-r--r-- | src/libirecovery.c | 201 |
1 files changed, 124 insertions, 77 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c index 40fd88f..a85cd97 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c | |||
@@ -1787,27 +1787,94 @@ static irecv_error_t iokit_open_with_ecid(irecv_client_t* pclient, uint64_t ecid | |||
1787 | #endif | 1787 | #endif |
1788 | #endif | 1788 | #endif |
1789 | 1789 | ||
1790 | irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, uint64_t ecid) | 1790 | #ifndef WIN32 |
1791 | { | 1791 | #ifndef HAVE_IOKIT |
1792 | #ifdef USE_DUMMY | 1792 | static irecv_error_t libusb_usb_open_handle_with_descriptor_and_ecid(irecv_client_t *pclient, struct libusb_device_handle *usb_handle, struct libusb_device_descriptor *usb_descriptor, uint64_t ecid){ |
1793 | return IRECV_E_UNSUPPORTED; | 1793 | irecv_error_t ret = IRECV_E_UNABLE_TO_CONNECT; |
1794 | #else | 1794 | irecv_error_t error = IRECV_E_UNABLE_TO_CONNECT; |
1795 | int ret = IRECV_E_UNABLE_TO_CONNECT; | ||
1796 | 1795 | ||
1797 | if (libirecovery_debug) { | 1796 | irecv_client_t client = (irecv_client_t) malloc(sizeof(struct irecv_client_private)); |
1798 | irecv_set_debug_level(libirecovery_debug); | 1797 | if (client == NULL) { |
1798 | libusb_close(usb_handle); | ||
1799 | return IRECV_E_OUT_OF_MEMORY; | ||
1799 | } | 1800 | } |
1800 | #ifndef WIN32 | 1801 | |
1801 | #ifdef HAVE_IOKIT | 1802 | memset(client, '\0', sizeof(struct irecv_client_private)); |
1802 | ret = iokit_open_with_ecid(pclient, ecid); | 1803 | client->usb_interface = 0; |
1803 | #else | 1804 | client->handle = usb_handle; |
1805 | client->mode = usb_descriptor->idProduct; | ||
1806 | |||
1807 | if (client->mode != KIS_PRODUCT_ID) { | ||
1808 | char serial_str[256]; | ||
1809 | memset(serial_str, 0, 256); | ||
1810 | irecv_get_string_descriptor_ascii(client, usb_descriptor->iSerialNumber, (unsigned char*)serial_str, 255); | ||
1811 | irecv_load_device_info_from_iboot_string(client, serial_str); | ||
1812 | } | ||
1813 | |||
1814 | if (ecid != 0 && client->mode != KIS_PRODUCT_ID) { | ||
1815 | if (client->device_info.ecid != ecid) { | ||
1816 | irecv_close(client); | ||
1817 | return IRECV_E_NO_DEVICE; //wrong device | ||
1818 | } | ||
1819 | debug("found device with ECID %016" PRIx64 "\n", (uint64_t)ecid); | ||
1820 | } | ||
1821 | |||
1822 | error = irecv_usb_set_configuration(client, 1); | ||
1823 | if (error != IRECV_E_SUCCESS) { | ||
1824 | irecv_close(client); | ||
1825 | return error; | ||
1826 | } | ||
1827 | |||
1828 | if ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE) && (client->mode != KIS_PRODUCT_ID)) { | ||
1829 | error = irecv_usb_set_interface(client, 0, 0); | ||
1830 | if (client->mode > IRECV_K_RECOVERY_MODE_2) { | ||
1831 | error = irecv_usb_set_interface(client, 1, 1); | ||
1832 | } | ||
1833 | } else { | ||
1834 | error = irecv_usb_set_interface(client, 0, 0); | ||
1835 | } | ||
1836 | |||
1837 | if (error != IRECV_E_SUCCESS) { | ||
1838 | irecv_close(client); | ||
1839 | return error; | ||
1840 | } | ||
1841 | |||
1842 | if (client->mode == KIS_PRODUCT_ID) { | ||
1843 | error = irecv_kis_init(client); | ||
1844 | if (error != IRECV_E_SUCCESS) { | ||
1845 | debug("irecv_kis_init failed, error %d\n", error); | ||
1846 | return error; | ||
1847 | } | ||
1848 | |||
1849 | error = irecv_kis_load_device_info(client); | ||
1850 | if (error != IRECV_E_SUCCESS) { | ||
1851 | debug("irecv_kis_load_device_info failed, error %d\n", error); | ||
1852 | return error; | ||
1853 | } | ||
1854 | if (ecid != 0 && client->device_info.ecid != ecid) { | ||
1855 | irecv_close(client); | ||
1856 | return IRECV_E_NO_DEVICE; //wrong device | ||
1857 | } | ||
1858 | debug("found device with ECID %016" PRIx64 "\n", (uint64_t)ecid); | ||
1859 | } else { | ||
1860 | irecv_copy_nonce_with_tag(client, "NONC", &client->device_info.ap_nonce, &client->device_info.ap_nonce_size); | ||
1861 | irecv_copy_nonce_with_tag(client, "SNON", &client->device_info.sep_nonce, &client->device_info.sep_nonce_size); | ||
1862 | } | ||
1863 | |||
1864 | ret = IRECV_E_SUCCESS; | ||
1865 | *pclient = client; | ||
1866 | return ret; | ||
1867 | } | ||
1868 | |||
1869 | static irecv_error_t libusb_open_with_ecid(irecv_client_t* pclient, uint64_t ecid) | ||
1870 | { | ||
1871 | irecv_error_t ret = IRECV_E_UNABLE_TO_CONNECT; | ||
1804 | int i = 0; | 1872 | int i = 0; |
1805 | struct libusb_device* usb_device = NULL; | 1873 | struct libusb_device* usb_device = NULL; |
1806 | struct libusb_device** usb_device_list = NULL; | 1874 | struct libusb_device** usb_device_list = NULL; |
1807 | struct libusb_device_descriptor usb_descriptor; | 1875 | struct libusb_device_descriptor usb_descriptor; |
1808 | 1876 | ||
1809 | *pclient = NULL; | 1877 | *pclient = NULL; |
1810 | irecv_error_t error = IRECV_E_SUCCESS; | ||
1811 | int usb_device_count = libusb_get_device_list(libirecovery_context, &usb_device_list); | 1878 | int usb_device_count = libusb_get_device_list(libirecovery_context, &usb_device_list); |
1812 | for (i = 0; i < usb_device_count; i++) { | 1879 | for (i = 0; i < usb_device_count; i++) { |
1813 | usb_device = usb_device_list[i]; | 1880 | usb_device = usb_device_list[i]; |
@@ -1819,7 +1886,8 @@ irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, uint64_t ecid) | |||
1819 | usb_descriptor.idProduct == IRECV_K_RECOVERY_MODE_3 || | 1886 | usb_descriptor.idProduct == IRECV_K_RECOVERY_MODE_3 || |
1820 | usb_descriptor.idProduct == IRECV_K_RECOVERY_MODE_4 || | 1887 | usb_descriptor.idProduct == IRECV_K_RECOVERY_MODE_4 || |
1821 | usb_descriptor.idProduct == IRECV_K_WTF_MODE || | 1888 | usb_descriptor.idProduct == IRECV_K_WTF_MODE || |
1822 | usb_descriptor.idProduct == IRECV_K_DFU_MODE) { | 1889 | usb_descriptor.idProduct == IRECV_K_DFU_MODE || |
1890 | usb_descriptor.idProduct == KIS_PRODUCT_ID) { | ||
1823 | 1891 | ||
1824 | if (ecid == IRECV_K_WTF_MODE) { | 1892 | if (ecid == IRECV_K_WTF_MODE) { |
1825 | if (usb_descriptor.idProduct != IRECV_K_WTF_MODE) { | 1893 | if (usb_descriptor.idProduct != IRECV_K_WTF_MODE) { |
@@ -1850,64 +1918,34 @@ irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, uint64_t ecid) | |||
1850 | return IRECV_E_UNABLE_TO_CONNECT; | 1918 | return IRECV_E_UNABLE_TO_CONNECT; |
1851 | } | 1919 | } |
1852 | 1920 | ||
1853 | irecv_client_t client = (irecv_client_t) malloc(sizeof(struct irecv_client_private)); | 1921 | ret = libusb_usb_open_handle_with_descriptor_and_ecid(pclient, usb_handle, &usb_descriptor, ecid); |
1854 | if (client == NULL) { | 1922 | if (ret == IRECV_E_SUCCESS) { |
1855 | libusb_free_device_list(usb_device_list, 1); | 1923 | break; |
1856 | libusb_close(usb_handle); | ||
1857 | return IRECV_E_OUT_OF_MEMORY; | ||
1858 | } | ||
1859 | |||
1860 | memset(client, '\0', sizeof(struct irecv_client_private)); | ||
1861 | client->usb_interface = 0; | ||
1862 | client->handle = usb_handle; | ||
1863 | client->mode = usb_descriptor.idProduct; | ||
1864 | |||
1865 | char serial_str[256]; | ||
1866 | memset(serial_str, 0, 256); | ||
1867 | irecv_get_string_descriptor_ascii(client, usb_descriptor.iSerialNumber, (unsigned char*)serial_str, 255); | ||
1868 | |||
1869 | irecv_load_device_info_from_iboot_string(client, serial_str); | ||
1870 | |||
1871 | irecv_copy_nonce_with_tag(client, "NONC", &client->device_info.ap_nonce, &client->device_info.ap_nonce_size); | ||
1872 | irecv_copy_nonce_with_tag(client, "SNON", &client->device_info.sep_nonce, &client->device_info.sep_nonce_size); | ||
1873 | |||
1874 | if (ecid != 0) { | ||
1875 | if (client->device_info.ecid != ecid) { | ||
1876 | irecv_close(client); | ||
1877 | continue; | ||
1878 | } | ||
1879 | debug("found device with ECID %016" PRIx64 "\n", (uint64_t)ecid); | ||
1880 | } | ||
1881 | |||
1882 | error = irecv_usb_set_configuration(client, 1); | ||
1883 | if (error != IRECV_E_SUCCESS) { | ||
1884 | libusb_free_device_list(usb_device_list, 1); | ||
1885 | irecv_close(client); | ||
1886 | return error; | ||
1887 | } | ||
1888 | |||
1889 | if ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)) { | ||
1890 | error = irecv_usb_set_interface(client, 0, 0); | ||
1891 | if (client->mode > IRECV_K_RECOVERY_MODE_2) { | ||
1892 | error = irecv_usb_set_interface(client, 1, 1); | ||
1893 | } | ||
1894 | } else { | ||
1895 | error = irecv_usb_set_interface(client, 0, 0); | ||
1896 | } | ||
1897 | |||
1898 | if (error != IRECV_E_SUCCESS) { | ||
1899 | libusb_free_device_list(usb_device_list, 1); | ||
1900 | irecv_close(client); | ||
1901 | return error; | ||
1902 | } | 1924 | } |
1903 | |||
1904 | *pclient = client; | ||
1905 | ret = IRECV_E_SUCCESS; | ||
1906 | break; | ||
1907 | } | 1925 | } |
1908 | } | 1926 | } |
1909 | } | 1927 | } |
1910 | libusb_free_device_list(usb_device_list, 1); | 1928 | libusb_free_device_list(usb_device_list, 1); |
1929 | return ret; | ||
1930 | } | ||
1931 | #endif | ||
1932 | #endif | ||
1933 | |||
1934 | irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, uint64_t ecid) | ||
1935 | { | ||
1936 | #ifdef USE_DUMMY | ||
1937 | return IRECV_E_UNSUPPORTED; | ||
1938 | #else | ||
1939 | int ret = IRECV_E_UNABLE_TO_CONNECT; | ||
1940 | |||
1941 | if (libirecovery_debug) { | ||
1942 | irecv_set_debug_level(libirecovery_debug); | ||
1943 | } | ||
1944 | #ifndef WIN32 | ||
1945 | #ifdef HAVE_IOKIT | ||
1946 | ret = iokit_open_with_ecid(pclient, ecid); | ||
1947 | #else | ||
1948 | ret = libusb_open_with_ecid(pclient, ecid); | ||
1911 | #endif | 1949 | #endif |
1912 | #else | 1950 | #else |
1913 | ret = mobiledevice_connect(pclient, ecid); | 1951 | ret = mobiledevice_connect(pclient, ecid); |
@@ -2438,16 +2476,25 @@ static void* _irecv_handle_device_add(void *userdata) | |||
2438 | } | 2476 | } |
2439 | 2477 | ||
2440 | if (product_id == KIS_PRODUCT_ID) { | 2478 | if (product_id == KIS_PRODUCT_ID) { |
2441 | debug("%s: ERROR: KIS currently not supported with this backend!\n", __func__); | 2479 | irecv_client_t client; |
2442 | return NULL; | 2480 | irecv_error_t error = libusb_usb_open_handle_with_descriptor_and_ecid(&client, usb_handle, &devdesc, 0); |
2443 | } | 2481 | if (error != IRECV_E_SUCCESS) { |
2482 | debug("%s: ERROR: could not open KIS device!\n", __func__); | ||
2483 | return NULL; | ||
2484 | } | ||
2444 | 2485 | ||
2445 | libusb_error = libusb_get_string_descriptor_ascii(usb_handle, devdesc.iSerialNumber, (unsigned char*)serial_str, 255); | 2486 | strcpy(serial_str, client->device_info.serial_string); |
2446 | if (libusb_error < 0) { | 2487 | product_id = client->mode; |
2447 | debug("%s: Failed to get string descriptor: %s\n", __func__, libusb_error_name(libusb_error)); | 2488 | |
2448 | return 0; | 2489 | irecv_close(client); |
2490 | } else { | ||
2491 | libusb_error = libusb_get_string_descriptor_ascii(usb_handle, devdesc.iSerialNumber, (unsigned char*)serial_str, 255); | ||
2492 | if (libusb_error < 0) { | ||
2493 | debug("%s: Failed to get string descriptor: %s\n", __func__, libusb_error_name(libusb_error)); | ||
2494 | return 0; | ||
2495 | } | ||
2496 | libusb_close(usb_handle); | ||
2449 | } | 2497 | } |
2450 | libusb_close(usb_handle); | ||
2451 | #endif /* !HAVE_IOKIT */ | 2498 | #endif /* !HAVE_IOKIT */ |
2452 | #endif /* !WIN32 */ | 2499 | #endif /* !WIN32 */ |
2453 | memset(&client_loc, '\0', sizeof(client_loc)); | 2500 | memset(&client_loc, '\0', sizeof(client_loc)); |
@@ -2745,7 +2792,7 @@ static void *_irecv_event_handler(void* data) | |||
2745 | #else /* !HAVE_IOKIT */ | 2792 | #else /* !HAVE_IOKIT */ |
2746 | #ifdef HAVE_LIBUSB_HOTPLUG_API | 2793 | #ifdef HAVE_LIBUSB_HOTPLUG_API |
2747 | static libusb_hotplug_callback_handle usb_hotplug_cb_handle; | 2794 | static libusb_hotplug_callback_handle usb_hotplug_cb_handle; |
2748 | libusb_hotplug_register_callback(irecv_hotplug_ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, APPLE_VENDOR_ID, LIBUSB_HOTPLUG_MATCH_ANY, 0, _irecv_usb_hotplug_cb, NULL, &usb_hotplug_cb_handle); | 2795 | libusb_hotplug_register_callback(irecv_hotplug_ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, APPLE_VENDOR_ID, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, _irecv_usb_hotplug_cb, NULL, &usb_hotplug_cb_handle); |
2749 | int running = 1; | 2796 | int running = 1; |
2750 | 2797 | ||
2751 | mutex_lock(&(info->startup_mutex)); | 2798 | mutex_lock(&(info->startup_mutex)); |
@@ -2969,7 +3016,7 @@ irecv_error_t irecv_close(irecv_client_t client) | |||
2969 | } | 3016 | } |
2970 | #else | 3017 | #else |
2971 | if (client->handle != NULL) { | 3018 | if (client->handle != NULL) { |
2972 | if ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)) { | 3019 | if ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE) && (client->isKIS == 0)) { |
2973 | libusb_release_interface(client->handle, client->usb_interface); | 3020 | libusb_release_interface(client->handle, client->usb_interface); |
2974 | } | 3021 | } |
2975 | libusb_close(client->handle); | 3022 | libusb_close(client->handle); |