diff options
-rw-r--r-- | configure.ac | 32 | ||||
-rw-r--r-- | include/libirecovery.h | 1 | ||||
-rw-r--r-- | src/libirecovery.c | 143 | ||||
-rw-r--r-- | tools/irecovery.c | 8 |
4 files changed, 172 insertions, 12 deletions
diff --git a/configure.ac b/configure.ac index e13c571..1f10bb7 100644 --- a/configure.ac +++ b/configure.ac @@ -59,6 +59,11 @@ case "$host_os" in esac AC_SUBST(LIBIRECOVERYLDFLAGS) +AC_ARG_WITH([dummy], + [AS_HELP_STRING([--with-dummy], [Use no USB driver at all [default=no]. This is only useful if you just want to query the device list by product type or hardware model. All other operations are no-ops or will return IRECV_E_UNSUPPORTED.])], + [], + [with_dummy=no]) + AS_IF([test "x$have_iokit" = "xyes"], [ AC_ARG_WITH([iokit], [AS_HELP_STRING([--with-iokit], [Use IOKit instead of libusb on OS X [default=yes]])], @@ -67,17 +72,22 @@ AS_IF([test "x$have_iokit" = "xyes"], [ ], [] ) -AS_IF([test "x$with_iokit" = "xyes" && test "x$have_iokit" = "xyes"] , [ - AC_DEFINE(HAVE_IOKIT, 1, [Define if we have IOKit]) - USB_BACKEND="IOKit" - ], - [ - PKG_CHECK_MODULES(libusb, libusb-1.0 >= $LIBUSB_VERSION) - USB_BACKEND="libusb `$PKG_CONFIG --modversion libusb-1.0`" - LIBUSB_REQUIRED="libusb-1.0 >= $LIBUSB_VERSION" - AC_SUBST(LIBUSB_REQUIRED) - ] -) +AS_IF([test "x$with_dummy" = "xyes"], [ + AC_DEFINE(USE_DUMMY, 1, [Define if we are using dummy USB driver]) + USB_BACKEND="dummy" +], [ + AS_IF([test "x$with_iokit" = "xyes" && test "x$have_iokit" = "xyes"] , [ + AC_DEFINE(HAVE_IOKIT, 1, [Define if we have IOKit]) + USB_BACKEND="IOKit" + ], + [ + PKG_CHECK_MODULES(libusb, libusb-1.0 >= $LIBUSB_VERSION) + USB_BACKEND="libusb `$PKG_CONFIG --modversion libusb-1.0`" + LIBUSB_REQUIRED="libusb-1.0 >= $LIBUSB_VERSION" + AC_SUBST(LIBUSB_REQUIRED) + ] + ) +]) # Checks for header files. AC_HEADER_STDC diff --git a/include/libirecovery.h b/include/libirecovery.h index 7f9c2b4..73fe6f0 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h @@ -49,6 +49,7 @@ typedef enum { IRECV_E_USB_CONFIGURATION = -9, IRECV_E_PIPE = -10, IRECV_E_TIMEOUT = -11, + IRECV_E_UNSUPPORTED = -254, IRECV_E_UNKNOWN_ERROR = -255 } irecv_error_t; diff --git a/src/libirecovery.c b/src/libirecovery.c index bf96408..945e591 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -31,6 +31,7 @@ #include <unistd.h> #include <sys/stat.h> +#ifndef USE_DUMMY #ifndef WIN32 #ifndef HAVE_IOKIT #include <libusb.h> @@ -52,6 +53,7 @@ #define sleep(n) Sleep(1000 * n) #endif #endif +#endif #ifdef WIN32 #define IRECV_API __declspec( dllexport ) @@ -72,6 +74,7 @@ struct irecv_client_private { int usb_alt_interface; unsigned int mode; struct irecv_device_info device_info; +#ifndef USE_DUMMY #ifndef WIN32 #ifndef HAVE_IOKIT libusb_device_handle* handle; @@ -92,6 +95,7 @@ struct irecv_client_private { irecv_event_cb_t precommand_callback; irecv_event_cb_t postcommand_callback; irecv_event_cb_t disconnected_callback; +#endif }; #define USB_TIMEOUT 10000 @@ -101,11 +105,13 @@ struct irecv_client_private { #define debug(...) if(libirecovery_debug) fprintf(stderr, __VA_ARGS__) static int libirecovery_debug = 0; +#ifndef USE_DUMMY #ifndef WIN32 #ifndef HAVE_IOKIT static libusb_context* libirecovery_context = NULL; #endif #endif +#endif static struct irecv_device irecv_devices[] = { {"iPhone1,1", "m68ap", 0x00, 0x8900 }, @@ -197,6 +203,7 @@ static struct irecv_device irecv_devices[] = { { NULL, NULL, -1, -1 } }; +#ifndef USE_DUMMY static unsigned int dfu_hash_t1[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, @@ -772,16 +779,20 @@ static int check_context(irecv_client_t client) { return IRECV_E_SUCCESS; } +#endif IRECV_API void irecv_init(void) { +#ifndef USE_DUMMY #ifndef WIN32 #ifndef HAVE_IOKIT libusb_init(&libirecovery_context); #endif #endif +#endif } IRECV_API void irecv_exit(void) { +#ifndef USE_DUMMY #ifndef WIN32 #ifndef HAVE_IOKIT if (libirecovery_context != NULL) { @@ -790,8 +801,10 @@ IRECV_API void irecv_exit(void) { } #endif #endif +#endif } +#ifndef USE_DUMMY #ifdef HAVE_IOKIT static int iokit_usb_control_transfer(irecv_client_t client, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, unsigned char *data, uint16_t w_length, unsigned int timeout) { @@ -824,8 +837,12 @@ static int iokit_usb_control_transfer(irecv_client_t client, uint8_t bm_request_ void dummy_callback(void) { } #endif #endif +#endif IRECV_API int irecv_usb_control_transfer(irecv_client_t client, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, unsigned char *data, uint16_t w_length, unsigned int timeout) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else #ifndef WIN32 #ifdef HAVE_IOKIT return iokit_usb_control_transfer(client, bm_request_type, b_request, w_value, w_index, data, w_length, timeout); @@ -873,8 +890,10 @@ IRECV_API int irecv_usb_control_transfer(irecv_client_t client, uint8_t bm_reque return count; #endif +#endif } +#ifndef USE_DUMMY #ifdef HAVE_IOKIT static int iokit_usb_bulk_transfer(irecv_client_t client, unsigned char endpoint, @@ -928,6 +947,7 @@ static int iokit_usb_bulk_transfer(irecv_client_t client, return IRECV_E_USB_INTERFACE; } #endif +#endif IRECV_API int irecv_usb_bulk_transfer(irecv_client_t client, unsigned char endpoint, @@ -935,6 +955,9 @@ IRECV_API int irecv_usb_bulk_transfer(irecv_client_t client, int length, int *transferred, unsigned int timeout) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else int ret; #ifndef WIN32 @@ -956,8 +979,10 @@ IRECV_API int irecv_usb_bulk_transfer(irecv_client_t client, #endif return ret; +#endif } +#ifndef USE_DUMMY #ifdef HAVE_IOKIT static irecv_error_t iokit_usb_open_service(irecv_client_t *pclient, io_service_t service) { @@ -1143,8 +1168,12 @@ UInt16 *pids = all_pids; return iokit_usb_open_service(pclient, ret_service); } #endif +#endif IRECV_API irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, unsigned long long ecid) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if(libirecovery_debug) { irecv_set_debug_level(libirecovery_debug); } @@ -1282,9 +1311,13 @@ IRECV_API irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, unsigned l return ret; #endif +#endif } IRECV_API irecv_error_t irecv_usb_set_configuration(irecv_client_t client, int configuration) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; @@ -1312,8 +1345,10 @@ IRECV_API irecv_error_t irecv_usb_set_configuration(irecv_client_t client, int c #endif return IRECV_E_SUCCESS; +#endif } +#ifndef USE_DUMMY #ifdef HAVE_IOKIT static IOReturn iokit_usb_get_interface(IOUSBDeviceInterface320 **device, uint8_t ifc, io_service_t *usbInterfacep) { @@ -1393,8 +1428,12 @@ static irecv_error_t iokit_usb_set_interface(irecv_client_t client, int usb_inte return IRECV_E_SUCCESS; } #endif +#endif IRECV_API irecv_error_t irecv_usb_set_interface(irecv_client_t client, int usb_interface, int usb_alt_interface) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; @@ -1424,9 +1463,13 @@ IRECV_API irecv_error_t irecv_usb_set_interface(irecv_client_t client, int usb_i client->usb_alt_interface = usb_alt_interface; return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_reset(irecv_client_t client) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; @@ -1453,9 +1496,13 @@ IRECV_API irecv_error_t irecv_reset(irecv_client_t client) { #endif return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_open_with_ecid_and_attempts(irecv_client_t* pclient, unsigned long long ecid, int attempts) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else int i; for (i = 0; i < attempts; i++) { @@ -1472,9 +1519,13 @@ IRECV_API irecv_error_t irecv_open_with_ecid_and_attempts(irecv_client_t* pclien } return IRECV_E_UNABLE_TO_CONNECT; +#endif } IRECV_API irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type, irecv_event_cb_t callback, void* user_data) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else switch(type) { case IRECV_RECEIVED: client->received_callback = callback; @@ -1502,9 +1553,13 @@ IRECV_API irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event } return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else switch(type) { case IRECV_RECEIVED: client->received_callback = NULL; @@ -1532,9 +1587,13 @@ IRECV_API irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_eve } return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_close(irecv_client_t client) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if (client != NULL) { if(client->disconnected_callback != NULL) { irecv_event_t event; @@ -1582,10 +1641,12 @@ IRECV_API irecv_error_t irecv_close(irecv_client_t client) { } return IRECV_E_SUCCESS; +#endif } IRECV_API void irecv_set_debug_level(int level) { libirecovery_debug = level; +#ifndef USE_DUMMY #ifndef WIN32 #ifndef HAVE_IOKIT if(libirecovery_context) { @@ -1593,8 +1654,10 @@ IRECV_API void irecv_set_debug_level(int level) { } #endif #endif +#endif } +#ifndef USE_DUMMY static irecv_error_t irecv_send_command_raw(irecv_client_t client, const char* command) { unsigned int length = strlen(command); if (length >= 0x100) { @@ -1607,8 +1670,12 @@ static irecv_error_t irecv_send_command_raw(irecv_client_t client, const char* c return IRECV_E_SUCCESS; } +#endif IRECV_API irecv_error_t irecv_send_command(irecv_client_t client, const char* command) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else irecv_error_t error = 0; if (check_context(client) != IRECV_E_SUCCESS) @@ -1646,9 +1713,13 @@ IRECV_API irecv_error_t irecv_send_command(irecv_client_t client, const char* co } return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, int dfu_notify_finished) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; @@ -1681,8 +1752,10 @@ IRECV_API irecv_error_t irecv_send_file(irecv_client_t client, const char* filen free(buffer); return error; +#endif } +#ifndef USE_DUMMY static irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) { if (check_context(client) != IRECV_E_SUCCESS) { *status = 0; @@ -1700,8 +1773,12 @@ static irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* statu return IRECV_E_SUCCESS; } +#endif IRECV_API irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, int dfu_notify_finished) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else irecv_error_t error = 0; int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)); @@ -1862,9 +1939,13 @@ IRECV_API irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* } return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_receive(irecv_client_t client) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else char buffer[BUFFER_SIZE]; memset(buffer, '\0', BUFFER_SIZE); @@ -1887,9 +1968,13 @@ IRECV_API irecv_error_t irecv_receive(irecv_client_t client) { } return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_getenv(irecv_client_t client, const char* variable, char** value) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else char command[256]; if (check_context(client) != IRECV_E_SUCCESS) @@ -1923,9 +2008,13 @@ IRECV_API irecv_error_t irecv_getenv(irecv_client_t client, const char* variable *value = response; return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_getret(irecv_client_t client, unsigned int* value) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; @@ -1942,25 +2031,35 @@ IRECV_API irecv_error_t irecv_getret(irecv_client_t client, unsigned int* value) *value = (unsigned int) *response; return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_get_mode(irecv_client_t client, int* mode) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; *mode = client->mode; return IRECV_E_SUCCESS; +#endif } IRECV_API const struct irecv_device_info* irecv_get_device_info(irecv_client_t client) { +#ifdef USE_DUMMY + return NULL; +#else if (check_context(client) != IRECV_E_SUCCESS) return NULL; return &client->device_info; +#endif } +#ifndef USE_DUMMY #ifdef HAVE_IOKIT static void *iokit_limera1n_usb_submit_request(void *argv) { void **args = argv; @@ -1974,8 +2073,12 @@ static void *iokit_limera1n_usb_submit_request(void *argv) { return NULL; } #endif +#endif IRECV_API irecv_error_t irecv_trigger_limera1n_exploit(irecv_client_t client) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; @@ -2020,9 +2123,13 @@ IRECV_API irecv_error_t irecv_trigger_limera1n_exploit(irecv_client_t client) { #endif return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_execute_script(irecv_client_t client, const char* script) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else irecv_error_t error = IRECV_E_SUCCESS; if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; @@ -2048,18 +2155,26 @@ IRECV_API irecv_error_t irecv_execute_script(irecv_client_t client, const char* free(body); return error; +#endif } IRECV_API irecv_error_t irecv_saveenv(irecv_client_t client) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else irecv_error_t error = irecv_send_command_raw(client, "saveenv"); if(error != IRECV_E_SUCCESS) { return error; } return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_setenv(irecv_client_t client, const char* variable, const char* value) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else char command[256]; if (check_context(client) != IRECV_E_SUCCESS) @@ -2077,15 +2192,20 @@ IRECV_API irecv_error_t irecv_setenv(irecv_client_t client, const char* variable } return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_reboot(irecv_client_t client) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else irecv_error_t error = irecv_send_command_raw(client, "reboot"); if(error != IRECV_E_SUCCESS) { return error; } return IRECV_E_SUCCESS; +#endif } IRECV_API const char* irecv_strerror(irecv_error_t error) { @@ -2126,6 +2246,9 @@ IRECV_API const char* irecv_strerror(irecv_error_t error) { case IRECV_E_TIMEOUT: return "Timeout talking to device"; + case IRECV_E_UNSUPPORTED: + return "Operation unsupported by driver"; + default: return "Unknown error"; } @@ -2134,6 +2257,9 @@ IRECV_API const char* irecv_strerror(irecv_error_t error) { } IRECV_API irecv_error_t irecv_reset_counters(irecv_client_t client) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; @@ -2142,9 +2268,13 @@ IRECV_API irecv_error_t irecv_reset_counters(irecv_client_t client) { } return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_recv_buffer(irecv_client_t client, char* buffer, unsigned long length) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)); if (check_context(client) != IRECV_E_SUCCESS) @@ -2184,9 +2314,13 @@ IRECV_API irecv_error_t irecv_recv_buffer(irecv_client_t client, char* buffer, u } return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_error_t irecv_finish_transfer(irecv_client_t client) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else int i = 0; unsigned int status = 0; @@ -2202,6 +2336,7 @@ IRECV_API irecv_error_t irecv_finish_transfer(irecv_client_t client) { irecv_reset(client); return IRECV_E_SUCCESS; +#endif } IRECV_API irecv_device_t irecv_devices_get_all(void) { @@ -2209,6 +2344,9 @@ IRECV_API irecv_device_t irecv_devices_get_all(void) { } IRECV_API irecv_error_t irecv_devices_get_device_by_client(irecv_client_t client, irecv_device_t* device) { +#ifdef USE_DUMMY + return IRECV_E_UNSUPPORTED; +#else int i = 0; *device = NULL; @@ -2225,6 +2363,7 @@ IRECV_API irecv_error_t irecv_devices_get_device_by_client(irecv_client_t client } return IRECV_E_NO_DEVICE; +#endif } IRECV_API irecv_error_t irecv_devices_get_device_by_product_type(const char* product_type, irecv_device_t* device) { @@ -2264,6 +2403,9 @@ IRECV_API irecv_error_t irecv_devices_get_device_by_hardware_model(const char* h } IRECV_API irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause) { +#ifdef USE_DUMMY + return NULL; +#else irecv_error_t error = 0; irecv_client_t new_client = NULL; irecv_event_cb_t progress_callback = client->progress_callback; @@ -2287,4 +2429,5 @@ IRECV_API irecv_client_t irecv_reconnect(irecv_client_t client, int initial_paus new_client->progress_callback = progress_callback; return new_client; +#endif } diff --git a/tools/irecovery.c b/tools/irecovery.c index f250dc5..2db6f4f 100644 --- a/tools/irecovery.c +++ b/tools/irecovery.c @@ -459,12 +459,18 @@ int main(int argc, char* argv[]) { for (i = 0; i <= 5; i++) { debug("Attempting to connect... \n"); - if (irecv_open_with_ecid(&client, ecid) != IRECV_E_SUCCESS) + irecv_error_t err = irecv_open_with_ecid(&client, ecid); + if (err == IRECV_E_UNSUPPORTED) { + fprintf(stderr, "ERROR: %s\n", irecv_strerror(err)); + return -1; + } + else if (err != IRECV_E_SUCCESS) sleep(1); else break; if (i == 5) { + fprintf(stderr, "ERROR: %s\n", irecv_strerror(err)); return -1; } } |