summaryrefslogtreecommitdiffstats
path: root/src/libirecovery.c
diff options
context:
space:
mode:
authorGravatar Joshua Hill2010-05-21 04:05:32 -0400
committerGravatar Joshua Hill2010-05-21 04:05:32 -0400
commit442363a01ef44e84eda3e22c71dd2de424f5121e (patch)
tree9e8ca5c4074c6596795efb568ede0b40bfe95719 /src/libirecovery.c
parentc4477844178978ef36a607a911712ed4c9c6904a (diff)
downloadlibirecovery-442363a01ef44e84eda3e22c71dd2de424f5121e.tar.gz
libirecovery-442363a01ef44e84eda3e22c71dd2de424f5121e.tar.bz2
Changed the API a bit to closer match libimobiledevice and added function to get ECID
Diffstat (limited to 'src/libirecovery.c')
-rw-r--r--src/libirecovery.c354
1 files changed, 169 insertions, 185 deletions
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 @@
25#include "libirecovery.h" 25#include "libirecovery.h"
26 26
27#define BUFFER_SIZE 0x1000 27#define BUFFER_SIZE 0x1000
28#define debug(...) if(device->debug) fprintf(stderr, __VA_ARGS__) 28#define debug(...) if(client->debug) fprintf(stderr, __VA_ARGS__)
29 29
30const char* irecv_error_invalid_input = "Invalid input"; 30const char* irecv_error_invalid_input = "Invalid input";
31const char* irecv_error_unknown = "Unknown error"; 31const char* irecv_error_unknown = "Unknown error";
@@ -39,40 +39,22 @@ const char* irecv_error_success = "Command completed successfully";
39const char* irecv_error_usb_upload = "Unable to upload data to device"; 39const char* irecv_error_usb_upload = "Unable to upload data to device";
40const char* irecv_error_usb_configuration = "Unable to set device configuration"; 40const char* irecv_error_usb_configuration = "Unable to set device configuration";
41 41
42int irecv_default_sender(irecv_device_t* device, unsigned char* data, int size); 42int irecv_default_sender(irecv_client_t client, unsigned char* data, int size);
43int irecv_default_receiver(irecv_device_t* device, unsigned char* data, int size); 43int irecv_default_receiver(irecv_client_t client, unsigned char* data, int size);
44 44
45irecv_device_t* irecv_init() { 45irecv_error_t irecv_open(irecv_client_t* pclient, const char* uuid) {
46 struct libusb_context* usb_context = NULL;
47
48 libusb_init(&usb_context);
49 irecv_device_t* device = (irecv_device_t*) malloc(sizeof(irecv_device_t));
50 if (device == NULL) {
51 return NULL;
52 }
53 memset(device, '\0', sizeof(irecv_device_t));
54
55 //irecv_set_receiver(device, &irecv_default_receiver);
56 //irecv_set_sender(device, &irecv_default_sender);
57 device->context = usb_context;
58 return device;
59}
60
61irecv_error_t irecv_open(irecv_device_t* device, const char *uuid) {
62 int i = 0; 46 int i = 0;
63 int usb_device_count = 0;
64 char serial[256]; 47 char serial[256];
65 struct libusb_device* usb_device = NULL; 48 struct libusb_device* usb_device = NULL;
49 struct libusb_context* usb_context = NULL;
66 struct libusb_device** usb_device_list = NULL; 50 struct libusb_device** usb_device_list = NULL;
67 struct libusb_device_handle* usb_handle = NULL; 51 struct libusb_device_handle* usb_handle = NULL;
68 struct libusb_device_descriptor usb_descriptor; 52 struct libusb_device_descriptor usb_descriptor;
69 53
70 if (device == NULL || device->context == NULL) { 54 *pclient = NULL;
71 return IRECV_ERROR_NO_DEVICE; 55 libusb_init(&usb_context);
72 } 56 irecv_error_t error = IRECV_E_SUCCESS;
73 57 int usb_device_count = libusb_get_device_list(usb_context, &usb_device_list);
74 irecv_error_t error = 0;
75 usb_device_count = libusb_get_device_list(device->context, &usb_device_list);
76 for (i = 0; i < usb_device_count; i++) { 58 for (i = 0; i < usb_device_count; i++) {
77 usb_device = usb_device_list[i]; 59 usb_device = usb_device_list[i];
78 libusb_get_device_descriptor(usb_device, &usb_descriptor); 60 libusb_get_device_descriptor(usb_device, &usb_descriptor);
@@ -87,147 +69,132 @@ irecv_error_t irecv_open(irecv_device_t* device, const char *uuid) {
87 libusb_open(usb_device, &usb_handle); 69 libusb_open(usb_device, &usb_handle);
88 if (usb_handle == NULL) { 70 if (usb_handle == NULL) {
89 libusb_free_device_list(usb_device_list, 1); 71 libusb_free_device_list(usb_device_list, 1);
90 return IRECV_ERROR_UNABLE_TO_CONNECT;
91 }
92
93 /* get serial number */
94 if (libusb_get_string_descriptor_ascii (usb_handle, usb_descriptor.iSerialNumber, serial, sizeof(serial)) < 0) {
95 libusb_free_device_list(usb_device_list, 1);
96 libusb_close(usb_handle); 72 libusb_close(usb_handle);
97 return IRECV_ERROR_UNABLE_TO_CONNECT; 73 libusb_exit(usb_context);
98 } 74 return IRECV_E_UNABLE_TO_CONNECT;
99
100 /* match uuid if required */
101 if (uuid != NULL) {
102 if (strcmp(uuid, serial)) {
103 libusb_close(usb_handle);
104 continue;
105 }
106 } 75 }
76 libusb_set_debug(usb_context, 3);
107 77
108 /* identified a valid recovery device */ 78 /* identified a valid recovery device */
109 libusb_free_device_list(usb_device_list, 1); 79 libusb_free_device_list(usb_device_list, 1);
110 80
111 device->handle = usb_handle; 81 irecv_client_t client = (irecv_client_t) malloc(sizeof(irecv_client_t));
112 device->uuid = strdup(serial); 82 if (client == NULL) {
113 device->mode = (irecv_mode_t) usb_descriptor.idProduct; 83 libusb_close(usb_handle);
114 84 libusb_exit(usb_context);
115 debug("opening UUID \"%s\"... ", device->uuid); 85 return IRECV_E_OUT_OF_MEMORY;
86 }
87 memset(client, '\0', sizeof(irecv_client_t));
88 client->handle = usb_handle;
89 client->context = usb_context;
90 client->mode = (irecv_mode_t) usb_descriptor.idProduct;
116 91
117 error = irecv_set_configuration(device, 1); 92 error = irecv_set_configuration(client, 1);
118 if(error != IRECV_SUCCESS) { 93 if(error != IRECV_E_SUCCESS) {
119 debug("setting configuration... ");
120 return error; 94 return error;
121 } 95 }
122 96
123 error = irecv_set_interface(device, 1, 1); 97 error = irecv_set_interface(client, 1, 1);
124 if(error != IRECV_SUCCESS) { 98 if(error != IRECV_E_SUCCESS) {
125 debug("setting interface... ");
126 return error; 99 return error;
127 } 100 }
128 101
129 return IRECV_SUCCESS; 102 *pclient = client;
103 printf("done");
104 return IRECV_E_SUCCESS;
130 } 105 }
131 } 106 }
132 } 107 }
133 108
134 return IRECV_ERROR_NO_DEVICE; 109 return IRECV_E_UNABLE_TO_CONNECT;
135} 110}
136 111
137irecv_error_t irecv_set_configuration(irecv_device_t* device, int configuration) { 112irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration) {
138 if(device == NULL || device->handle == NULL) { 113 if(client == NULL || client->handle == NULL) {
139 return IRECV_ERROR_NO_DEVICE; 114 return IRECV_E_NO_DEVICE;
140 } 115 }
116
117 debug("Setting to configuration %d", configuration);
141 118
142 int current = 0; 119 int current = 0;
143 libusb_get_configuration(device->handle, &current); 120 libusb_get_configuration(client->handle, &current);
144 if(current != configuration) { 121 if(current != configuration) {
145 if (libusb_set_configuration(device->handle, configuration) < 0) { 122 if (libusb_set_configuration(client->handle, configuration) < 0) {
146 return IRECV_ERROR_USB_CONFIGURATION; 123 return IRECV_E_USB_CONFIGURATION;
147 } 124 }
148 } 125 }
149 126
150 device->config = configuration; 127 client->config = configuration;
151 return IRECV_SUCCESS; 128 return IRECV_E_SUCCESS;
152} 129}
153 130
154irecv_error_t irecv_set_interface(irecv_device_t* device, int interface, int alt_interface) { 131irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface) {
155 if(device == NULL || device->handle == NULL) { 132 if(client == NULL || client->handle == NULL) {
156 return IRECV_ERROR_NO_DEVICE; 133 return IRECV_E_NO_DEVICE;
157 } 134 }
158 135
159 if (libusb_claim_interface(device->handle, interface) < 0) { 136 debug("Setting to interface %d:%d", interface, alt_interface);
160 return IRECV_ERROR_USB_INTERFACE; 137 libusb_reset_device(client->handle);
138
139 if (libusb_claim_interface(client->handle, interface) < 0) {
140 return IRECV_E_USB_INTERFACE;
161 } 141 }
162 142
163 if(libusb_set_interface_alt_setting(device->handle, interface, alt_interface) < 0) { 143 if(libusb_set_interface_alt_setting(client->handle, interface, alt_interface) < 0) {
164 return IRECV_ERROR_USB_INTERFACE; 144 return IRECV_E_USB_INTERFACE;
165 } 145 }
166 146
167 device->interface = interface; 147 client->interface = interface;
168 device->alt_interface = alt_interface; 148 client->alt_interface = alt_interface;
169 return IRECV_SUCCESS; 149 return IRECV_E_SUCCESS;
170} 150}
171 151
172irecv_error_t irecv_reset(irecv_device_t* device) { 152irecv_error_t irecv_reset(irecv_client_t client) {
173 if (device == NULL || device->handle != NULL) { 153 if (client == NULL || client->handle != NULL) {
174 return IRECV_ERROR_NO_DEVICE; 154 return IRECV_E_NO_DEVICE;
175 } 155 }
176 156
177 libusb_reset_device(device->handle); 157 libusb_reset_device(client->handle);
178 return IRECV_SUCCESS; 158 return IRECV_E_SUCCESS;
179} 159}
180 160
181irecv_error_t irecv_close(irecv_device_t* device) { 161irecv_error_t irecv_close(irecv_client_t client) {
182 if (device == NULL) { 162 if (client != NULL) {
183 return IRECV_ERROR_NO_DEVICE; 163 if (client->handle != NULL) {
184 } 164 libusb_release_interface(client->handle, 1);
185 165 libusb_close(client->handle);
186 if(device->handle != NULL) { 166 client->handle = NULL;
187 libusb_release_interface(device->handle, 0); 167 }
188 libusb_release_interface(device->handle, 1);
189 libusb_close(device->handle);
190 device->handle = NULL;
191 }
192
193 if(device->uuid != NULL) {
194 free(device->uuid);
195 }
196
197 return IRECV_SUCCESS;
198}
199 168
200irecv_error_t irecv_exit(irecv_device_t* device) { 169 if (client->context != NULL) {
201 if (device != NULL) { 170 libusb_exit(client->context);
202 if (device->handle != NULL) { 171 client->context = NULL;
203 irecv_close(device);
204 } 172 }
205 173
206 if (device->context != NULL) { 174 if(client->uuid != NULL) {
207 libusb_exit(device->context); 175 free(client->uuid);
208 device->context = NULL;
209 } 176 }
210 177
211 free(device); 178 free(client);
212 device = NULL; 179 client = NULL;
213 } 180 }
214 181
215 return IRECV_SUCCESS; 182 return IRECV_E_SUCCESS;
216} 183}
217 184
218irecv_error_t irecv_set_debug(irecv_device_t* device, int level) { 185irecv_error_t irecv_set_debug(irecv_client_t client, int level) {
219 if(device == NULL || device->context == NULL) { 186 if(client == NULL || client->context == NULL) {
220 return IRECV_ERROR_NO_DEVICE; 187 return IRECV_E_NO_DEVICE;
221 } 188 }
222 189
223 libusb_set_debug(device->context, level); 190 libusb_set_debug(client->context, level);
224 device->debug = level; 191 client->debug = level;
225 return IRECV_SUCCESS; 192 return IRECV_E_SUCCESS;
226} 193}
227 194
228irecv_error_t irecv_send(irecv_device_t* device, unsigned char* command) { 195irecv_error_t irecv_send(irecv_client_t client, unsigned char* command) {
229 if(device == NULL || device->handle == NULL) { 196 if(client == NULL || client->handle == NULL) {
230 return IRECV_ERROR_NO_DEVICE; 197 return IRECV_E_NO_DEVICE;
231 } 198 }
232 199
233 unsigned int length = strlen(command); 200 unsigned int length = strlen(command);
@@ -235,22 +202,22 @@ irecv_error_t irecv_send(irecv_device_t* device, unsigned char* command) {
235 length = 0xFF; 202 length = 0xFF;
236 } 203 }
237 204
238 if(device->send_callback != NULL) { 205 if(client->send_callback != NULL) {
239 // Call our user defined callback first, this must return a number of bytes to send 206 // Call our user defined callback first, this must return a number of bytes to send
240 // or zero to abort send. 207 // or zero to abort send.
241 length = device->send_callback(device, command, length); 208 length = client->send_callback(client, command, length);
242 } 209 }
243 210
244 if(length > 0) { 211 if(length > 0) {
245 irecv_send_command(device, command); 212 irecv_send_command(client, command);
246 } 213 }
247 214
248 return IRECV_SUCCESS; 215 return IRECV_E_SUCCESS;
249} 216}
250 217
251irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command) { 218irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) {
252 if(device == NULL || device->handle == NULL) { 219 if(client == NULL || client->handle == NULL) {
253 return IRECV_ERROR_NO_DEVICE; 220 return IRECV_E_NO_DEVICE;
254 } 221 }
255 222
256 unsigned int length = strlen(command); 223 unsigned int length = strlen(command);
@@ -259,20 +226,20 @@ irecv_error_t irecv_send_command(irecv_device_t* device, unsigned char* command)
259 } 226 }
260 227
261 if(length > 0) { 228 if(length > 0) {
262 libusb_control_transfer(device->handle, 0x40, 0, 0, 0, command, length+1, 100); 229 libusb_control_transfer(client->handle, 0x40, 0, 0, 0, command, length+1, 100);
263 } 230 }
264 231
265 return IRECV_SUCCESS; 232 return IRECV_E_SUCCESS;
266} 233}
267 234
268irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename) { 235irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) {
269 if(device == NULL || device->handle == NULL) { 236 if(client == NULL || client->handle == NULL) {
270 return IRECV_ERROR_NO_DEVICE; 237 return IRECV_E_NO_DEVICE;
271 } 238 }
272 239
273 FILE* file = fopen(filename, "rb"); 240 FILE* file = fopen(filename, "rb");
274 if (file == NULL) { 241 if (file == NULL) {
275 return IRECV_ERROR_FILE_NOT_FOUND; 242 return IRECV_E_FILE_NOT_FOUND;
276 } 243 }
277 244
278 fseek(file, 0, SEEK_END); 245 fseek(file, 0, SEEK_END);
@@ -282,7 +249,7 @@ irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename) {
282 unsigned char* buffer = (unsigned char*) malloc(length); 249 unsigned char* buffer = (unsigned char*) malloc(length);
283 if (buffer == NULL) { 250 if (buffer == NULL) {
284 fclose(file); 251 fclose(file);
285 return IRECV_ERROR_OUT_OF_MEMORY; 252 return IRECV_E_OUT_OF_MEMORY;
286 } 253 }
287 254
288 int bytes = fread(buffer, 1, length, file); 255 int bytes = fread(buffer, 1, length, file);
@@ -290,36 +257,36 @@ irecv_error_t irecv_send_file(irecv_device_t* device, const char* filename) {
290 257
291 if(bytes != length) { 258 if(bytes != length) {
292 free(buffer); 259 free(buffer);
293 return IRECV_ERROR_UNKNOWN; 260 return IRECV_E_UNKNOWN;
294 } 261 }
295 262
296 irecv_error_t error = irecv_send_buffer(device, buffer, length); 263 irecv_error_t error = irecv_send_buffer(client, buffer, length);
297 free(buffer); 264 free(buffer);
298 return error; 265 return error;
299} 266}
300 267
301irecv_error_t irecv_get_status(irecv_device_t* device, unsigned int* status) { 268irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) {
302 if(device == NULL || device->handle == NULL) { 269 if(client == NULL || client->handle == NULL) {
303 *status = 0; 270 *status = 0;
304 return IRECV_ERROR_NO_DEVICE; 271 return IRECV_E_NO_DEVICE;
305 } 272 }
306 273
307 unsigned char buffer[6]; 274 unsigned char buffer[6];
308 memset(buffer, '\0', 6); 275 memset(buffer, '\0', 6);
309 if(libusb_control_transfer(device->handle, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) { 276 if(libusb_control_transfer(client->handle, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) {
310 *status = 0; 277 *status = 0;
311 return IRECV_ERROR_USB_STATUS; 278 return IRECV_E_USB_STATUS;
312 } 279 }
313 280
314 debug("status: %d\n", (unsigned int) buffer[4]); 281 debug("status: %d\n", (unsigned int) buffer[4]);
315 *status = (unsigned int) buffer[4]; 282 *status = (unsigned int) buffer[4];
316 return IRECV_SUCCESS; 283 return IRECV_E_SUCCESS;
317} 284}
318 285
319irecv_error_t irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, unsigned int length) { 286irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length) {
320 irecv_error_t error = 0; 287 irecv_error_t error = 0;
321 if(device == NULL || device->handle == NULL) { 288 if(client == NULL || client->handle == NULL) {
322 return IRECV_ERROR_NO_DEVICE; 289 return IRECV_E_NO_DEVICE;
323 } 290 }
324 291
325 int last = length % 0x800; 292 int last = length % 0x800;
@@ -332,61 +299,61 @@ irecv_error_t irecv_send_buffer(irecv_device_t* device, unsigned char* buffer, u
332 unsigned int status = 0; 299 unsigned int status = 0;
333 for (i = 0; i < packets; i++) { 300 for (i = 0; i < packets; i++) {
334 int size = i + 1 < packets ? 0x800 : last; 301 int size = i + 1 < packets ? 0x800 : last;
335 int bytes = libusb_control_transfer(device->handle, 0x21, 1, 0, 0, &buffer[i * 0x800], size, 1000); 302 int bytes = libusb_control_transfer(client->handle, 0x21, 1, 0, 0, &buffer[i * 0x800], size, 1000);
336 if (bytes != size) { 303 if (bytes != size) {
337 return IRECV_ERROR_USB_UPLOAD; 304 return IRECV_E_USB_UPLOAD;
338 } 305 }
339 306
340 debug("Sent %d bytes\n", bytes); 307 debug("Sent %d bytes\n", bytes);
341 308
342 error = irecv_get_status(device, &status); 309 error = irecv_get_status(client, &status);
343 if (error != IRECV_SUCCESS) { 310 if (error != IRECV_E_SUCCESS) {
344 return error; 311 return error;
345 } 312 }
346 313
347 if(status != 5) { 314 if(status != 5) {
348 return IRECV_ERROR_USB_STATUS; 315 return IRECV_E_USB_STATUS;
349 } 316 }
350 317
351 } 318 }
352 319
353 libusb_control_transfer(device->handle, 0x21, 1, 0, 0, buffer, 0, 1000); 320 libusb_control_transfer(client->handle, 0x21, 1, 0, 0, buffer, 0, 1000);
354 for (i = 0; i < 3; i++) { 321 for (i = 0; i < 3; i++) {
355 error = irecv_get_status(device, &status); 322 error = irecv_get_status(client, &status);
356 if(error != IRECV_SUCCESS) { 323 if(error != IRECV_E_SUCCESS) {
357 return error; 324 return error;
358 } 325 }
359 } 326 }
360 327
361 return IRECV_SUCCESS; 328 return IRECV_E_SUCCESS;
362} 329}
363 330
364irecv_error_t irecv_receive(irecv_device_t* device) { 331irecv_error_t irecv_receive(irecv_client_t client) {
365 unsigned char buffer[BUFFER_SIZE]; 332 unsigned char buffer[BUFFER_SIZE];
366 memset(buffer, '\0', BUFFER_SIZE); 333 memset(buffer, '\0', BUFFER_SIZE);
367 if(device == NULL || device->handle == NULL) { 334 if(client == NULL || client->handle == NULL) {
368 return IRECV_ERROR_NO_DEVICE; 335 return IRECV_E_NO_DEVICE;
369 } 336 }
370 337
371 int bytes = 0; 338 int bytes = 0;
372 while(libusb_bulk_transfer(device->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) { 339 while(libusb_bulk_transfer(client->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) {
373 if(bytes > 0) { 340 if(bytes > 0) {
374 if(device->receive_callback != NULL) { 341 if(client->receive_callback != NULL) {
375 if(device->receive_callback(device, buffer, bytes) != bytes) { 342 if(client->receive_callback(client, buffer, bytes) != bytes) {
376 return IRECV_ERROR_UNKNOWN; 343 return IRECV_E_UNKNOWN;
377 } 344 }
378 } 345 }
379 } else break; 346 } else break;
380 } 347 }
381 348
382 return IRECV_SUCCESS; 349 return IRECV_E_SUCCESS;
383} 350}
384 351
385int irecv_default_sender(irecv_device_t* device, unsigned char* data, int size) { 352int irecv_default_sender(irecv_client_t client, unsigned char* data, int size) {
386 return size; 353 return size;
387} 354}
388 355
389int irecv_default_receiver(irecv_device_t* device, unsigned char* data, int size) { 356int irecv_default_receiver(irecv_client_t client, unsigned char* data, int size) {
390 int i = 0; 357 int i = 0;
391 for(i = 0; i < size; i++) { 358 for(i = 0; i < size; i++) {
392 printf("%c", data[i]); 359 printf("%c", data[i]);
@@ -394,72 +361,89 @@ int irecv_default_receiver(irecv_device_t* device, unsigned char* data, int size
394 return size; 361 return size;
395} 362}
396 363
397irecv_error_t irecv_set_receiver(irecv_device_t* device, irecv_receive_callback callback) { 364irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback) {
398 if(device == NULL) { 365 if(client == NULL) {
399 return IRECV_ERROR_NO_DEVICE; 366 return IRECV_E_NO_DEVICE;
400 } 367 }
401 368
402 device->receive_callback = callback; 369 client->receive_callback = callback;
403 return IRECV_SUCCESS; 370 return IRECV_E_SUCCESS;
404} 371}
405 372
406irecv_error_t irecv_set_sender(irecv_device_t* device, irecv_send_callback callback) { 373irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callback) {
407 if(device == NULL) { 374 if(client == NULL) {
408 return IRECV_ERROR_NO_DEVICE; 375 return IRECV_E_NO_DEVICE;
409 } 376 }
410 377
411 device->send_callback = callback; 378 client->send_callback = callback;
412 return IRECV_SUCCESS; 379 return IRECV_E_SUCCESS;
413} 380}
414 381
415irecv_error_t irecv_getenv(irecv_device_t* device, unsigned char** var) { 382irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) {
416 unsigned char* value = (unsigned char*) malloc(0x200); 383 unsigned char* value = (unsigned char*) malloc(0x200);
417 if(value == NULL) { 384 if(value == NULL) {
418 return IRECV_ERROR_OUT_OF_MEMORY; 385 return IRECV_E_OUT_OF_MEMORY;
419 } 386 }
420 387
421 int ret = libusb_control_transfer(device->handle, 0xC0, 0, 0, 0, value, 0x200, 500); 388 int ret = libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, value, 0x200, 500);
422 if(ret < 0) { 389 if(ret < 0) {
423 return IRECV_ERROR_UNKNOWN; 390 return IRECV_E_UNKNOWN;
424 } 391 }
425 392
426 *var = value; 393 *var = value;
427 return IRECV_SUCCESS; 394 return IRECV_E_SUCCESS;
395}
396
397
398irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) {
399 char info[256];
400 memset(info, '\0', 256);
401 libusb_get_string_descriptor_ascii(client->handle, 3, info, 0x100);
402 debug("%s\n", info);
403
404 unsigned char* ecid_string = strstr(info, "ECID:");
405 if(ecid_string == NULL) {
406 *ecid = 0;
407 return IRECV_E_UNKNOWN;
408 }
409 sscanf(ecid_string, "ECID:%qX", ecid);
410
411 return IRECV_E_SUCCESS;
428} 412}
429 413
430const char* irecv_strerror(irecv_error_t error) { 414const char* irecv_strerror(irecv_error_t error) {
431 switch(error) { 415 switch(error) {
432 case IRECV_SUCCESS: 416 case IRECV_E_SUCCESS:
433 return irecv_error_success; 417 return irecv_error_success;
434 418
435 case IRECV_ERROR_NO_DEVICE: 419 case IRECV_E_NO_DEVICE:
436 return irecv_error_no_device; 420 return irecv_error_no_device;
437 421
438 case IRECV_ERROR_OUT_OF_MEMORY: 422 case IRECV_E_OUT_OF_MEMORY:
439 return irecv_error_out_of_memory; 423 return irecv_error_out_of_memory;
440 424
441 case IRECV_ERROR_UNABLE_TO_CONNECT: 425 case IRECV_E_UNABLE_TO_CONNECT:
442 return irecv_error_unable_to_connect; 426 return irecv_error_unable_to_connect;
443 427
444 case IRECV_ERROR_INVALID_INPUT: 428 case IRECV_E_INVALID_INPUT:
445 return irecv_error_invalid_input; 429 return irecv_error_invalid_input;
446 430
447 case IRECV_ERROR_UNKNOWN: 431 case IRECV_E_UNKNOWN:
448 return irecv_error_unknown; 432 return irecv_error_unknown;
449 433
450 case IRECV_ERROR_FILE_NOT_FOUND: 434 case IRECV_E_FILE_NOT_FOUND:
451 return irecv_error_file_not_found; 435 return irecv_error_file_not_found;
452 436
453 case IRECV_ERROR_USB_UPLOAD: 437 case IRECV_E_USB_UPLOAD:
454 return irecv_error_usb_upload; 438 return irecv_error_usb_upload;
455 439
456 case IRECV_ERROR_USB_STATUS: 440 case IRECV_E_USB_STATUS:
457 return irecv_error_usb_status; 441 return irecv_error_usb_status;
458 442
459 case IRECV_ERROR_USB_INTERFACE: 443 case IRECV_E_USB_INTERFACE:
460 return irecv_error_usb_interface; 444 return irecv_error_usb_interface;
461 445
462 case IRECV_ERROR_USB_CONFIGURATION: 446 case IRECV_E_USB_CONFIGURATION:
463 return irecv_error_usb_configuration; 447 return irecv_error_usb_configuration;
464 448
465 default: 449 default: