diff options
| author | 2010-05-20 13:10:26 +0200 | |
|---|---|---|
| committer | 2010-05-20 13:10:26 +0200 | |
| commit | fdbdb9f9e964528d08038e51cd57f9545cef294a (patch) | |
| tree | 9f8b43a2d95121973d48c2c23c26d732168069cb | |
| parent | cf12a431935f814b6f0b98fe43915c48fde2fcf0 (diff) | |
| download | libirecovery-fdbdb9f9e964528d08038e51cd57f9545cef294a.tar.gz libirecovery-fdbdb9f9e964528d08038e51cd57f9545cef294a.tar.bz2 | |
Improve irecv_open()'s device selection logic and allow opening by uuid
Previous code did attempt to open anything with an Apple vendor id.
Now it also verifies if the USB device is within a mode we know and also
allows targeting a specific device by it's UUID.
| -rw-r--r-- | include/libirecovery.h | 12 | ||||
| -rw-r--r-- | src/irecovery.c | 24 | ||||
| -rw-r--r-- | src/libirecovery.c | 77 | 
3 files changed, 81 insertions, 32 deletions
| diff --git a/include/libirecovery.h b/include/libirecovery.h index 680448f..f977ebb 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h @@ -32,10 +32,13 @@ typedef enum {  	IRECV_ERROR_USB_CONFIGURATION = -10  } irecv_error_t; +#define APPLE_VENDOR_ID 0x05AC +  typedef enum { -	kAppleId       = 0x05AC, -	kKernelMode    = 0x1294, -	kRecoveryMode  = 0x1281, +	kRecoveryMode1 = 0x1280, +	kRecoveryMode2 = 0x1281, +	kRecoveryMode3 = 0x1282, +	kRecoveryMode4 = 0x1283,  	kDfuMode       = 0x1227  } irecv_mode_t; @@ -50,6 +53,7 @@ struct irecv_device {  	int config;  	int interface;  	int alt_interface; +	char *uuid;  	irecv_mode_t mode;  	libusb_context* context;  	libusb_device_handle* handle; @@ -59,7 +63,7 @@ struct irecv_device {  irecv_device_t* irecv_init();  const char* irecv_strerror(irecv_error_t error); -irecv_error_t irecv_open(irecv_device_t* device); +irecv_error_t irecv_open(irecv_device_t* device, const char *uuid);  irecv_error_t irecv_exit(irecv_device_t* device);  irecv_error_t irecv_reset(irecv_device_t* device);  irecv_error_t irecv_close(irecv_device_t* device); diff --git a/src/irecovery.c b/src/irecovery.c index 1c4957e..56b0453 100644 --- a/src/irecovery.c +++ b/src/irecovery.c @@ -52,8 +52,10 @@ void parse_command(irecv_device_t* device, unsigned char* command, unsigned int  	} else  	if(!strcmp(cmd, "/reconnect")) { +		char* uuid = strdup(device->uuid);  		irecv_close(device); -		irecv_open(device); +		irecv_open(device, uuid); +		free(uuid);  	} else  	if(!strcmp(cmd, "/upload")) { @@ -151,6 +153,7 @@ void print_usage() {  	printf("iRecovery - iDevice Recovery Utility\n");  	printf("Usage: ./irecovery [args]\n");  	printf("\t-v\t\tStart irecovery in verbose mode.\n"); +	printf("\t-u <uuid>\ttarget specific device by its 40-digit device UUID\n");  	printf("\t-c <cmd>\tSend command to device.\n");  	printf("\t-f <file>\tSend file to device.\n");  	printf("\t-h\t\tShow this help.\n"); @@ -163,9 +166,10 @@ int main(int argc, char** argv) {  	int opt = 0;  	int action = 0;  	char* argument = NULL; +	char *uuid = NULL;  	irecv_error_t error = 0;  	if(argc == 1) print_usage(); -	while ((opt = getopt(argc, argv, "vhrsc:f:")) > 0) { +	while ((opt = getopt(argc, argv, "vhru:sc:f:")) > 0) {  		switch (opt) {  		case 'v':  			verbose += 1; @@ -179,6 +183,10 @@ int main(int argc, char** argv) {  			action = kResetDevice;  			break; +		case 'u': +			uuid = optarg; +			break; +  		case 's':  			action = kStartShell;  			break; @@ -195,7 +203,7 @@ int main(int argc, char** argv) {  		default:  			fprintf(stderr, "Unknown argument\n"); -			break; +			return -1;  		}  	} @@ -209,14 +217,16 @@ int main(int argc, char** argv) {  	int i = 0;  	for(i = 0; i <= 5; i++) {  		debug("Attempting to connect... "); + +		if(irecv_open(device, uuid) < 0) sleep(1); +		else break; + +		debug("failed. No recovery device found.\n"); +  		if(i == 5) {  			irecv_exit(device);  			return -1;  		} - -		if(irecv_open(device) < 0) sleep(1); -		else break; -		debug("failed\n");  	}  	switch(action) { diff --git a/src/libirecovery.c b/src/libirecovery.c index b8eb224..18097ee 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -58,9 +58,10 @@ irecv_device_t* irecv_init() {  	return device;  } -irecv_error_t irecv_open(irecv_device_t* device) { +irecv_error_t irecv_open(irecv_device_t* device, const char *uuid) {  	int i = 0;  	int usb_device_count = 0; +	char serial[256];  	struct libusb_device* usb_device = NULL;  	struct libusb_device** usb_device_list = NULL;  	struct libusb_device_handle* usb_handle = NULL; @@ -75,28 +76,58 @@ irecv_error_t irecv_open(irecv_device_t* device) {  	for (i = 0; i < usb_device_count; i++) {  		usb_device = usb_device_list[i];  		libusb_get_device_descriptor(usb_device, &usb_descriptor); -		if (usb_descriptor.idVendor == kAppleId) { +		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) { + +				libusb_open(usb_device, &usb_handle); +				if (usb_handle == NULL) { +					libusb_free_device_list(usb_device_list, 1); +					return IRECV_ERROR_UNABLE_TO_CONNECT; +				} + +				/* get serial number */ +				if (libusb_get_string_descriptor_ascii (usb_handle, usb_descriptor.iSerialNumber, serial, sizeof(serial)) < 0) { +					libusb_free_device_list(usb_device_list, 1); +					libusb_close(usb_handle); +					return IRECV_ERROR_UNABLE_TO_CONNECT; +				} + +				/* match uuid if required */ +				if (uuid != NULL) { +					if (strcmp(uuid, serial)) { +						libusb_close(usb_handle); +						continue; +					} +				} -			libusb_open(usb_device, &usb_handle); -			if (usb_handle == NULL) { +				/* identified a valid recovery device */  				libusb_free_device_list(usb_device_list, 1); -				return IRECV_ERROR_UNABLE_TO_CONNECT; -			} -			libusb_free_device_list(usb_device_list, 1); -			 -			device->handle = usb_handle; -			device->mode = (irecv_mode_t) usb_descriptor.idProduct; -			error = irecv_set_configuration(device, 1); -			if(error != IRECV_SUCCESS) { -				return error; -			} -			 -			error = irecv_set_interface(device, 1, 1); -			if(error != IRECV_SUCCESS) { -				return error; + +				device->handle = usb_handle; +				device->uuid = strdup(serial); +				device->mode = (irecv_mode_t) usb_descriptor.idProduct; + +				debug("opening UUID \"%s\"... ", device->uuid); + +				error = irecv_set_configuration(device, 1); +				if(error != IRECV_SUCCESS) { +					debug("setting configuration... "); +					return error; +				} + +				error = irecv_set_interface(device, 1, 1); +				if(error != IRECV_SUCCESS) { +					debug("setting interface... "); +					return error; +				} + +				return IRECV_SUCCESS;  			} -			 -			return IRECV_SUCCESS;  		}  	} @@ -158,7 +189,11 @@ irecv_error_t irecv_close(irecv_device_t* device) {  		libusb_close(device->handle);  		device->handle = NULL;  	} -	 + +	if(device->uuid != NULL) { +		free(device->uuid); +	} +  	return IRECV_SUCCESS;  } | 
