summaryrefslogtreecommitdiffstats
path: root/src/libirecovery.c
diff options
context:
space:
mode:
authorGravatar Joshua Hill2010-05-26 00:56:36 -0400
committerGravatar Joshua Hill2010-05-26 00:56:36 -0400
commitce77e6ac8ead2cb4fd204c67eb4d8a67e9a8e608 (patch)
treeb8b65fc01acc901c776149a136c9f115e67d7b87 /src/libirecovery.c
parent8482031ce77cb4914b5a04ba4704484cc6548dcd (diff)
downloadlibirecovery-ce77e6ac8ead2cb4fd204c67eb4d8a67e9a8e608.tar.gz
libirecovery-ce77e6ac8ead2cb4fd204c67eb4d8a67e9a8e608.tar.bz2
Began work on a new event based callback system
Diffstat (limited to 'src/libirecovery.c')
-rw-r--r--src/libirecovery.c277
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, &current);
- 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;
}