diff options
-rw-r--r-- | include/libirecovery.h | 35 | ||||
-rw-r--r-- | src/libirecovery.c | 115 |
2 files changed, 82 insertions, 68 deletions
diff --git a/include/libirecovery.h b/include/libirecovery.h index 9d30497..9848655 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h @@ -18,29 +18,29 @@ #include <libusb-1.0/libusb.h> -typedef enum { - IRECV_E_SUCCESS = 0, - IRECV_E_NO_DEVICE = -1, - IRECV_E_OUT_OF_MEMORY = -2, - IRECV_E_UNABLE_TO_CONNECT = -3, - IRECV_E_INVALID_INPUT = -4, - IRECV_E_UNKNOWN = -5, - IRECV_E_FILE_NOT_FOUND = -6, - IRECV_E_USB_UPLOAD = -7, - IRECV_E_USB_STATUS = -8, - IRECV_E_USB_INTERFACE = -9, - IRECV_E_USB_CONFIGURATION = -10 -} irecv_error_t; - #define APPLE_VENDOR_ID 0x05AC -typedef enum { +enum { kRecoveryMode1 = 0x1280, kRecoveryMode2 = 0x1281, kRecoveryMode3 = 0x1282, kRecoveryMode4 = 0x1283, kDfuMode = 0x1227 -} irecv_mode_t; +}; + +typedef enum { + IRECV_E_SUCCESS = 0, + IRECV_E_NO_DEVICE = -1, + IRECV_E_OUT_OF_MEMORY = -2, + IRECV_E_UNABLE_TO_CONNECT = -3, + IRECV_E_INVALID_INPUT = -4, + IRECV_E_FILE_NOT_FOUND = -5, + IRECV_E_USB_UPLOAD = -6, + IRECV_E_USB_STATUS = -7, + IRECV_E_USB_INTERFACE = -8, + IRECV_E_USB_CONFIGURATION = -9, + IRECV_E_UNKNOWN_ERROR = -255 +} irecv_error_t; struct irecv_client; typedef struct irecv_client* irecv_client_t; @@ -53,8 +53,7 @@ struct irecv_client { int config; int interface; int alt_interface; - char *uuid; - irecv_mode_t mode; + unsigned short mode; libusb_context* context; libusb_device_handle* handle; irecv_send_callback send_callback; diff --git a/src/libirecovery.c b/src/libirecovery.c index a2ec9c9..131032c 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -27,18 +27,6 @@ #define BUFFER_SIZE 0x1000 #define debug(...) if(client->debug) fprintf(stderr, __VA_ARGS__) -const char* irecv_error_invalid_input = "Invalid input"; -const char* irecv_error_unknown = "Unknown error"; -const char* irecv_error_file_not_found = "Unable to find file"; -const char* irecv_error_usb_status = "Invalid device status"; -const char* irecv_error_no_device = "Unable to find device"; -const char* irecv_error_out_of_memory = "Unable to allocate memory"; -const char* irecv_error_unable_to_connect = "Unable to connect to device"; -const char* irecv_error_usb_interface = "Unable to set device interface"; -const char* irecv_error_success = "Command completed successfully"; -const char* irecv_error_usb_upload = "Unable to upload data to device"; -const char* irecv_error_usb_configuration = "Unable to set device configuration"; - int irecv_default_sender(irecv_client_t client, unsigned char* data, int size); int irecv_default_receiver(irecv_client_t client, unsigned char* data, int size); @@ -85,22 +73,17 @@ irecv_error_t irecv_open(irecv_client_t* pclient, const char* uuid) { return IRECV_E_OUT_OF_MEMORY; } memset(client, '\0', sizeof(irecv_client_t)); + client->interface = -1; client->handle = usb_handle; client->context = usb_context; - client->mode = (irecv_mode_t) usb_descriptor.idProduct; + client->mode = usb_descriptor.idProduct; error = irecv_set_configuration(client, 1); if(error != IRECV_E_SUCCESS) { return error; } - error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; - } - *pclient = client; - printf("done"); return IRECV_E_SUCCESS; } } @@ -133,9 +116,11 @@ irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_ return IRECV_E_NO_DEVICE; } - debug("Setting to interface %d:%d", interface, alt_interface); - libusb_reset_device(client->handle); + if(client->interface == interface) { + return IRECV_E_SUCCESS; + } + debug("Setting to interface %d:%d", interface, alt_interface); if (libusb_claim_interface(client->handle, interface) < 0) { return IRECV_E_USB_INTERFACE; } @@ -150,7 +135,7 @@ irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_ } irecv_error_t irecv_reset(irecv_client_t client) { - if (client == NULL || client->handle != NULL) { + if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } @@ -161,7 +146,9 @@ irecv_error_t irecv_reset(irecv_client_t client) { irecv_error_t irecv_close(irecv_client_t client) { if (client != NULL) { if (client->handle != NULL) { - libusb_release_interface(client->handle, 1); + if(client->interface >= 0) { + libusb_release_interface(client->handle, client->interface); + } libusb_close(client->handle); client->handle = NULL; } @@ -171,10 +158,6 @@ irecv_error_t irecv_close(irecv_client_t client) { client->context = NULL; } - if(client->uuid != NULL) { - free(client->uuid); - } - free(client); client = NULL; } @@ -220,6 +203,11 @@ irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) return IRECV_E_NO_DEVICE; } + irecv_error_t error = irecv_set_interface(client, 1, 1); + if(error != IRECV_E_SUCCESS) { + return error; + } + unsigned int length = strlen(command); if(length >= 0x100) { length = 0xFF; @@ -257,7 +245,7 @@ irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) { if(bytes != length) { free(buffer); - return IRECV_E_UNKNOWN; + return IRECV_E_UNKNOWN_ERROR; } irecv_error_t error = irecv_send_buffer(client, buffer, length); @@ -271,6 +259,11 @@ irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) { return IRECV_E_NO_DEVICE; } + irecv_error_t error = irecv_set_interface(client, 1, 1); + if(error != IRECV_E_SUCCESS) { + return error; + } + unsigned char buffer[6]; memset(buffer, '\0', 6); if(libusb_control_transfer(client->handle, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) { @@ -289,6 +282,11 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un return IRECV_E_NO_DEVICE; } + error = irecv_set_interface(client, 1, 1); + if(error != IRECV_E_SUCCESS) { + return error; + } + int last = length % 0x800; int packets = length / 0x800; if (last != 0) { @@ -312,7 +310,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un } if(status != 5) { - return IRECV_E_USB_STATUS; + return IRECV_E_USB_UPLOAD; } } @@ -335,12 +333,17 @@ irecv_error_t irecv_receive(irecv_client_t client) { return IRECV_E_NO_DEVICE; } + irecv_error_t error = irecv_set_interface(client, 1, 1); + if(error != IRECV_E_SUCCESS) { + return error; + } + int bytes = 0; while(libusb_bulk_transfer(client->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) { if(bytes > 0) { if(client->receive_callback != NULL) { if(client->receive_callback(client, buffer, bytes) != bytes) { - return IRECV_E_UNKNOWN; + return IRECV_E_UNKNOWN_ERROR; } } } else break; @@ -380,14 +383,23 @@ irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callba } irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) { - unsigned char* value = (unsigned char*) malloc(0x200); + if(client == NULL || client->handle == NULL) { + return IRECV_E_NO_DEVICE; + } + + irecv_error_t error = irecv_set_interface(client, 1, 1); + if(error != IRECV_E_SUCCESS) { + return error; + } + + unsigned char* value = (unsigned char*) malloc(256); if(value == NULL) { return IRECV_E_OUT_OF_MEMORY; } - int ret = libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, value, 0x200, 500); + int ret = libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, value, 256, 500); if(ret < 0) { - return IRECV_E_UNKNOWN; + return IRECV_E_UNKNOWN_ERROR; } *var = value; @@ -398,56 +410,59 @@ irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) { irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) { char info[256]; memset(info, '\0', 256); - libusb_get_string_descriptor_ascii(client->handle, 3, info, 0x100); - debug("%s\n", info); + + if(client == NULL || client->handle == NULL) { + return IRECV_E_NO_DEVICE; + } + + libusb_get_string_descriptor_ascii(client->handle, 3, info, 255); + printf("%d: %s\n", strlen(info), info); unsigned char* ecid_string = strstr(info, "ECID:"); if(ecid_string == NULL) { *ecid = 0; - return IRECV_E_UNKNOWN; + return IRECV_E_UNKNOWN_ERROR; } sscanf(ecid_string, "ECID:%qX", ecid); + irecv_reset(client); return IRECV_E_SUCCESS; } const char* irecv_strerror(irecv_error_t error) { switch(error) { case IRECV_E_SUCCESS: - return irecv_error_success; + return "Command completed successfully"; case IRECV_E_NO_DEVICE: - return irecv_error_no_device; + return "Unable to find device"; case IRECV_E_OUT_OF_MEMORY: - return irecv_error_out_of_memory; + return "Out of memory"; case IRECV_E_UNABLE_TO_CONNECT: - return irecv_error_unable_to_connect; + return "Unable to connect to device"; case IRECV_E_INVALID_INPUT: - return irecv_error_invalid_input; - - case IRECV_E_UNKNOWN: - return irecv_error_unknown; + return "Invalid input"; case IRECV_E_FILE_NOT_FOUND: - return irecv_error_file_not_found; + return "File not found"; case IRECV_E_USB_UPLOAD: - return irecv_error_usb_upload; + return "Unable to upload data to device"; case IRECV_E_USB_STATUS: - return irecv_error_usb_status; + return "Unable to get device status"; case IRECV_E_USB_INTERFACE: - return irecv_error_usb_interface; + return "Unable to set device interface"; case IRECV_E_USB_CONFIGURATION: - return irecv_error_usb_configuration; + return "Unable to set device configuration"; default: - return irecv_error_unknown; + return "Unknown error"; } return NULL; |