diff options
| author | 2010-05-21 04:05:32 -0400 | |
|---|---|---|
| committer | 2010-05-21 04:05:32 -0400 | |
| commit | 442363a01ef44e84eda3e22c71dd2de424f5121e (patch) | |
| tree | 9e8ca5c4074c6596795efb568ede0b40bfe95719 | |
| parent | c4477844178978ef36a607a911712ed4c9c6904a (diff) | |
| download | libirecovery-442363a01ef44e84eda3e22c71dd2de424f5121e.tar.gz libirecovery-442363a01ef44e84eda3e22c71dd2de424f5121e.tar.bz2 | |
Changed the API a bit to closer match libimobiledevice and added function to get ECID
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | include/libirecovery.h | 63 | ||||
| -rw-r--r-- | src/irecovery.c | 90 | ||||
| -rw-r--r-- | src/libirecovery.c | 354 | 
4 files changed, 240 insertions, 271 deletions
| @@ -1,4 +1,4 @@ -all: +all: linux  	@echo "Please choose either macosx, linux, or windows"  static: @@ -26,7 +26,7 @@ install:  uninstall:  	rm -rf /usr/local/lib/libirecovery.so -	rm -rf include/libirecovery.h /usr/local/include/libirecovery.h +	rm -rf /usr/local/include/libirecovery.h  	rm -rf /usr/local/bin/irecovery  clean: diff --git a/include/libirecovery.h b/include/libirecovery.h index f977ebb..9d30497 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h @@ -19,17 +19,17 @@  #include <libusb-1.0/libusb.h>  typedef enum { -	IRECV_SUCCESS =                   0, -	IRECV_ERROR_NO_DEVICE =          -1, -	IRECV_ERROR_OUT_OF_MEMORY =      -2, -	IRECV_ERROR_UNABLE_TO_CONNECT =  -3, -	IRECV_ERROR_INVALID_INPUT =      -4, -	IRECV_ERROR_UNKNOWN =            -5, -	IRECV_ERROR_FILE_NOT_FOUND =     -6, -	IRECV_ERROR_USB_UPLOAD =         -7, -	IRECV_ERROR_USB_STATUS =         -8, -	IRECV_ERROR_USB_INTERFACE =      -9, -	IRECV_ERROR_USB_CONFIGURATION = -10 +	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 @@ -42,13 +42,13 @@ typedef enum {  	kDfuMode       = 0x1227  } irecv_mode_t; -struct irecv_device; -typedef struct irecv_device irecv_device_t; +struct irecv_client; +typedef struct irecv_client* irecv_client_t; -typedef int(*irecv_send_callback)(irecv_device_t* device, unsigned char* data, int size); -typedef int(*irecv_receive_callback)(irecv_device_t* device, unsigned char* data, int size); +typedef int(*irecv_send_callback)(irecv_client_t client, unsigned char* data, int size); +typedef int(*irecv_receive_callback)(irecv_client_t client, unsigned char* data, int size); -struct irecv_device { +struct irecv_client {  	int debug;  	int config;  	int interface; @@ -61,21 +61,20 @@ struct irecv_device {  	irecv_receive_callback receive_callback;  }; -irecv_device_t* irecv_init();  const char* irecv_strerror(irecv_error_t error); -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); -irecv_error_t irecv_receive(irecv_device_t* device); -irecv_error_t irecv_set_debug(irecv_device_t* device, int level); -irecv_error_t irecv_getenv(irecv_device_t* device, unsigned char** var); -irecv_error_t irecv_send(irecv_device_t* device, unsigned char* command); -irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename); -irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command); -irecv_error_t irecv_set_configuration(irecv_device_t* device, int configuration); -irecv_error_t irecv_set_sender(irecv_device_t* device, irecv_send_callback callback); -irecv_error_t irecv_set_receiver(irecv_device_t* device, irecv_receive_callback callback); -irecv_error_t irecv_set_interface(irecv_device_t* device, int interface, int alt_interface); -irecv_error_t irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, unsigned int length); +irecv_error_t irecv_open(irecv_client_t* client, const char *uuid); +irecv_error_t irecv_reset(irecv_client_t client); +irecv_error_t irecv_close(irecv_client_t client); +irecv_error_t irecv_receive(irecv_client_t client); +irecv_error_t irecv_set_debug(irecv_client_t client, int level); +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* pecid); +irecv_error_t irecv_send(irecv_client_t client, unsigned char* command); +irecv_error_t irecv_send_file(irecv_client_t client, const char* filename); +irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command); +irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration); +irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callback); +irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback); +irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface); +irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length); diff --git a/src/irecovery.c b/src/irecovery.c index 56b0453..00db72d 100644 --- a/src/irecovery.c +++ b/src/irecovery.c @@ -35,12 +35,12 @@ static unsigned int verbose = 0;  void print_shell_usage() {  	printf("Usage:\n"); -	printf("\t/upload <file>\tSend file to device.\n"); +	printf("\t/upload <file>\tSend file to client.\n");  	printf("\t/help\t\tShow this help.\n");  	printf("\t/exit\t\tExit interactive shell.\n");  } -void parse_command(irecv_device_t* device, unsigned char* command, unsigned int size) { +void parse_command(irecv_client_t client, unsigned char* command, unsigned int size) {  	char* cmd = strtok(strdup(command), " ");  	debug("Executing %s %s\n", cmd, command);  	if(!strcmp(cmd, "/exit")) { @@ -50,25 +50,18 @@ void parse_command(irecv_device_t* device, unsigned char* command, unsigned int  	if(!strcmp(cmd, "/help")) {  		print_shell_usage();  	} else - -	if(!strcmp(cmd, "/reconnect")) { -		char* uuid = strdup(device->uuid); -		irecv_close(device); -		irecv_open(device, uuid); -		free(uuid); -	} else  	if(!strcmp(cmd, "/upload")) {  		char* filename = strtok(NULL, " ");  		debug("Sending %s\n", filename);  		if(filename != NULL) { -			irecv_send_file(device, filename); +			irecv_send_file(client, filename);  		}  	}  	free(cmd);  } -int recv_callback(irecv_device_t* device, unsigned char* data, int size) { +int recv_callback(irecv_client_t client, unsigned char* data, int size) {  	int i = 0;  	for(i = 0; i < size; i++) {  		printf("%c", data[i]); @@ -76,23 +69,23 @@ int recv_callback(irecv_device_t* device, unsigned char* data, int size) {  	return size;  } -int send_callback(irecv_device_t* device, unsigned char* command, int size) { +int send_callback(irecv_client_t client, unsigned char* command, int size) {  	irecv_error_t error = 0;  	if(command[0] == '/') { -		parse_command(device, command, size); +		parse_command(client, command, size);  		return 0;  	}  	if(strstr(command, "getenv") != NULL) {  		unsigned char* value = NULL; -		error = irecv_send_command(device, command); -		if(error != IRECV_SUCCESS) { +		error = irecv_send_command(client, command); +		if(error != IRECV_E_SUCCESS) {  			debug("%s\n", irecv_strerror(error));  			return error;  		} -		error = irecv_getenv(device, &value); -		if(error != IRECV_SUCCESS) { +		error = irecv_getenv(client, &value); +		if(error != IRECV_E_SUCCESS) {  			debug("%s\n", irecv_strerror(error));  			return error;  		} @@ -103,8 +96,8 @@ int send_callback(irecv_device_t* device, unsigned char* command, int size) {  	}  	if(!strcmp(command, "reboot")) { -		error = irecv_send_command(device, command); -		if(error != IRECV_SUCCESS) { +		error = irecv_send_command(client, command); +		if(error != IRECV_E_SUCCESS) {  			debug("%s\n", irecv_strerror(error));  			return error;  		} @@ -124,22 +117,22 @@ void append_command_to_history(char* cmd) {  	write_history(FILE_HISTORY_PATH);  } -void init_shell(irecv_device_t* device) { +void init_shell(irecv_client_t client) {  	irecv_error_t error = 0;  	load_command_history(); -	irecv_set_sender(device, &send_callback); -	irecv_set_receiver(device, &recv_callback); +	irecv_set_sender(client, &send_callback); +	irecv_set_receiver(client, &recv_callback);  	while(!quit) { -		error = irecv_receive(device); -		if(error != IRECV_SUCCESS) { +		error = irecv_receive(client); +		if(error != IRECV_E_SUCCESS) {  			debug("%s\n", irecv_strerror(error));  			break;  		}  		char* cmd = readline("> ");  		if(cmd && *cmd) { -			error = irecv_send(device, cmd); -			if(error != IRECV_SUCCESS) { +			error = irecv_send(client, cmd); +			if(error != IRECV_E_SUCCESS) {  				quit = 1;  			} @@ -153,16 +146,17 @@ 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-u <uuid>\ttarget specific client by its 40-digit client UUID\n"); +	printf("\t-c <cmd>\tSend command to client.\n"); +	printf("\t-f <file>\tSend file to client.\n");  	printf("\t-h\t\tShow this help.\n"); -	printf("\t-r\t\tReset device.\n"); +	printf("\t-r\t\tReset client.\n");  	printf("\t-s\t\tStart interactive shell.\n");  	exit(1);  }  int main(int argc, char** argv) { +	int i = 0;  	int opt = 0;  	int action = 0;  	char* argument = NULL; @@ -179,14 +173,14 @@ int main(int argc, char** argv) {  			print_usage();  			break; -		case 'r': -			action = kResetDevice; -			break; -  		case 'u':  			uuid = optarg;  			break; +		case 'r': +			action = kResetDevice; +			break; +  		case 's':  			action = kStartShell;  			break; @@ -207,45 +201,37 @@ int main(int argc, char** argv) {  		}  	} -	irecv_device_t* device = irecv_init(); -	if(device == NULL) { -		fprintf(stderr, "Unable to initialize libirecovery\n"); -		return -1; -	} -	if(verbose) irecv_set_debug(device, verbose); - -	int i = 0; +	irecv_client_t client = NULL;  	for(i = 0; i <= 5; i++) { -		debug("Attempting to connect... "); +		debug("Attempting to connect... \n"); -		if(irecv_open(device, uuid) < 0) sleep(1); +		if(irecv_open(&client, uuid) != IRECV_E_SUCCESS) sleep(1);  		else break; -		debug("failed. No recovery device found.\n"); -  		if(i == 5) { -			irecv_exit(device);  			return -1;  		}  	} +	if(verbose) irecv_set_debug(client, verbose); +  	switch(action) {  	case kResetDevice: -		irecv_reset(device); +		irecv_reset(client);  		break;  	case kSendFile: -		error = irecv_send_file(device, argument); +		error = irecv_send_file(client, argument);  		debug("%s\n", irecv_strerror(error));  		break;  	case kSendCommand: -		error = irecv_send_command(device, argument); +		error = irecv_send_command(client, argument);  		debug("%s\n", irecv_strerror(error));  		break;  	case kStartShell: -		init_shell(device); +		init_shell(client);  		break;  	default: @@ -253,7 +239,7 @@ int main(int argc, char** argv) {  		break;  	} -	irecv_exit(device); +	irecv_close(client);  	return 0;  } diff --git a/src/libirecovery.c b/src/libirecovery.c index 0be16c6..a2ec9c9 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -25,7 +25,7 @@  #include "libirecovery.h"  #define BUFFER_SIZE 0x1000 -#define debug(...) if(device->debug) fprintf(stderr, __VA_ARGS__) +#define debug(...) if(client->debug) fprintf(stderr, __VA_ARGS__)  const char* irecv_error_invalid_input     = "Invalid input";  const char* irecv_error_unknown           = "Unknown error"; @@ -39,40 +39,22 @@ 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_device_t* device, unsigned char* data, int size); -int irecv_default_receiver(irecv_device_t* device, unsigned char* data, int size); +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); -irecv_device_t* irecv_init() { -	struct libusb_context* usb_context = NULL; - -	libusb_init(&usb_context); -	irecv_device_t* device = (irecv_device_t*) malloc(sizeof(irecv_device_t)); -	if (device == NULL) { -		return NULL; -	} -	memset(device, '\0', sizeof(irecv_device_t)); - -	//irecv_set_receiver(device, &irecv_default_receiver); -	//irecv_set_sender(device, &irecv_default_sender); -	device->context = usb_context; -	return device; -} - -irecv_error_t irecv_open(irecv_device_t* device, const char *uuid) { +irecv_error_t irecv_open(irecv_client_t* pclient, const char* uuid) {  	int i = 0; -	int usb_device_count = 0;  	char serial[256];  	struct libusb_device* usb_device = NULL; +	struct libusb_context* usb_context = NULL;  	struct libusb_device** usb_device_list = NULL;  	struct libusb_device_handle* usb_handle = NULL;  	struct libusb_device_descriptor usb_descriptor; -	if (device == NULL || device->context == NULL) { -		return IRECV_ERROR_NO_DEVICE; -	} - -	irecv_error_t error = 0; -	usb_device_count = libusb_get_device_list(device->context, &usb_device_list); +	*pclient = NULL; +	libusb_init(&usb_context); +	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++) {  		usb_device = usb_device_list[i];  		libusb_get_device_descriptor(usb_device, &usb_descriptor); @@ -87,147 +69,132 @@ irecv_error_t irecv_open(irecv_device_t* device, const char *uuid) {  				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_exit(usb_context); +					return IRECV_E_UNABLE_TO_CONNECT;  				} +				libusb_set_debug(usb_context, 3);  				/* identified a valid recovery device */  				libusb_free_device_list(usb_device_list, 1); -				device->handle = usb_handle; -				device->uuid = strdup(serial); -				device->mode = (irecv_mode_t) usb_descriptor.idProduct; - -				debug("opening UUID \"%s\"... ", device->uuid); +				irecv_client_t client = (irecv_client_t) malloc(sizeof(irecv_client_t)); +				if (client == NULL) { +					libusb_close(usb_handle); +					libusb_exit(usb_context); +					return IRECV_E_OUT_OF_MEMORY; +				} +				memset(client, '\0', sizeof(irecv_client_t)); +				client->handle = usb_handle; +				client->context = usb_context; +				client->mode = (irecv_mode_t) usb_descriptor.idProduct; -				error = irecv_set_configuration(device, 1); -				if(error != IRECV_SUCCESS) { -					debug("setting configuration... "); +				error = irecv_set_configuration(client, 1); +				if(error != IRECV_E_SUCCESS) {  					return error;  				} -				error = irecv_set_interface(device, 1, 1); -				if(error != IRECV_SUCCESS) { -					debug("setting interface... "); +				error = irecv_set_interface(client, 1, 1); +				if(error != IRECV_E_SUCCESS) {  					return error;  				} -				return IRECV_SUCCESS; +				*pclient = client; +				printf("done"); +				return IRECV_E_SUCCESS;  			}  		}  	} -	return IRECV_ERROR_NO_DEVICE; +	return IRECV_E_UNABLE_TO_CONNECT;  } -irecv_error_t irecv_set_configuration(irecv_device_t* device, int configuration) { -	if(device == NULL || device->handle == NULL) { -		return IRECV_ERROR_NO_DEVICE;  +irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration) { +	if(client == NULL || client->handle == NULL) { +		return IRECV_E_NO_DEVICE;  	} + +	debug("Setting to configuration %d", configuration);  	int current = 0; -	libusb_get_configuration(device->handle, ¤t); +	libusb_get_configuration(client->handle, ¤t);  	if(current != configuration) { -		if (libusb_set_configuration(device->handle, configuration) < 0) { -			return IRECV_ERROR_USB_CONFIGURATION; +		if (libusb_set_configuration(client->handle, configuration) < 0) { +			return IRECV_E_USB_CONFIGURATION;  		}  	} -	device->config = configuration; -	return IRECV_SUCCESS; +	client->config = configuration; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_set_interface(irecv_device_t* device, int interface, int alt_interface) { -	if(device == NULL || device->handle == NULL) { -		return IRECV_ERROR_NO_DEVICE;  +irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface) { +	if(client == NULL || client->handle == NULL) { +		return IRECV_E_NO_DEVICE;  	} -	if (libusb_claim_interface(device->handle, interface) < 0) { -		return IRECV_ERROR_USB_INTERFACE; +	debug("Setting to interface %d:%d", interface, alt_interface); +	libusb_reset_device(client->handle); + +	if (libusb_claim_interface(client->handle, interface) < 0) { +		return IRECV_E_USB_INTERFACE;  	} -	if(libusb_set_interface_alt_setting(device->handle, interface, alt_interface) < 0) { -		return IRECV_ERROR_USB_INTERFACE; +	if(libusb_set_interface_alt_setting(client->handle, interface, alt_interface) < 0) { +		return IRECV_E_USB_INTERFACE;  	} -	device->interface = interface; -	device->alt_interface = alt_interface; -	return IRECV_SUCCESS; +	client->interface = interface; +	client->alt_interface = alt_interface; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_reset(irecv_device_t* device) { -	if (device == NULL || device->handle != NULL) { -		return IRECV_ERROR_NO_DEVICE; +irecv_error_t irecv_reset(irecv_client_t client) { +	if (client == NULL || client->handle != NULL) { +		return IRECV_E_NO_DEVICE;  	} -	libusb_reset_device(device->handle); -	return IRECV_SUCCESS; +	libusb_reset_device(client->handle); +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_close(irecv_device_t* device) { -	if (device == NULL) { -		return IRECV_ERROR_NO_DEVICE; -	} - -	if(device->handle != NULL) { -		libusb_release_interface(device->handle, 0); -		libusb_release_interface(device->handle, 1); -		libusb_close(device->handle); -		device->handle = NULL; -	} - -	if(device->uuid != NULL) { -		free(device->uuid); -	} - -	return IRECV_SUCCESS; -} +irecv_error_t irecv_close(irecv_client_t client) { +	if (client != NULL) { +		if (client->handle != NULL) { +			libusb_release_interface(client->handle, 1); +			libusb_close(client->handle); +			client->handle = NULL; +		} -irecv_error_t irecv_exit(irecv_device_t* device) { -	if (device != NULL) { -		if (device->handle != NULL) { -			irecv_close(device); +		if (client->context != NULL) { +			libusb_exit(client->context); +			client->context = NULL;  		} -		if (device->context != NULL) { -			libusb_exit(device->context); -			device->context = NULL; +		if(client->uuid != NULL) { +			free(client->uuid);  		} -		free(device); -		device = NULL; +		free(client); +		client = NULL;  	} -	return IRECV_SUCCESS; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_set_debug(irecv_device_t* device, int level) { -	if(device == NULL || device->context == NULL) { -		return IRECV_ERROR_NO_DEVICE;  +irecv_error_t irecv_set_debug(irecv_client_t client, int level) { +	if(client == NULL || client->context == NULL) { +		return IRECV_E_NO_DEVICE;  	} -	libusb_set_debug(device->context, level); -	device->debug = level; -	return IRECV_SUCCESS; +	libusb_set_debug(client->context, level); +	client->debug = level; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_send(irecv_device_t* device, unsigned char* command) { -	if(device == NULL || device->handle == NULL) { -		return IRECV_ERROR_NO_DEVICE; +irecv_error_t irecv_send(irecv_client_t client, unsigned char* command) { +	if(client == NULL || client->handle == NULL) { +		return IRECV_E_NO_DEVICE;  	}  	unsigned int length = strlen(command); @@ -235,22 +202,22 @@ irecv_error_t irecv_send(irecv_device_t* device, unsigned char* command) {  		length = 0xFF;  	} -	if(device->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 = device->send_callback(device, command, length); +		length = client->send_callback(client, command, length);  	}  	if(length > 0) { -		irecv_send_command(device, command); +		irecv_send_command(client, command);  	} -	return IRECV_SUCCESS; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command) { -	if(device == NULL || device->handle == NULL) { -		return IRECV_ERROR_NO_DEVICE; +irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) { +	if(client == NULL || client->handle == NULL) { +		return IRECV_E_NO_DEVICE;  	}  	unsigned int length = strlen(command); @@ -259,20 +226,20 @@ irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command)  	}  	if(length > 0) { -		libusb_control_transfer(device->handle, 0x40, 0, 0, 0, command, length+1, 100); +		libusb_control_transfer(client->handle, 0x40, 0, 0, 0, command, length+1, 100);  	} -	return IRECV_SUCCESS; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename) { -	if(device == NULL || device->handle == NULL) { -		return IRECV_ERROR_NO_DEVICE;  +irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) { +	if(client == NULL || client->handle == NULL) { +		return IRECV_E_NO_DEVICE;  	}  	FILE* file = fopen(filename, "rb");  	if (file == NULL) { -		return IRECV_ERROR_FILE_NOT_FOUND; +		return IRECV_E_FILE_NOT_FOUND;  	}  	fseek(file, 0, SEEK_END); @@ -282,7 +249,7 @@ irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename) {  	unsigned char* buffer = (unsigned char*) malloc(length);  	if (buffer == NULL) {  		fclose(file); -		return IRECV_ERROR_OUT_OF_MEMORY; +		return IRECV_E_OUT_OF_MEMORY;  	}  	int bytes = fread(buffer, 1, length, file); @@ -290,36 +257,36 @@ irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename) {  	if(bytes != length) {  		free(buffer); -		return IRECV_ERROR_UNKNOWN; +		return IRECV_E_UNKNOWN;  	} -	irecv_error_t error = irecv_send_buffer(device, buffer, length); +	irecv_error_t error = irecv_send_buffer(client, buffer, length);  	free(buffer);  	return error;  } -irecv_error_t irecv_get_status(irecv_device_t* device, unsigned int* status) { -	if(device == NULL || device->handle == NULL) { +irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) { +	if(client == NULL || client->handle == NULL) {  		*status = 0; -		return IRECV_ERROR_NO_DEVICE;  +		return IRECV_E_NO_DEVICE;  	}  	unsigned char buffer[6];  	memset(buffer, '\0', 6); -	if(libusb_control_transfer(device->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_ERROR_USB_STATUS; +		return IRECV_E_USB_STATUS;  	}  	debug("status: %d\n", (unsigned int) buffer[4]);  	*status = (unsigned int) buffer[4]; -	return IRECV_SUCCESS; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, unsigned int length) { +irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length) {  	irecv_error_t error = 0; -	if(device == NULL || device->handle == NULL) { -		return IRECV_ERROR_NO_DEVICE;  +	if(client == NULL || client->handle == NULL) { +		return IRECV_E_NO_DEVICE;  	}  	int last = length % 0x800; @@ -332,61 +299,61 @@ irecv_error_t irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, u  	unsigned int status = 0;  	for (i = 0; i < packets; i++) {  		int size = i + 1 < packets ? 0x800 : last; -		int bytes = libusb_control_transfer(device->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_ERROR_USB_UPLOAD; +			return IRECV_E_USB_UPLOAD;  		}  		debug("Sent %d bytes\n", bytes); -		error = irecv_get_status(device, &status); -		if (error != IRECV_SUCCESS) { +		error = irecv_get_status(client, &status); +		if (error != IRECV_E_SUCCESS) {  			return error;  		}  		if(status != 5) { -			return IRECV_ERROR_USB_STATUS; +			return IRECV_E_USB_STATUS;  		}  	} -	libusb_control_transfer(device->handle, 0x21, 1, 0, 0, buffer, 0, 1000); +	libusb_control_transfer(client->handle, 0x21, 1, 0, 0, buffer, 0, 1000);  	for (i = 0; i < 3; i++) { -		error = irecv_get_status(device, &status); -		if(error != IRECV_SUCCESS) { +		error = irecv_get_status(client, &status); +		if(error != IRECV_E_SUCCESS) {  			return error;  		}  	} -	return IRECV_SUCCESS; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_receive(irecv_device_t* device) { +irecv_error_t irecv_receive(irecv_client_t client) {  	unsigned char buffer[BUFFER_SIZE];  	memset(buffer, '\0', BUFFER_SIZE); -	if(device == NULL || device->handle == NULL) { -		return IRECV_ERROR_NO_DEVICE;  +	if(client == NULL || client->handle == NULL) { +		return IRECV_E_NO_DEVICE;  	}  	int bytes = 0; -	while(libusb_bulk_transfer(device->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) { +	while(libusb_bulk_transfer(client->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) {  		if(bytes > 0) { -			if(device->receive_callback != NULL) { -				if(device->receive_callback(device, buffer, bytes) != bytes) { -					return IRECV_ERROR_UNKNOWN; +			if(client->receive_callback != NULL) { +				if(client->receive_callback(client, buffer, bytes) != bytes) { +					return IRECV_E_UNKNOWN;  				}  			}  		} else break;  	} -	return IRECV_SUCCESS; +	return IRECV_E_SUCCESS;  } -int irecv_default_sender(irecv_device_t* device, unsigned char* data, int size) { +int irecv_default_sender(irecv_client_t client, unsigned char* data, int size) {  	return size;  } -int irecv_default_receiver(irecv_device_t* device, 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++) {  		printf("%c", data[i]); @@ -394,72 +361,89 @@ int irecv_default_receiver(irecv_device_t* device, unsigned char* data, int size  	return size;  } -irecv_error_t irecv_set_receiver(irecv_device_t* device, irecv_receive_callback callback) { -	if(device == NULL) { -		return IRECV_ERROR_NO_DEVICE;  +irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback) { +	if(client == NULL) { +		return IRECV_E_NO_DEVICE;  	} -	device->receive_callback = callback; -	return IRECV_SUCCESS; +	client->receive_callback = callback; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_set_sender(irecv_device_t* device, irecv_send_callback callback) { -	if(device == NULL) { -		return IRECV_ERROR_NO_DEVICE;  +irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callback) { +	if(client == NULL) { +		return IRECV_E_NO_DEVICE;  	} -	device->send_callback = callback; -	return IRECV_SUCCESS; +	client->send_callback = callback; +	return IRECV_E_SUCCESS;  } -irecv_error_t irecv_getenv(irecv_device_t* device, unsigned char** var) { +irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) {  	unsigned char* value = (unsigned char*) malloc(0x200);  	if(value == NULL) { -		return IRECV_ERROR_OUT_OF_MEMORY; +		return IRECV_E_OUT_OF_MEMORY;  	} -	int ret =  libusb_control_transfer(device->handle, 0xC0, 0, 0, 0, value, 0x200, 500); +	int ret =  libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, value, 0x200, 500);  	if(ret < 0) { -		return IRECV_ERROR_UNKNOWN; +		return IRECV_E_UNKNOWN;  	}  	*var = value; -	return IRECV_SUCCESS; +	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); +	libusb_get_string_descriptor_ascii(client->handle, 3, info, 0x100); +	debug("%s\n", info); + +	unsigned char* ecid_string = strstr(info, "ECID:"); +	if(ecid_string == NULL) { +		*ecid = 0; +		return IRECV_E_UNKNOWN; +	} +	sscanf(ecid_string, "ECID:%qX", ecid); + +	return IRECV_E_SUCCESS;  }  const char* irecv_strerror(irecv_error_t error) {  	switch(error) { -	case IRECV_SUCCESS: +	case IRECV_E_SUCCESS:  		return irecv_error_success; -	case IRECV_ERROR_NO_DEVICE: +	case IRECV_E_NO_DEVICE:  		return irecv_error_no_device; -	case IRECV_ERROR_OUT_OF_MEMORY: +	case IRECV_E_OUT_OF_MEMORY:  		return irecv_error_out_of_memory; -	case IRECV_ERROR_UNABLE_TO_CONNECT: +	case IRECV_E_UNABLE_TO_CONNECT:  		return irecv_error_unable_to_connect; -	case IRECV_ERROR_INVALID_INPUT: +	case IRECV_E_INVALID_INPUT:  		return irecv_error_invalid_input; -	case IRECV_ERROR_UNKNOWN: +	case IRECV_E_UNKNOWN:  		return irecv_error_unknown; -	case IRECV_ERROR_FILE_NOT_FOUND: +	case IRECV_E_FILE_NOT_FOUND:  		return irecv_error_file_not_found; -	case IRECV_ERROR_USB_UPLOAD: +	case IRECV_E_USB_UPLOAD:  		return irecv_error_usb_upload; -	case IRECV_ERROR_USB_STATUS: +	case IRECV_E_USB_STATUS:  		return irecv_error_usb_status; -	case IRECV_ERROR_USB_INTERFACE: +	case IRECV_E_USB_INTERFACE:  		return irecv_error_usb_interface; -	case IRECV_ERROR_USB_CONFIGURATION: +	case IRECV_E_USB_CONFIGURATION:  		return irecv_error_usb_configuration;  	default: | 
