diff options
Diffstat (limited to 'src/libirecovery.c')
-rw-r--r-- | src/libirecovery.c | 277 |
1 files changed, 166 insertions, 111 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c index 6587fe0..8f029ed 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -41,6 +41,7 @@ irecv_error_t irecv_open(irecv_client_t* pclient) { *pclient = NULL; libusb_init(&usb_context); + //libusb_init(NULL); irecv_error_t error = IRECV_E_SUCCESS; int usb_device_count = libusb_get_device_list(usb_context, &usb_device_list); for (i = 0; i < usb_device_count; i++) { @@ -48,11 +49,10 @@ irecv_error_t irecv_open(irecv_client_t* pclient) { libusb_get_device_descriptor(usb_device, &usb_descriptor); if (usb_descriptor.idVendor == APPLE_VENDOR_ID) { /* verify this device is in a mode we understand */ - if (usb_descriptor.idProduct == kRecoveryMode1 || - usb_descriptor.idProduct == kRecoveryMode2 || - usb_descriptor.idProduct == kRecoveryMode3 || - usb_descriptor.idProduct == kRecoveryMode4 || - usb_descriptor.idProduct == kDfuMode) { + if (usb_descriptor.idProduct == kRecoveryMode1 || usb_descriptor.idProduct + == kRecoveryMode2 || usb_descriptor.idProduct == kRecoveryMode3 + || usb_descriptor.idProduct == kRecoveryMode4 || usb_descriptor.idProduct + == kDfuMode) { libusb_open(usb_device, &usb_handle); if (usb_handle == NULL) { @@ -63,7 +63,7 @@ irecv_error_t irecv_open(irecv_client_t* pclient) { } libusb_set_debug(usb_context, 3); - libusb_free_device_list(usb_device_list, 0); + libusb_free_device_list(usb_device_list, 1); irecv_client_t client = (irecv_client_t) malloc(sizeof(struct irecv_client)); if (client == NULL) { @@ -72,13 +72,18 @@ irecv_error_t irecv_open(irecv_client_t* pclient) { return IRECV_E_OUT_OF_MEMORY; } memset(client, '\0', sizeof(struct irecv_client)); - client->interface = -1; + client->interface = 0; client->handle = usb_handle; client->context = usb_context; client->mode = usb_descriptor.idProduct; error = irecv_set_configuration(client, 1); - if(error != IRECV_E_SUCCESS) { + if (error != IRECV_E_SUCCESS) { + return error; + } + + error = irecv_set_interface(client, 1, 1); + if (error != IRECV_E_SUCCESS) { return error; } @@ -92,30 +97,30 @@ irecv_error_t irecv_open(irecv_client_t* pclient) { } irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration) { - if(client == NULL || client->handle == NULL) { + if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } debug("Setting to configuration %d", configuration); - + int current = 0; libusb_get_configuration(client->handle, ¤t); - if(current != configuration) { + if (current != configuration) { if (libusb_set_configuration(client->handle, configuration) < 0) { return IRECV_E_USB_CONFIGURATION; } } - + client->config = configuration; return IRECV_E_SUCCESS; } irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface) { - if(client == NULL || client->handle == NULL) { + if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } - if(client->interface == interface) { + if (client->interface == interface) { return IRECV_E_SUCCESS; } @@ -123,11 +128,11 @@ irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_ if (libusb_claim_interface(client->handle, interface) < 0) { return IRECV_E_USB_INTERFACE; } - - if(libusb_set_interface_alt_setting(client->handle, interface, alt_interface) < 0) { + + if (libusb_set_interface_alt_setting(client->handle, interface, alt_interface) < 0) { return IRECV_E_USB_INTERFACE; } - + client->interface = interface; client->alt_interface = alt_interface; return IRECV_E_SUCCESS; @@ -139,15 +144,48 @@ irecv_error_t irecv_reset(irecv_client_t client) { } libusb_reset_device(client->handle); + + return IRECV_E_SUCCESS; +} + +irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type, irecv_event_cb_t callback, void* user_data) { + switch(type) { + case IRECV_PRECOMMAND: + client->precommand_callback = callback; + break; + + case IRECV_POSTCOMMAND: + client->postcommand_callback = callback; + break; + + default: + return IRECV_E_UNKNOWN_ERROR; + } + + return IRECV_E_SUCCESS; +} + +irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type) { + switch(type) { + case IRECV_PRECOMMAND: + client->precommand_callback = NULL; + break; + + case IRECV_POSTCOMMAND: + client->postcommand_callback = NULL; + break; + + default: + return IRECV_E_UNKNOWN_ERROR; + } + return IRECV_E_SUCCESS; } irecv_error_t irecv_close(irecv_client_t client) { if (client != NULL) { if (client->handle != NULL) { - if(client->interface >= 0) { - libusb_release_interface(client->handle, client->interface); - } + libusb_release_interface(client->handle, 1); libusb_close(client->handle); client->handle = NULL; } @@ -165,32 +203,32 @@ irecv_error_t irecv_close(irecv_client_t client) { } irecv_error_t irecv_set_debug(irecv_client_t client, int level) { - if(client == NULL || client->context == NULL) { + if (client == NULL || client->context == NULL) { return IRECV_E_NO_DEVICE; } - + libusb_set_debug(client->context, level); client->debug = level; return IRECV_E_SUCCESS; } irecv_error_t irecv_send(irecv_client_t client, unsigned char* command) { - if(client == NULL || client->handle == NULL) { + if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } unsigned int length = strlen(command); - if(length >= 0x100) { + if (length >= 0x100) { length = 0xFF; } - - if(client->send_callback != NULL) { + + if (client->send_callback != NULL) { // Call our user defined callback first, this must return a number of bytes to send // or zero to abort send. length = client->send_callback(client, command, length); } - if(length > 0) { + if (length > 0) { irecv_send_command(client, command); } @@ -198,32 +236,49 @@ irecv_error_t irecv_send(irecv_client_t client, unsigned char* command) { } irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) { - if(client == NULL || client->handle == NULL) { + 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 int length = strlen(command); + if (length >= 0x100) { + length = 0xFF; + } - irecv_error_t error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; + irecv_event_t event; + if(client->precommand_callback != NULL) { + event.data = command; + event.type = IRECV_PRECOMMAND; + if(client->precommand_callback(client, &event)) { + return IRECV_E_SUCCESS; + } } - unsigned int length = strlen(command); - if(length >= 0x100) { - length = 0xFF; + if (length > 0) { + libusb_control_transfer(client->handle, 0x40, 0, 0, 0, command, length + 1, 100); } - if(length > 0) { - libusb_control_transfer(client->handle, 0x40, 0, 0, 0, command, length+1, 100); + if(client->postcommand_callback != NULL) { + event.data = command; + event.type = IRECV_POSTCOMMAND; + if(client->postcommand_callback(client, &event)) { + return IRECV_E_SUCCESS; + } } - + return IRECV_E_SUCCESS; } irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) { - if(client == NULL || client->handle == NULL) { + if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } - + FILE* file = fopen(filename, "rb"); if (file == NULL) { return IRECV_E_FILE_NOT_FOUND; @@ -242,7 +297,7 @@ irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) { int bytes = fread(buffer, 1, length, file); fclose(file); - if(bytes != length) { + if (bytes != length) { free(buffer); return IRECV_E_UNKNOWN_ERROR; } @@ -253,23 +308,23 @@ irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) { } irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) { - if(client == NULL || client->handle == NULL) { + if (client == NULL || client->handle == NULL) { *status = 0; return IRECV_E_NO_DEVICE; } - - irecv_error_t error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; - } - + /* + 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) { + if (libusb_control_transfer(client->handle, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) { *status = 0; return IRECV_E_USB_STATUS; } - + debug("status: %d\n", (unsigned int) buffer[4]); *status = (unsigned int) buffer[4]; return IRECV_E_SUCCESS; @@ -277,15 +332,15 @@ irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) { irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length) { irecv_error_t error = 0; - if(client == NULL || client->handle == NULL) { + if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } - - error = irecv_set_interface(client, 1, 1); - if(error != IRECV_E_SUCCESS) { - return error; - } - + /* + 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) { @@ -296,11 +351,12 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un unsigned int status = 0; for (i = 0; i < packets; i++) { int size = i + 1 < packets ? 0x800 : last; - int bytes = libusb_control_transfer(client->handle, 0x21, 1, 0, 0, &buffer[i * 0x800], size, 1000); + int bytes = libusb_control_transfer(client->handle, 0x21, 1, 0, 0, &buffer[i * 0x800], + size, 1000); if (bytes != size) { return IRECV_E_USB_UPLOAD; } - + debug("Sent %d bytes\n", bytes); error = irecv_get_status(client, &status); @@ -308,7 +364,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un return error; } - if(status != 5) { + if (status != 5) { return IRECV_E_USB_UPLOAD; } @@ -317,7 +373,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un libusb_control_transfer(client->handle, 0x21, 1, 0, 0, buffer, 0, 1000); for (i = 0; i < 3; i++) { error = irecv_get_status(client, &status); - if(error != IRECV_E_SUCCESS) { + if (error != IRECV_E_SUCCESS) { return error; } } @@ -328,26 +384,27 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un irecv_error_t irecv_receive(irecv_client_t client) { unsigned char buffer[BUFFER_SIZE]; memset(buffer, '\0', BUFFER_SIZE); - if(client == NULL || client->handle == NULL) { + 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; - } - + /* + 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) { + 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_ERROR; } } - } else break; + } else + break; } - + return IRECV_E_SUCCESS; } @@ -357,47 +414,47 @@ 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) { int i = 0; - for(i = 0; i < size; i++) { + for (i = 0; i < size; i++) { printf("%c", data[i]); } return size; } irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback) { - if(client == NULL) { + if (client == NULL) { return IRECV_E_NO_DEVICE; } - + client->receive_callback = callback; return IRECV_E_SUCCESS; } irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callback) { - if(client == NULL) { + if (client == NULL) { return IRECV_E_NO_DEVICE; } - + client->send_callback = callback; return IRECV_E_SUCCESS; } irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) { - if(client == NULL || client->handle == NULL) { + 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; - } - + /* + 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) { + if (value == NULL) { return IRECV_E_OUT_OF_MEMORY; } - int ret = libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, value, 256, 500); - if(ret < 0) { + int ret = libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, value, 256, 500); + if (ret < 0) { return IRECV_E_UNKNOWN_ERROR; } @@ -405,12 +462,11 @@ irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) { return IRECV_E_SUCCESS; } - irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) { char info[256]; memset(info, '\0', 256); - if(client == NULL || client->handle == NULL) { + if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } @@ -418,7 +474,7 @@ irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) { printf("%d: %s\n", strlen(info), info); unsigned char* ecid_string = strstr(info, "ECID:"); - if(ecid_string == NULL) { + if (ecid_string == NULL) { *ecid = 0; return IRECV_E_UNKNOWN_ERROR; } @@ -428,56 +484,55 @@ irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) { return IRECV_E_SUCCESS; } - irecv_error_t irecv_send_exploit(irecv_client_t client) { - if(client == NULL || client->handle == NULL) { + 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; - } - + /* + irecv_error_t error = irecv_set_interface(client, 1, 1); + if(error != IRECV_E_SUCCESS) { + return error; + } + */ libusb_control_transfer(client->handle, 0x21, 2, 0, 0, NULL, 0, 100); return IRECV_E_SUCCESS; } const char* irecv_strerror(irecv_error_t error) { - switch(error) { + switch (error) { case IRECV_E_SUCCESS: return "Command completed successfully"; - + case IRECV_E_NO_DEVICE: return "Unable to find device"; - + case IRECV_E_OUT_OF_MEMORY: return "Out of memory"; - + case IRECV_E_UNABLE_TO_CONNECT: return "Unable to connect to device"; - + case IRECV_E_INVALID_INPUT: return "Invalid input"; - + case IRECV_E_FILE_NOT_FOUND: return "File not found"; - + case IRECV_E_USB_UPLOAD: return "Unable to upload data to device"; - + case IRECV_E_USB_STATUS: return "Unable to get device status"; - + case IRECV_E_USB_INTERFACE: return "Unable to set device interface"; - + case IRECV_E_USB_CONFIGURATION: return "Unable to set device configuration"; - + default: return "Unknown error"; } - + return NULL; } |