From cf12a431935f814b6f0b98fe43915c48fde2fcf0 Mon Sep 17 00:00:00 2001 From: Joshua Hill Date: Mon, 17 May 2010 18:40:58 -0400 Subject: Implemented irecv_getenv() and added a number of bug fixes --- include/libirecovery.h | 4 ++- src/irecovery.c | 79 ++++++++++++++++++++++++++++++++++++++++++-------- src/libirecovery.c | 79 +++++++++++++++++++++++++++++++++++++------------- 3 files changed, 129 insertions(+), 33 deletions(-) diff --git a/include/libirecovery.h b/include/libirecovery.h index 65abf04..680448f 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h @@ -63,8 +63,10 @@ irecv_error_t irecv_open(irecv_device_t* device); 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_update(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); diff --git a/src/irecovery.c b/src/irecovery.c index 7133606..1c4957e 100644 --- a/src/irecovery.c +++ b/src/irecovery.c @@ -23,7 +23,8 @@ #include #include -#define FILE_HISTORY_PATH "~/.irecovery/history" +#define FILE_HISTORY_PATH ".irecovery" +#define debug(...) if(verbose) fprintf(stderr, __VA_ARGS__) enum { kResetDevice, kStartShell, kSendCommand, kSendFile @@ -40,21 +41,29 @@ void print_shell_usage() { } void parse_command(irecv_device_t* device, unsigned char* command, unsigned int size) { - char* cmd = strtok(command, " "); - if(!strcmp(command, "/exit")) { + char* cmd = strtok(strdup(command), " "); + debug("Executing %s %s\n", cmd, command); + if(!strcmp(cmd, "/exit")) { quit = 1; } else - if(!strcmp(command, "/help")) { + if(!strcmp(cmd, "/help")) { print_shell_usage(); } else + + if(!strcmp(cmd, "/reconnect")) { + irecv_close(device); + irecv_open(device); + } else - if(!strcmp(command, "/upload")) { + if(!strcmp(cmd, "/upload")) { char* filename = strtok(NULL, " "); + debug("Sending %s\n", filename); if(filename != NULL) { irecv_send_file(device, filename); } } + free(cmd); } int recv_callback(irecv_device_t* device, unsigned char* data, int size) { @@ -66,10 +75,41 @@ int recv_callback(irecv_device_t* device, unsigned char* data, int size) { } int send_callback(irecv_device_t* device, unsigned char* command, int size) { + irecv_error_t error = 0; if(command[0] == '/') { parse_command(device, command, size); return 0; } + + if(strstr(command, "getenv") != NULL) { + unsigned char* value = NULL; + error = irecv_send_command(device, command); + if(error != IRECV_SUCCESS) { + debug("%s\n", irecv_strerror(error)); + return error; + } + + error = irecv_getenv(device, &value); + if(error != IRECV_SUCCESS) { + debug("%s\n", irecv_strerror(error)); + return error; + } + + printf("%s\n", value); + free(value); + return 0; + } + + if(!strcmp(command, "reboot")) { + error = irecv_send_command(device, command); + if(error != IRECV_SUCCESS) { + debug("%s\n", irecv_strerror(error)); + return error; + } + quit = 1; + return 0; + } + return size; } @@ -83,17 +123,21 @@ void append_command_to_history(char* cmd) { } void init_shell(irecv_device_t* device) { + irecv_error_t error = 0; load_command_history(); irecv_set_sender(device, &send_callback); irecv_set_receiver(device, &recv_callback); while(!quit) { - if(irecv_update(device) != IRECV_SUCCESS) { + error = irecv_receive(device); + if(error != IRECV_SUCCESS) { + debug("%s\n", irecv_strerror(error)); break; } char* cmd = readline("> "); if(cmd && *cmd) { - if(irecv_send_command(device, cmd) != IRECV_SUCCESS) { + error = irecv_send(device, cmd); + if(error != IRECV_SUCCESS) { quit = 1; } @@ -119,6 +163,7 @@ int main(int argc, char** argv) { int opt = 0; int action = 0; char* argument = NULL; + irecv_error_t error = 0; if(argc == 1) print_usage(); while ((opt = getopt(argc, argv, "vhrsc:f:")) > 0) { switch (opt) { @@ -161,9 +206,17 @@ int main(int argc, char** argv) { } if(verbose) irecv_set_debug(device, verbose); - if(irecv_open(device) < 0) { - fprintf(stderr, "Unable to open device\n"); - return -1; + int i = 0; + for(i = 0; i <= 5; i++) { + debug("Attempting to connect... "); + if(i == 5) { + irecv_exit(device); + return -1; + } + + if(irecv_open(device) < 0) sleep(1); + else break; + debug("failed\n"); } switch(action) { @@ -172,11 +225,13 @@ int main(int argc, char** argv) { break; case kSendFile: - irecv_send_file(device, argument); + error = irecv_send_file(device, argument); + debug("%s\n", irecv_strerror(error)); break; case kSendCommand: - irecv_send_command(device, argument); + error = irecv_send_command(device, argument); + debug("%s\n", irecv_strerror(error)); break; case kStartShell: diff --git a/src/libirecovery.c b/src/libirecovery.c index bcea61c..b8eb224 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -52,8 +52,8 @@ irecv_device_t* irecv_init() { } memset(device, '\0', sizeof(irecv_device_t)); - irecv_set_receiver(device, &irecv_default_receiver); - irecv_set_sender(device, &irecv_default_sender); + //irecv_set_receiver(device, &irecv_default_receiver); + //irecv_set_sender(device, &irecv_default_sender); device->context = usb_context; return device; } @@ -124,15 +124,13 @@ irecv_error_t irecv_set_interface(irecv_device_t* device, int interface, int alt if(device == NULL || device->handle == NULL) { return IRECV_ERROR_NO_DEVICE; } - + if (libusb_claim_interface(device->handle, interface) < 0) { return IRECV_ERROR_USB_INTERFACE; } - if(alt_interface > 0) { - if(libusb_set_interface_alt_setting(device->handle, interface, alt_interface) < 0) { - return IRECV_ERROR_USB_INTERFACE; - } + if(libusb_set_interface_alt_setting(device->handle, interface, alt_interface) < 0) { + return IRECV_ERROR_USB_INTERFACE; } device->interface = interface; @@ -192,7 +190,7 @@ irecv_error_t irecv_set_debug(irecv_device_t* device, int level) { return IRECV_SUCCESS; } -irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command) { +irecv_error_t irecv_send(irecv_device_t* device, unsigned char* command) { if(device == NULL || device->handle == NULL) { return IRECV_ERROR_NO_DEVICE; } @@ -208,6 +206,23 @@ irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command) length = device->send_callback(device, command, length); } + if(length > 0) { + irecv_send_command(device, command); + } + + return IRECV_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; + } + + unsigned int length = strlen(command); + if(length >= 0x100) { + length = 0xFF; + } + if(length > 0) { libusb_control_transfer(device->handle, 0x40, 0, 0, 0, command, length+1, 100); } @@ -243,7 +258,9 @@ irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename) { return IRECV_ERROR_UNKNOWN; } - return irecv_send_buffer(device, buffer, length); + irecv_error_t error = irecv_send_buffer(device, buffer, length); + free(buffer); + return error; } irecv_error_t irecv_get_status(irecv_device_t* device, unsigned int* status) { @@ -254,11 +271,12 @@ irecv_error_t irecv_get_status(irecv_device_t* device, unsigned int* status) { unsigned char buffer[6]; memset(buffer, '\0', 6); - if(libusb_control_transfer(device->handle, 0xA1, 3, 0, 0, buffer, 6, 500) != 6) { + if(libusb_control_transfer(device->handle, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) { *status = 0; return IRECV_ERROR_USB_STATUS; } + debug("status: %d\n", (unsigned int) buffer[4]); *status = (unsigned int) buffer[4]; return IRECV_SUCCESS; } @@ -268,46 +286,52 @@ irecv_error_t irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, u if(device == NULL || device->handle == NULL) { return IRECV_ERROR_NO_DEVICE; } - + int last = length % 0x800; int packets = length / 0x800; if (last != 0) { packets++; - } else { - last = 0x800; } int i = 0; 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, i, 0, &buffer[i * 0x800], size, 500); + int bytes = libusb_control_transfer(device->handle, 0x21, 1, i, 0, &buffer[i * 0x800], size, 1000); if (bytes != size) { - free(buffer); return IRECV_ERROR_USB_UPLOAD; } + debug("Sent %d bytes\n", bytes); + error = irecv_get_status(device, &status); - if (error != IRECV_SUCCESS || status != 5) { - free(buffer); + if (error != IRECV_SUCCESS) { return error; } + + if(status != 5) { + return IRECV_ERROR_USB_STATUS; + } + } + //char command[0x100]; + //memset(command, '\0', 0x100); + //snprintf(command, 0x100, "setenv filesize %d", length); libusb_control_transfer(device->handle, 0x21, 1, i, 0, buffer, 0, 1000); for (i = 0; i < 3; i++) { error = irecv_get_status(device, &status); if(error != IRECV_SUCCESS) { - free(buffer); return error; } } - free(buffer); + //irecv_send_command(device, command); + return IRECV_SUCCESS; } -irecv_error_t irecv_update(irecv_device_t* device) { +irecv_error_t irecv_receive(irecv_device_t* device) { unsigned char buffer[BUFFER_SIZE]; memset(buffer, '\0', BUFFER_SIZE); if(device == NULL || device->handle == NULL) { @@ -358,6 +382,21 @@ irecv_error_t irecv_set_sender(irecv_device_t* device, irecv_send_callback callb return IRECV_SUCCESS; } +irecv_error_t irecv_getenv(irecv_device_t* device, unsigned char** var) { + unsigned char* value = (unsigned char*) malloc(0x200); + if(value == NULL) { + return IRECV_ERROR_OUT_OF_MEMORY; + } + + int ret = libusb_control_transfer(device->handle, 0xC0, 0, 0, 0, value, 0x200, 500); + if(ret < 0) { + return IRECV_ERROR_UNKNOWN; + } + + *var = value; + return IRECV_SUCCESS; +} + const char* irecv_strerror(irecv_error_t error) { switch(error) { case IRECV_SUCCESS: -- cgit v1.1-32-gdbae