summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Joshua Hill2010-05-16 14:15:26 -0400
committerGravatar Joshua Hill2010-05-16 14:15:26 -0400
commit3491ef9c41f1cd867028881a8beebf1ad55373c7 (patch)
treea8a0621e59f897544b1218eaf0ca513e1775a5cb /src
parente7cc5716d941ee2c1ec554926e76448092d9e0c5 (diff)
downloadlibirecovery-3491ef9c41f1cd867028881a8beebf1ad55373c7.tar.gz
libirecovery-3491ef9c41f1cd867028881a8beebf1ad55373c7.tar.bz2
Added irecv_set_configuration() and irecv_set_interface() functions and implemented bulk read
Diffstat (limited to 'src')
-rw-r--r--src/irecovery.c14
-rw-r--r--src/libirecovery.c161
2 files changed, 138 insertions, 37 deletions
diff --git a/src/irecovery.c b/src/irecovery.c
index 2ab0aaa..8ffe86b 100644
--- a/src/irecovery.c
+++ b/src/irecovery.c
@@ -29,7 +29,8 @@ enum {
29 kResetDevice, kStartShell, kSendCommand, kSendFile 29 kResetDevice, kStartShell, kSendCommand, kSendFile
30}; 30};
31 31
32static unsigned int exit_shell = 0; 32static unsigned int quit = 0;
33static unsigned int debug = 0;
33 34
34void print_shell_usage() { 35void print_shell_usage() {
35 printf("Usage:\n"); 36 printf("Usage:\n");
@@ -41,7 +42,7 @@ void print_shell_usage() {
41void parse_command(irecv_device_t* device, unsigned char* command, unsigned int size) { 42void parse_command(irecv_device_t* device, unsigned char* command, unsigned int size) {
42 char* cmd = strtok(command, " "); 43 char* cmd = strtok(command, " ");
43 if(!strcmp(command, "/exit")) { 44 if(!strcmp(command, "/exit")) {
44 exit_shell = 1; 45 quit = 1;
45 } else 46 } else
46 47
47 if(!strcmp(command, "/help")) { 48 if(!strcmp(command, "/help")) {
@@ -56,7 +57,7 @@ void parse_command(irecv_device_t* device, unsigned char* command, unsigned int
56 } 57 }
57} 58}
58 59
59int recv_callback(irecv_device_t* device, unsigned char* data, unsigned int size) { 60int recv_callback(irecv_device_t* device, unsigned char* data, int size) {
60 int i = 0; 61 int i = 0;
61 for(i = 0; i < size; i++) { 62 for(i = 0; i < size; i++) {
62 printf("%c", data[i]); 63 printf("%c", data[i]);
@@ -64,7 +65,7 @@ int recv_callback(irecv_device_t* device, unsigned char* data, unsigned int size
64 return size; 65 return size;
65} 66}
66 67
67int send_callback(irecv_device_t* device, unsigned char* command, unsigned int size) { 68int send_callback(irecv_device_t* device, unsigned char* command, int size) {
68 if(command[0] == '/') { 69 if(command[0] == '/') {
69 parse_command(device, command, size); 70 parse_command(device, command, size);
70 return 0; 71 return 0;
@@ -85,14 +86,14 @@ void init_shell(irecv_device_t* device) {
85 load_command_history(); 86 load_command_history();
86 irecv_set_sender(device, &send_callback); 87 irecv_set_sender(device, &send_callback);
87 irecv_set_receiver(device, &recv_callback); 88 irecv_set_receiver(device, &recv_callback);
88 while(!exit_shell) { 89 while(!quit) {
90 irecv_update(device);
89 char* cmd = readline("> "); 91 char* cmd = readline("> ");
90 if(cmd && *cmd) { 92 if(cmd && *cmd) {
91 irecv_send_command(device, cmd); 93 irecv_send_command(device, cmd);
92 append_command_to_history(cmd); 94 append_command_to_history(cmd);
93 free(cmd); 95 free(cmd);
94 } 96 }
95 irecv_update(device);
96 } 97 }
97} 98}
98 99
@@ -110,7 +111,6 @@ void print_usage() {
110 111
111int main(int argc, char** argv) { 112int main(int argc, char** argv) {
112 int opt = 0; 113 int opt = 0;
113 int debug = 0;
114 int action = 0; 114 int action = 0;
115 char* argument = NULL; 115 char* argument = NULL;
116 if(argc == 1) print_usage(); 116 if(argc == 1) print_usage();
diff --git a/src/libirecovery.c b/src/libirecovery.c
index c31a424..21cdfcf 100644
--- a/src/libirecovery.c
+++ b/src/libirecovery.c
@@ -19,10 +19,14 @@
19#include <stdio.h> 19#include <stdio.h>
20#include <stdlib.h> 20#include <stdlib.h>
21#include <string.h> 21#include <string.h>
22#include <unistd.h>
22#include <libusb-1.0/libusb.h> 23#include <libusb-1.0/libusb.h>
23 24
24#include "libirecovery.h" 25#include "libirecovery.h"
25 26
27#define BUFFER_SIZE 0x1000
28#define debug(...) if(device->debug) fprintf(stderr, __VA_ARGS__)
29
26irecv_device_t* irecv_init() { 30irecv_device_t* irecv_init() {
27 struct libusb_context* usb_context = NULL; 31 struct libusb_context* usb_context = NULL;
28 32
@@ -37,7 +41,7 @@ irecv_device_t* irecv_init() {
37 return device; 41 return device;
38} 42}
39 43
40int irecv_open(irecv_device_t* device) { 44irecv_error_t irecv_open(irecv_device_t* device) {
41 int i = 0; 45 int i = 0;
42 int usb_device_count = 0; 46 int usb_device_count = 0;
43 struct libusb_device* usb_device = NULL; 47 struct libusb_device* usb_device = NULL;
@@ -49,6 +53,7 @@ int irecv_open(irecv_device_t* device) {
49 return IRECV_ERROR_NO_DEVICE; 53 return IRECV_ERROR_NO_DEVICE;
50 } 54 }
51 55
56 irecv_error_t error = 0;
52 usb_device_count = libusb_get_device_list(device->context, &usb_device_list); 57 usb_device_count = libusb_get_device_list(device->context, &usb_device_list);
53 for (i = 0; i < usb_device_count; i++) { 58 for (i = 0; i < usb_device_count; i++) {
54 usb_device = usb_device_list[i]; 59 usb_device = usb_device_list[i];
@@ -60,10 +65,20 @@ int irecv_open(irecv_device_t* device) {
60 libusb_free_device_list(usb_device_list, 1); 65 libusb_free_device_list(usb_device_list, 1);
61 return IRECV_ERROR_UNABLE_TO_CONNECT; 66 return IRECV_ERROR_UNABLE_TO_CONNECT;
62 } 67 }
63
64 libusb_free_device_list(usb_device_list, 1); 68 libusb_free_device_list(usb_device_list, 1);
65 device->mode = usb_descriptor.idProduct; 69
66 device->handle = usb_handle; 70 device->handle = usb_handle;
71 device->mode = (irecv_mode_t) usb_descriptor.idProduct;
72 error = irecv_set_configuration(device, 1);
73 if(error != IRECV_SUCCESS) {
74 return error;
75 }
76
77 error = irecv_set_interface(device, 1, 1);
78 if(error != IRECV_SUCCESS) {
79 return error;
80 }
81
67 return IRECV_SUCCESS; 82 return IRECV_SUCCESS;
68 } 83 }
69 } 84 }
@@ -71,7 +86,42 @@ int irecv_open(irecv_device_t* device) {
71 return IRECV_ERROR_NO_DEVICE; 86 return IRECV_ERROR_NO_DEVICE;
72} 87}
73 88
74int irecv_reset(irecv_device_t* device) { 89irecv_error_t irecv_set_configuration(irecv_device_t* device, int configuration) {
90 if(device == NULL || device->handle == NULL) {
91 return IRECV_ERROR_NO_DEVICE;
92 }
93
94 int current = 0;
95 libusb_get_configuration(device->handle, &current);
96 if(current != configuration) {
97 if (libusb_set_configuration(device->handle, configuration) < 0) {
98 return IRECV_ERROR_USB_CONFIGURATION;
99 }
100 }
101
102 device->config = configuration;
103 return IRECV_SUCCESS;
104}
105
106irecv_error_t irecv_set_interface(irecv_device_t* device, int interface, int alt_interface) {
107 if(device == NULL || device->handle == NULL) {
108 return IRECV_ERROR_NO_DEVICE;
109 }
110
111 if (libusb_claim_interface(device->handle, interface) < 0) {
112 return IRECV_ERROR_USB_INTERFACE;
113 }
114
115 if(libusb_set_interface_alt_setting(device->handle, interface, alt_interface) < 0) {
116 return IRECV_ERROR_USB_INTERFACE;
117 }
118
119 device->interface = interface;
120 device->alt_interface = alt_interface;
121 return IRECV_SUCCESS;
122}
123
124irecv_error_t irecv_reset(irecv_device_t* device) {
75 if (device == NULL || device->handle != NULL) { 125 if (device == NULL || device->handle != NULL) {
76 return IRECV_ERROR_NO_DEVICE; 126 return IRECV_ERROR_NO_DEVICE;
77 } 127 }
@@ -80,21 +130,25 @@ int irecv_reset(irecv_device_t* device) {
80 return IRECV_SUCCESS; 130 return IRECV_SUCCESS;
81} 131}
82 132
83int irecv_close(irecv_device_t* device) { 133irecv_error_t irecv_close(irecv_device_t* device) {
84 if (device == NULL || device->handle != NULL) { 134 if (device == NULL) {
85 return IRECV_ERROR_NO_DEVICE; 135 return IRECV_ERROR_NO_DEVICE;
86 } 136 }
87 137
88 libusb_close(device->handle); 138 if(device->handle != NULL) {
89 device->handle = NULL; 139 libusb_release_interface(device->handle, 0);
140 libusb_release_interface(device->handle, 1);
141 libusb_close(device->handle);
142 device->handle = NULL;
143 }
144
90 return IRECV_SUCCESS; 145 return IRECV_SUCCESS;
91} 146}
92 147
93int irecv_exit(irecv_device_t* device) { 148irecv_error_t irecv_exit(irecv_device_t* device) {
94 if (device != NULL) { 149 if (device != NULL) {
95 if (device->handle != NULL) { 150 if (device->handle != NULL) {
96 libusb_close(device->handle); 151 irecv_close(device);
97 device->handle = NULL;
98 } 152 }
99 153
100 if (device->context != NULL) { 154 if (device->context != NULL) {
@@ -109,12 +163,16 @@ int irecv_exit(irecv_device_t* device) {
109 return IRECV_SUCCESS; 163 return IRECV_SUCCESS;
110} 164}
111 165
112void irecv_set_debug(irecv_device_t* device, int level) { 166irecv_error_t irecv_set_debug(irecv_device_t* device, int level) {
167 if(device == NULL || device->context == NULL) {
168 return IRECV_ERROR_NO_DEVICE;
169 }
170
113 libusb_set_debug(device->context, level); 171 libusb_set_debug(device->context, level);
114 device->debug = level; 172 device->debug = level;
115} 173}
116 174
117int irecv_send_command(irecv_device_t* device, unsigned char* command) { 175irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command) {
118 if(device == NULL || device->handle == NULL) { 176 if(device == NULL || device->handle == NULL) {
119 return IRECV_ERROR_NO_DEVICE; 177 return IRECV_ERROR_NO_DEVICE;
120 } 178 }
@@ -139,7 +197,11 @@ int irecv_send_command(irecv_device_t* device, unsigned char* command) {
139 return IRECV_SUCCESS; 197 return IRECV_SUCCESS;
140} 198}
141 199
142int irecv_send_file(irecv_device_t* device, const char* filename) { 200irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename) {
201 if(device == NULL || device->handle == NULL) {
202 return IRECV_ERROR_NO_DEVICE;
203 }
204
143 FILE* file = fopen(filename, "rb"); 205 FILE* file = fopen(filename, "rb");
144 if (file == NULL) { 206 if (file == NULL) {
145 return IRECV_ERROR_FILE_NOT_FOUND; 207 return IRECV_ERROR_FILE_NOT_FOUND;
@@ -166,16 +228,29 @@ int irecv_send_file(irecv_device_t* device, const char* filename) {
166 return irecv_send_buffer(device, buffer, length); 228 return irecv_send_buffer(device, buffer, length);
167} 229}
168 230
169unsigned int irecv_get_status(irecv_device_t* device) { 231irecv_error_t irecv_get_status(irecv_device_t* device, unsigned int* status) {
170 unsigned char status[6]; 232 if(device == NULL || device->handle == NULL) {
171 memset(status, '\0', 6); 233 *status = 0;
172 if(libusb_control_transfer(device->handle, 0xA1, 3, 0, 0, status, 6, 500) != 6) { 234 return IRECV_ERROR_NO_DEVICE;
235 }
236
237 unsigned char buffer[6];
238 memset(buffer, '\0', 6);
239 if(libusb_control_transfer(device->handle, 0xA1, 3, 0, 0, buffer, 6, 500) != 6) {
240 *status = 0;
173 return IRECV_ERROR_USB_STATUS; 241 return IRECV_ERROR_USB_STATUS;
174 } 242 }
175 return (unsigned int) status[4]; 243
244 *status = (unsigned int) buffer[4];
245 return IRECV_SUCCESS;
176} 246}
177 247
178int irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, int length) { 248irecv_error_t irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, unsigned int length) {
249 irecv_error_t error = 0;
250 if(device == NULL || device->handle == NULL) {
251 return IRECV_ERROR_NO_DEVICE;
252 }
253
179 int last = length % 0x800; 254 int last = length % 0x800;
180 int packets = length / 0x800; 255 int packets = length / 0x800;
181 if (last != 0) { 256 if (last != 0) {
@@ -185,7 +260,7 @@ int irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, int length)
185 } 260 }
186 261
187 int i = 0; 262 int i = 0;
188 char status[6]; 263 unsigned int status = 0;
189 for (i = 0; i < packets; i++) { 264 for (i = 0; i < packets; i++) {
190 int size = i + 1 < packets ? 0x800 : last; 265 int size = i + 1 < packets ? 0x800 : last;
191 int bytes = libusb_control_transfer(device->handle, 0x21, 1, i, 0, &buffer[i * 0x800], size, 500); 266 int bytes = libusb_control_transfer(device->handle, 0x21, 1, i, 0, &buffer[i * 0x800], size, 500);
@@ -193,34 +268,60 @@ int irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, int length)
193 free(buffer); 268 free(buffer);
194 return IRECV_ERROR_USB_UPLOAD; 269 return IRECV_ERROR_USB_UPLOAD;
195 } 270 }
196 271
197 if (irecv_get_status(device) != 5) { 272 error = irecv_get_status(device, &status);
273 if (error != IRECV_SUCCESS || status != 5) {
198 free(buffer); 274 free(buffer);
199 return IRECV_ERROR_USB_STATUS; 275 return error;
200 } 276 }
201 } 277 }
202 278
203 libusb_control_transfer(device->handle, 0x21, 1, i, 0, buffer, 0, 1000); 279 libusb_control_transfer(device->handle, 0x21, 1, i, 0, buffer, 0, 1000);
204 for (i = 0; i < 3; i++) { 280 for (i = 0; i < 3; i++) {
205 irecv_get_status(device); 281 error = irecv_get_status(device, &status);
282 if(error != IRECV_SUCCESS) {
283 free(buffer);
284 return error;
285 }
206 } 286 }
207 287
208 free(buffer); 288 free(buffer);
209 return IRECV_SUCCESS; 289 return IRECV_SUCCESS;
210} 290}
211 291
212void irecv_update(irecv_device_t* device) { 292irecv_error_t irecv_update(irecv_device_t* device) {
213 if(device->receive_callback == NULL) { 293 unsigned char buffer[BUFFER_SIZE];
214 return; 294 memset(buffer, '\0', BUFFER_SIZE);
295 if(device == NULL || device->handle == NULL) {
296 return IRECV_ERROR_NO_DEVICE;
297 }
298
299 int bytes = 0;
300 while(libusb_bulk_transfer(device->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) {
301 if(bytes > 0) {
302 if(device->receive_callback(device, buffer, bytes) != bytes) {
303 return IRECV_ERROR_UNKNOWN;
304 }
305 } else break;
215 } 306 }
307
308 return IRECV_SUCCESS;
216} 309}
217 310
218int irecv_set_receiver(irecv_device_t* device, irecv_receive_callback callback) { 311irecv_error_t irecv_set_receiver(irecv_device_t* device, irecv_receive_callback callback) {
312 if(device == NULL) {
313 return IRECV_ERROR_NO_DEVICE;
314 }
315
219 device->receive_callback = callback; 316 device->receive_callback = callback;
220 return IRECV_SUCCESS; 317 return IRECV_SUCCESS;
221} 318}
222 319
223int irecv_set_sender(irecv_device_t* device, irecv_send_callback callback) { 320irecv_error_t irecv_set_sender(irecv_device_t* device, irecv_send_callback callback) {
321 if(device == NULL) {
322 return IRECV_ERROR_NO_DEVICE;
323 }
324
224 device->send_callback = callback; 325 device->send_callback = callback;
225 return IRECV_SUCCESS; 326 return IRECV_SUCCESS;
226} 327}