summaryrefslogtreecommitdiffstats
path: root/src/libirecovery.c
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/libirecovery.c
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/libirecovery.c')
-rw-r--r--src/libirecovery.c161
1 files changed, 131 insertions, 30 deletions
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}