summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Joshua Hill2010-05-17 18:40:58 -0400
committerGravatar Joshua Hill2010-05-17 18:40:58 -0400
commitcf12a431935f814b6f0b98fe43915c48fde2fcf0 (patch)
tree8b2b2acdbbec86fecf7cc1901282bb8d6ae3a18d
parent34fc43b128e475fda4e9834689e3649eba82c4c9 (diff)
downloadlibirecovery-cf12a431935f814b6f0b98fe43915c48fde2fcf0.tar.gz
libirecovery-cf12a431935f814b6f0b98fe43915c48fde2fcf0.tar.bz2
Implemented irecv_getenv() and added a number of bug fixes
-rw-r--r--include/libirecovery.h4
-rw-r--r--src/irecovery.c79
-rw-r--r--src/libirecovery.c79
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 <readline/readline.h>
#include <readline/history.h>
-#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;
}
@@ -209,6 +207,23 @@ irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command)
}
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: