summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/irecovery.c79
-rw-r--r--src/libirecovery.c79
2 files changed, 126 insertions, 32 deletions
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 @@
23#include <readline/readline.h> 23#include <readline/readline.h>
24#include <readline/history.h> 24#include <readline/history.h>
25 25
26#define FILE_HISTORY_PATH "~/.irecovery/history" 26#define FILE_HISTORY_PATH ".irecovery"
27#define debug(...) if(verbose) fprintf(stderr, __VA_ARGS__)
27 28
28enum { 29enum {
29 kResetDevice, kStartShell, kSendCommand, kSendFile 30 kResetDevice, kStartShell, kSendCommand, kSendFile
@@ -40,21 +41,29 @@ void print_shell_usage() {
40} 41}
41 42
42void parse_command(irecv_device_t* device, unsigned char* command, unsigned int size) { 43void parse_command(irecv_device_t* device, unsigned char* command, unsigned int size) {
43 char* cmd = strtok(command, " "); 44 char* cmd = strtok(strdup(command), " ");
44 if(!strcmp(command, "/exit")) { 45 debug("Executing %s %s\n", cmd, command);
46 if(!strcmp(cmd, "/exit")) {
45 quit = 1; 47 quit = 1;
46 } else 48 } else
47 49
48 if(!strcmp(command, "/help")) { 50 if(!strcmp(cmd, "/help")) {
49 print_shell_usage(); 51 print_shell_usage();
50 } else 52 } else
53
54 if(!strcmp(cmd, "/reconnect")) {
55 irecv_close(device);
56 irecv_open(device);
57 } else
51 58
52 if(!strcmp(command, "/upload")) { 59 if(!strcmp(cmd, "/upload")) {
53 char* filename = strtok(NULL, " "); 60 char* filename = strtok(NULL, " ");
61 debug("Sending %s\n", filename);
54 if(filename != NULL) { 62 if(filename != NULL) {
55 irecv_send_file(device, filename); 63 irecv_send_file(device, filename);
56 } 64 }
57 } 65 }
66 free(cmd);
58} 67}
59 68
60int recv_callback(irecv_device_t* device, unsigned char* data, int size) { 69int 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) {
66} 75}
67 76
68int send_callback(irecv_device_t* device, unsigned char* command, int size) { 77int send_callback(irecv_device_t* device, unsigned char* command, int size) {
78 irecv_error_t error = 0;
69 if(command[0] == '/') { 79 if(command[0] == '/') {
70 parse_command(device, command, size); 80 parse_command(device, command, size);
71 return 0; 81 return 0;
72 } 82 }
83
84 if(strstr(command, "getenv") != NULL) {
85 unsigned char* value = NULL;
86 error = irecv_send_command(device, command);
87 if(error != IRECV_SUCCESS) {
88 debug("%s\n", irecv_strerror(error));
89 return error;
90 }
91
92 error = irecv_getenv(device, &value);
93 if(error != IRECV_SUCCESS) {
94 debug("%s\n", irecv_strerror(error));
95 return error;
96 }
97
98 printf("%s\n", value);
99 free(value);
100 return 0;
101 }
102
103 if(!strcmp(command, "reboot")) {
104 error = irecv_send_command(device, command);
105 if(error != IRECV_SUCCESS) {
106 debug("%s\n", irecv_strerror(error));
107 return error;
108 }
109 quit = 1;
110 return 0;
111 }
112
73 return size; 113 return size;
74} 114}
75 115
@@ -83,17 +123,21 @@ void append_command_to_history(char* cmd) {
83} 123}
84 124
85void init_shell(irecv_device_t* device) { 125void init_shell(irecv_device_t* device) {
126 irecv_error_t error = 0;
86 load_command_history(); 127 load_command_history();
87 irecv_set_sender(device, &send_callback); 128 irecv_set_sender(device, &send_callback);
88 irecv_set_receiver(device, &recv_callback); 129 irecv_set_receiver(device, &recv_callback);
89 while(!quit) { 130 while(!quit) {
90 if(irecv_update(device) != IRECV_SUCCESS) { 131 error = irecv_receive(device);
132 if(error != IRECV_SUCCESS) {
133 debug("%s\n", irecv_strerror(error));
91 break; 134 break;
92 } 135 }
93 136
94 char* cmd = readline("> "); 137 char* cmd = readline("> ");
95 if(cmd && *cmd) { 138 if(cmd && *cmd) {
96 if(irecv_send_command(device, cmd) != IRECV_SUCCESS) { 139 error = irecv_send(device, cmd);
140 if(error != IRECV_SUCCESS) {
97 quit = 1; 141 quit = 1;
98 } 142 }
99 143
@@ -119,6 +163,7 @@ int main(int argc, char** argv) {
119 int opt = 0; 163 int opt = 0;
120 int action = 0; 164 int action = 0;
121 char* argument = NULL; 165 char* argument = NULL;
166 irecv_error_t error = 0;
122 if(argc == 1) print_usage(); 167 if(argc == 1) print_usage();
123 while ((opt = getopt(argc, argv, "vhrsc:f:")) > 0) { 168 while ((opt = getopt(argc, argv, "vhrsc:f:")) > 0) {
124 switch (opt) { 169 switch (opt) {
@@ -161,9 +206,17 @@ int main(int argc, char** argv) {
161 } 206 }
162 if(verbose) irecv_set_debug(device, verbose); 207 if(verbose) irecv_set_debug(device, verbose);
163 208
164 if(irecv_open(device) < 0) { 209 int i = 0;
165 fprintf(stderr, "Unable to open device\n"); 210 for(i = 0; i <= 5; i++) {
166 return -1; 211 debug("Attempting to connect... ");
212 if(i == 5) {
213 irecv_exit(device);
214 return -1;
215 }
216
217 if(irecv_open(device) < 0) sleep(1);
218 else break;
219 debug("failed\n");
167 } 220 }
168 221
169 switch(action) { 222 switch(action) {
@@ -172,11 +225,13 @@ int main(int argc, char** argv) {
172 break; 225 break;
173 226
174 case kSendFile: 227 case kSendFile:
175 irecv_send_file(device, argument); 228 error = irecv_send_file(device, argument);
229 debug("%s\n", irecv_strerror(error));
176 break; 230 break;
177 231
178 case kSendCommand: 232 case kSendCommand:
179 irecv_send_command(device, argument); 233 error = irecv_send_command(device, argument);
234 debug("%s\n", irecv_strerror(error));
180 break; 235 break;
181 236
182 case kStartShell: 237 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() {
52 } 52 }
53 memset(device, '\0', sizeof(irecv_device_t)); 53 memset(device, '\0', sizeof(irecv_device_t));
54 54
55 irecv_set_receiver(device, &irecv_default_receiver); 55 //irecv_set_receiver(device, &irecv_default_receiver);
56 irecv_set_sender(device, &irecv_default_sender); 56 //irecv_set_sender(device, &irecv_default_sender);
57 device->context = usb_context; 57 device->context = usb_context;
58 return device; 58 return device;
59} 59}
@@ -124,15 +124,13 @@ irecv_error_t irecv_set_interface(irecv_device_t* device, int interface, int alt
124 if(device == NULL || device->handle == NULL) { 124 if(device == NULL || device->handle == NULL) {
125 return IRECV_ERROR_NO_DEVICE; 125 return IRECV_ERROR_NO_DEVICE;
126 } 126 }
127 127
128 if (libusb_claim_interface(device->handle, interface) < 0) { 128 if (libusb_claim_interface(device->handle, interface) < 0) {
129 return IRECV_ERROR_USB_INTERFACE; 129 return IRECV_ERROR_USB_INTERFACE;
130 } 130 }
131 131
132 if(alt_interface > 0) { 132 if(libusb_set_interface_alt_setting(device->handle, interface, alt_interface) < 0) {
133 if(libusb_set_interface_alt_setting(device->handle, interface, alt_interface) < 0) { 133 return IRECV_ERROR_USB_INTERFACE;
134 return IRECV_ERROR_USB_INTERFACE;
135 }
136 } 134 }
137 135
138 device->interface = interface; 136 device->interface = interface;
@@ -192,7 +190,7 @@ irecv_error_t irecv_set_debug(irecv_device_t* device, int level) {
192 return IRECV_SUCCESS; 190 return IRECV_SUCCESS;
193} 191}
194 192
195irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command) { 193irecv_error_t irecv_send(irecv_device_t* device, unsigned char* command) {
196 if(device == NULL || device->handle == NULL) { 194 if(device == NULL || device->handle == NULL) {
197 return IRECV_ERROR_NO_DEVICE; 195 return IRECV_ERROR_NO_DEVICE;
198 } 196 }
@@ -209,6 +207,23 @@ irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command)
209 } 207 }
210 208
211 if(length > 0) { 209 if(length > 0) {
210 irecv_send_command(device, command);
211 }
212
213 return IRECV_SUCCESS;
214}
215
216irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command) {
217 if(device == NULL || device->handle == NULL) {
218 return IRECV_ERROR_NO_DEVICE;
219 }
220
221 unsigned int length = strlen(command);
222 if(length >= 0x100) {
223 length = 0xFF;
224 }
225
226 if(length > 0) {
212 libusb_control_transfer(device->handle, 0x40, 0, 0, 0, command, length+1, 100); 227 libusb_control_transfer(device->handle, 0x40, 0, 0, 0, command, length+1, 100);
213 } 228 }
214 229
@@ -243,7 +258,9 @@ irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename) {
243 return IRECV_ERROR_UNKNOWN; 258 return IRECV_ERROR_UNKNOWN;
244 } 259 }
245 260
246 return irecv_send_buffer(device, buffer, length); 261 irecv_error_t error = irecv_send_buffer(device, buffer, length);
262 free(buffer);
263 return error;
247} 264}
248 265
249irecv_error_t irecv_get_status(irecv_device_t* device, unsigned int* status) { 266irecv_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) {
254 271
255 unsigned char buffer[6]; 272 unsigned char buffer[6];
256 memset(buffer, '\0', 6); 273 memset(buffer, '\0', 6);
257 if(libusb_control_transfer(device->handle, 0xA1, 3, 0, 0, buffer, 6, 500) != 6) { 274 if(libusb_control_transfer(device->handle, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) {
258 *status = 0; 275 *status = 0;
259 return IRECV_ERROR_USB_STATUS; 276 return IRECV_ERROR_USB_STATUS;
260 } 277 }
261 278
279 debug("status: %d\n", (unsigned int) buffer[4]);
262 *status = (unsigned int) buffer[4]; 280 *status = (unsigned int) buffer[4];
263 return IRECV_SUCCESS; 281 return IRECV_SUCCESS;
264} 282}
@@ -268,46 +286,52 @@ irecv_error_t irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, u
268 if(device == NULL || device->handle == NULL) { 286 if(device == NULL || device->handle == NULL) {
269 return IRECV_ERROR_NO_DEVICE; 287 return IRECV_ERROR_NO_DEVICE;
270 } 288 }
271 289
272 int last = length % 0x800; 290 int last = length % 0x800;
273 int packets = length / 0x800; 291 int packets = length / 0x800;
274 if (last != 0) { 292 if (last != 0) {
275 packets++; 293 packets++;
276 } else {
277 last = 0x800;
278 } 294 }
279 295
280 int i = 0; 296 int i = 0;
281 unsigned int status = 0; 297 unsigned int status = 0;
282 for (i = 0; i < packets; i++) { 298 for (i = 0; i < packets; i++) {
283 int size = i + 1 < packets ? 0x800 : last; 299 int size = i + 1 < packets ? 0x800 : last;
284 int bytes = libusb_control_transfer(device->handle, 0x21, 1, i, 0, &buffer[i * 0x800], size, 500); 300 int bytes = libusb_control_transfer(device->handle, 0x21, 1, i, 0, &buffer[i * 0x800], size, 1000);
285 if (bytes != size) { 301 if (bytes != size) {
286 free(buffer);
287 return IRECV_ERROR_USB_UPLOAD; 302 return IRECV_ERROR_USB_UPLOAD;
288 } 303 }
289 304
305 debug("Sent %d bytes\n", bytes);
306
290 error = irecv_get_status(device, &status); 307 error = irecv_get_status(device, &status);
291 if (error != IRECV_SUCCESS || status != 5) { 308 if (error != IRECV_SUCCESS) {
292 free(buffer);
293 return error; 309 return error;
294 } 310 }
311
312 if(status != 5) {
313 return IRECV_ERROR_USB_STATUS;
314 }
315
295 } 316 }
296 317
318 //char command[0x100];
319 //memset(command, '\0', 0x100);
320 //snprintf(command, 0x100, "setenv filesize %d", length);
297 libusb_control_transfer(device->handle, 0x21, 1, i, 0, buffer, 0, 1000); 321 libusb_control_transfer(device->handle, 0x21, 1, i, 0, buffer, 0, 1000);
298 for (i = 0; i < 3; i++) { 322 for (i = 0; i < 3; i++) {
299 error = irecv_get_status(device, &status); 323 error = irecv_get_status(device, &status);
300 if(error != IRECV_SUCCESS) { 324 if(error != IRECV_SUCCESS) {
301 free(buffer);
302 return error; 325 return error;
303 } 326 }
304 } 327 }
305 328
306 free(buffer); 329 //irecv_send_command(device, command);
330
307 return IRECV_SUCCESS; 331 return IRECV_SUCCESS;
308} 332}
309 333
310irecv_error_t irecv_update(irecv_device_t* device) { 334irecv_error_t irecv_receive(irecv_device_t* device) {
311 unsigned char buffer[BUFFER_SIZE]; 335 unsigned char buffer[BUFFER_SIZE];
312 memset(buffer, '\0', BUFFER_SIZE); 336 memset(buffer, '\0', BUFFER_SIZE);
313 if(device == NULL || device->handle == NULL) { 337 if(device == NULL || device->handle == NULL) {
@@ -358,6 +382,21 @@ irecv_error_t irecv_set_sender(irecv_device_t* device, irecv_send_callback callb
358 return IRECV_SUCCESS; 382 return IRECV_SUCCESS;
359} 383}
360 384
385irecv_error_t irecv_getenv(irecv_device_t* device, unsigned char** var) {
386 unsigned char* value = (unsigned char*) malloc(0x200);
387 if(value == NULL) {
388 return IRECV_ERROR_OUT_OF_MEMORY;
389 }
390
391 int ret = libusb_control_transfer(device->handle, 0xC0, 0, 0, 0, value, 0x200, 500);
392 if(ret < 0) {
393 return IRECV_ERROR_UNKNOWN;
394 }
395
396 *var = value;
397 return IRECV_SUCCESS;
398}
399
361const char* irecv_strerror(irecv_error_t error) { 400const char* irecv_strerror(irecv_error_t error) {
362 switch(error) { 401 switch(error) {
363 case IRECV_SUCCESS: 402 case IRECV_SUCCESS: