summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Joshua Hill2010-05-26 00:56:36 -0400
committerGravatar Joshua Hill2010-05-26 00:56:36 -0400
commitce77e6ac8ead2cb4fd204c67eb4d8a67e9a8e608 (patch)
treeb8b65fc01acc901c776149a136c9f115e67d7b87
parent8482031ce77cb4914b5a04ba4704484cc6548dcd (diff)
downloadlibirecovery-ce77e6ac8ead2cb4fd204c67eb4d8a67e9a8e608.tar.gz
libirecovery-ce77e6ac8ead2cb4fd204c67eb4d8a67e9a8e608.tar.bz2
Began work on a new event based callback system
-rw-r--r--include/libirecovery.h47
-rw-r--r--src/irecovery.c118
-rw-r--r--src/libirecovery.c277
3 files changed, 258 insertions, 184 deletions
diff --git a/include/libirecovery.h b/include/libirecovery.h
index fdc418b..ab43663 100644
--- a/include/libirecovery.h
+++ b/include/libirecovery.h
@@ -25,29 +25,45 @@ enum {
25 kRecoveryMode2 = 0x1281, 25 kRecoveryMode2 = 0x1281,
26 kRecoveryMode3 = 0x1282, 26 kRecoveryMode3 = 0x1282,
27 kRecoveryMode4 = 0x1283, 27 kRecoveryMode4 = 0x1283,
28 kDfuMode = 0x1227 28 kDfuMode = 0x1227
29}; 29};
30 30
31typedef enum { 31typedef enum {
32 IRECV_E_SUCCESS = 0, 32 IRECV_E_SUCCESS = 0,
33 IRECV_E_NO_DEVICE = -1, 33 IRECV_E_NO_DEVICE = -1,
34 IRECV_E_OUT_OF_MEMORY = -2, 34 IRECV_E_OUT_OF_MEMORY = -2,
35 IRECV_E_UNABLE_TO_CONNECT = -3, 35 IRECV_E_UNABLE_TO_CONNECT = -3,
36 IRECV_E_INVALID_INPUT = -4, 36 IRECV_E_INVALID_INPUT = -4,
37 IRECV_E_FILE_NOT_FOUND = -5, 37 IRECV_E_FILE_NOT_FOUND = -5,
38 IRECV_E_USB_UPLOAD = -6, 38 IRECV_E_USB_UPLOAD = -6,
39 IRECV_E_USB_STATUS = -7, 39 IRECV_E_USB_STATUS = -7,
40 IRECV_E_USB_INTERFACE = -8, 40 IRECV_E_USB_INTERFACE = -8,
41 IRECV_E_USB_CONFIGURATION = -9, 41 IRECV_E_USB_CONFIGURATION = -9,
42 IRECV_E_UNKNOWN_ERROR = -255 42 IRECV_E_UNKNOWN_ERROR = -255
43} irecv_error_t; 43} irecv_error_t;
44 44
45typedef enum {
46 IRECV_DATA_RECV = 1,
47 IRECV_PRECOMMAND = 2,
48 IRECV_POSTCOMMAND = 3,
49 IRECV_CONNECTED = 4,
50 IRECV_DISCONNECTED = 5,
51 IRECV_PROGRESS = 6
52} irecv_event_type;
53
54typedef struct {
55 char* data;
56 irecv_event_type type;
57} irecv_event_t;
58
45struct irecv_client; 59struct irecv_client;
46typedef struct irecv_client* irecv_client_t; 60typedef struct irecv_client* irecv_client_t;
47 61
48typedef int(*irecv_send_callback)(irecv_client_t client, unsigned char* data, int size); 62typedef int(*irecv_send_callback)(irecv_client_t client, unsigned char* data, int size);
49typedef int(*irecv_receive_callback)(irecv_client_t client, unsigned char* data, int size); 63typedef int(*irecv_receive_callback)(irecv_client_t client, unsigned char* data, int size);
50 64
65typedef int(*irecv_event_cb_t)(irecv_client_t client, const irecv_event_t* event);
66
51struct irecv_client { 67struct irecv_client {
52 int debug; 68 int debug;
53 int config; 69 int config;
@@ -58,9 +74,12 @@ struct irecv_client {
58 libusb_device_handle* handle; 74 libusb_device_handle* handle;
59 irecv_send_callback send_callback; 75 irecv_send_callback send_callback;
60 irecv_receive_callback receive_callback; 76 irecv_receive_callback receive_callback;
77 irecv_event_cb_t precommand_callback;
78 irecv_event_cb_t postcommand_callback;
61}; 79};
62 80
63const char* irecv_strerror(irecv_error_t error); 81irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type, irecv_event_cb_t callback, void *user_data);
82irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type);
64irecv_error_t irecv_open(irecv_client_t* client); 83irecv_error_t irecv_open(irecv_client_t* client);
65irecv_error_t irecv_reset(irecv_client_t client); 84irecv_error_t irecv_reset(irecv_client_t client);
66irecv_error_t irecv_close(irecv_client_t client); 85irecv_error_t irecv_close(irecv_client_t client);
@@ -77,4 +96,4 @@ irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callba
77irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback); 96irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback);
78irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface); 97irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface);
79irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length); 98irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length);
80 99const char* irecv_strerror(irecv_error_t error);
diff --git a/src/irecovery.c b/src/irecovery.c
index 98b1e90..a623579 100644
--- a/src/irecovery.c
+++ b/src/irecovery.c
@@ -43,18 +43,18 @@ void print_shell_usage() {
43void parse_command(irecv_client_t client, unsigned char* command, unsigned int size) { 43void parse_command(irecv_client_t client, unsigned char* command, unsigned int size) {
44 char* cmd = strtok(strdup(command), " "); 44 char* cmd = strtok(strdup(command), " ");
45 debug("Executing %s %s\n", cmd, command); 45 debug("Executing %s %s\n", cmd, command);
46 if(!strcmp(cmd, "/exit")) { 46 if (!strcmp(cmd, "/exit")) {
47 quit = 1; 47 quit = 1;
48 } else 48 } else
49 49
50 if(!strcmp(cmd, "/help")) { 50 if (!strcmp(cmd, "/help")) {
51 print_shell_usage(); 51 print_shell_usage();
52 } else 52 } else
53 53
54 if(!strcmp(cmd, "/upload")) { 54 if (!strcmp(cmd, "/upload")) {
55 char* filename = strtok(NULL, " "); 55 char* filename = strtok(NULL, " ");
56 debug("Sending %s\n", filename); 56 debug("Sending %s\n", filename);
57 if(filename != NULL) { 57 if (filename != NULL) {
58 irecv_send_file(client, filename); 58 irecv_send_file(client, filename);
59 } 59 }
60 } 60 }
@@ -63,47 +63,14 @@ void parse_command(irecv_client_t client, unsigned char* command, unsigned int s
63 63
64int recv_callback(irecv_client_t client, unsigned char* data, int size) { 64int recv_callback(irecv_client_t client, unsigned char* data, int size) {
65 int i = 0; 65 int i = 0;
66 for(i = 0; i < size; i++) { 66 for (i = 0; i < size; i++) {
67 printf("%c", data[i]); 67 printf("%c", data[i]);
68 } 68 }
69 return size; 69 return size;
70} 70}
71 71
72int send_callback(irecv_client_t client, unsigned char* command, int size) { 72int send_callback(irecv_client_t client, unsigned char* command, int size) {
73 irecv_error_t error = 0;
74 if(command[0] == '/') {
75 parse_command(client, command, size);
76 return 0;
77 }
78
79 if(strstr(command, "getenv") != NULL) {
80 unsigned char* value = NULL;
81 error = irecv_send_command(client, command);
82 if(error != IRECV_E_SUCCESS) {
83 debug("%s\n", irecv_strerror(error));
84 return error;
85 }
86
87 error = irecv_getenv(client, &value);
88 if(error != IRECV_E_SUCCESS) {
89 debug("%s\n", irecv_strerror(error));
90 return error;
91 }
92
93 printf("%s\n", value);
94 free(value);
95 return 0;
96 }
97 73
98 if(!strcmp(command, "reboot")) {
99 error = irecv_send_command(client, command);
100 if(error != IRECV_E_SUCCESS) {
101 debug("%s\n", irecv_strerror(error));
102 return error;
103 }
104 quit = 1;
105 return 0;
106 }
107 74
108 return size; 75 return size;
109} 76}
@@ -119,24 +86,25 @@ void append_command_to_history(char* cmd) {
119 86
120void init_shell(irecv_client_t client) { 87void init_shell(irecv_client_t client) {
121 irecv_error_t error = 0; 88 irecv_error_t error = 0;
122 //load_command_history(); 89 load_command_history();
123 irecv_set_sender(client, &send_callback);
124 irecv_set_receiver(client, &recv_callback); 90 irecv_set_receiver(client, &recv_callback);
125 while(!quit) { 91 irecv_event_subscribe(client, IRECV_PRECOMMAND, &precommand_cb, NULL);
92 irecv_event_subscribe(client, IRECV_POSTCOMMAND, &postcommand_cb, NULL);
93 while (!quit) {
126 error = irecv_receive(client); 94 error = irecv_receive(client);
127 if(error != IRECV_E_SUCCESS) { 95 if (error != IRECV_E_SUCCESS) {
128 debug("%s\n", irecv_strerror(error)); 96 debug("%s\n", irecv_strerror(error));
129 break; 97 break;
130 } 98 }
131 99
132 char* cmd = readline("> "); 100 char* cmd = readline("> ");
133 if(cmd && *cmd) { 101 if (cmd && *cmd) {
134 error = irecv_send(client, cmd); 102 error = irecv_send_command(client, cmd);
135 if(error != IRECV_E_SUCCESS) { 103 if (error != IRECV_E_SUCCESS) {
136 quit = 1; 104 quit = 1;
137 } 105 }
138 106
139 //append_command_to_history(cmd); 107 append_command_to_history(cmd);
140 free(cmd); 108 free(cmd);
141 } 109 }
142 } 110 }
@@ -155,13 +123,43 @@ void print_usage() {
155 exit(1); 123 exit(1);
156} 124}
157 125
126int precommand_cb(irecv_client_t client, const irecv_event_t* event) {
127 irecv_error_t error = 0;
128 if (event->data[0] == '/') {
129 parse_command(client, event->data, strlen(event->data));
130 return -1;
131 }
132 return 0;
133}
134
135int postcommand_cb(irecv_client_t client, const irecv_event_t* event) {
136 irecv_error_t error = 0;
137 if (strstr(event->data, "getenv") != NULL) {
138 unsigned char* value = NULL;
139 error = irecv_getenv(client, &value);
140 if (error != IRECV_E_SUCCESS) {
141 debug("%s\n", irecv_strerror(error));
142 return error;
143 }
144
145 printf("%s\n", value);
146 free(value);
147 }
148
149 if (!strcmp(event->data, "reboot")) {
150 quit = 1;
151 }
152
153 return 0;
154}
155
158int main(int argc, char** argv) { 156int main(int argc, char** argv) {
159 int i = 0; 157 int i = 0;
160 int opt = 0; 158 int opt = 0;
161 int action = 0; 159 int action = 0;
162 char* argument = NULL; 160 char* argument = NULL;
163 irecv_error_t error = 0; 161 irecv_error_t error = 0;
164 if(argc == 1) print_usage(); 162 if (argc == 1) print_usage();
165 while ((opt = getopt(argc, argv, "vhrsc:f:k::")) > 0) { 163 while ((opt = getopt(argc, argv, "vhrsc:f:k::")) > 0) {
166 switch (opt) { 164 switch (opt) {
167 case 'v': 165 case 'v':
@@ -202,20 +200,22 @@ int main(int argc, char** argv) {
202 } 200 }
203 201
204 irecv_client_t client = NULL; 202 irecv_client_t client = NULL;
205 for(i = 0; i <= 5; i++) { 203 for (i = 0; i <= 5; i++) {
206 debug("Attempting to connect... \n"); 204 debug("Attempting to connect... \n");
207 205
208 if(irecv_open(&client) != IRECV_E_SUCCESS) sleep(1); 206 if (irecv_open(&client) != IRECV_E_SUCCESS)
209 else break; 207 sleep(1);
208 else
209 break;
210 210
211 if(i == 5) { 211 if (i == 5) {
212 return -1; 212 return -1;
213 } 213 }
214 } 214 }
215 215
216 if(verbose) irecv_set_debug(client, verbose); 216 if (verbose) irecv_set_debug(client, verbose);
217 217
218 switch(action) { 218 switch (action) {
219 case kResetDevice: 219 case kResetDevice:
220 irecv_reset(client); 220 irecv_reset(client);
221 break; 221 break;
@@ -231,9 +231,9 @@ int main(int argc, char** argv) {
231 break; 231 break;
232 232
233 case kSendExploit: 233 case kSendExploit:
234 if(argument != NULL) { 234 if (argument != NULL) {
235 error = irecv_send_file(client, argument); 235 error = irecv_send_file(client, argument);
236 if(error != IRECV_E_SUCCESS) { 236 if (error != IRECV_E_SUCCESS) {
237 debug("%s\n", irecv_strerror(error)); 237 debug("%s\n", irecv_strerror(error));
238 break; 238 break;
239 } 239 }
diff --git a/src/libirecovery.c b/src/libirecovery.c
index 6587fe0..8f029ed 100644
--- a/src/libirecovery.c
+++ b/src/libirecovery.c
@@ -41,6 +41,7 @@ irecv_error_t irecv_open(irecv_client_t* pclient) {
41 41
42 *pclient = NULL; 42 *pclient = NULL;
43 libusb_init(&usb_context); 43 libusb_init(&usb_context);
44 //libusb_init(NULL);
44 irecv_error_t error = IRECV_E_SUCCESS; 45 irecv_error_t error = IRECV_E_SUCCESS;
45 int usb_device_count = libusb_get_device_list(usb_context, &usb_device_list); 46 int usb_device_count = libusb_get_device_list(usb_context, &usb_device_list);
46 for (i = 0; i < usb_device_count; i++) { 47 for (i = 0; i < usb_device_count; i++) {
@@ -48,11 +49,10 @@ irecv_error_t irecv_open(irecv_client_t* pclient) {
48 libusb_get_device_descriptor(usb_device, &usb_descriptor); 49 libusb_get_device_descriptor(usb_device, &usb_descriptor);
49 if (usb_descriptor.idVendor == APPLE_VENDOR_ID) { 50 if (usb_descriptor.idVendor == APPLE_VENDOR_ID) {
50 /* verify this device is in a mode we understand */ 51 /* verify this device is in a mode we understand */
51 if (usb_descriptor.idProduct == kRecoveryMode1 || 52 if (usb_descriptor.idProduct == kRecoveryMode1 || usb_descriptor.idProduct
52 usb_descriptor.idProduct == kRecoveryMode2 || 53 == kRecoveryMode2 || usb_descriptor.idProduct == kRecoveryMode3
53 usb_descriptor.idProduct == kRecoveryMode3 || 54 || usb_descriptor.idProduct == kRecoveryMode4 || usb_descriptor.idProduct
54 usb_descriptor.idProduct == kRecoveryMode4 || 55 == kDfuMode) {
55 usb_descriptor.idProduct == kDfuMode) {
56 56
57 libusb_open(usb_device, &usb_handle); 57 libusb_open(usb_device, &usb_handle);
58 if (usb_handle == NULL) { 58 if (usb_handle == NULL) {
@@ -63,7 +63,7 @@ irecv_error_t irecv_open(irecv_client_t* pclient) {
63 } 63 }
64 libusb_set_debug(usb_context, 3); 64 libusb_set_debug(usb_context, 3);
65 65
66 libusb_free_device_list(usb_device_list, 0); 66 libusb_free_device_list(usb_device_list, 1);
67 67
68 irecv_client_t client = (irecv_client_t) malloc(sizeof(struct irecv_client)); 68 irecv_client_t client = (irecv_client_t) malloc(sizeof(struct irecv_client));
69 if (client == NULL) { 69 if (client == NULL) {
@@ -72,13 +72,18 @@ irecv_error_t irecv_open(irecv_client_t* pclient) {
72 return IRECV_E_OUT_OF_MEMORY; 72 return IRECV_E_OUT_OF_MEMORY;
73 } 73 }
74 memset(client, '\0', sizeof(struct irecv_client)); 74 memset(client, '\0', sizeof(struct irecv_client));
75 client->interface = -1; 75 client->interface = 0;
76 client->handle = usb_handle; 76 client->handle = usb_handle;
77 client->context = usb_context; 77 client->context = usb_context;
78 client->mode = usb_descriptor.idProduct; 78 client->mode = usb_descriptor.idProduct;
79 79
80 error = irecv_set_configuration(client, 1); 80 error = irecv_set_configuration(client, 1);
81 if(error != IRECV_E_SUCCESS) { 81 if (error != IRECV_E_SUCCESS) {
82 return error;
83 }
84
85 error = irecv_set_interface(client, 1, 1);
86 if (error != IRECV_E_SUCCESS) {
82 return error; 87 return error;
83 } 88 }
84 89
@@ -92,30 +97,30 @@ irecv_error_t irecv_open(irecv_client_t* pclient) {
92} 97}
93 98
94irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration) { 99irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration) {
95 if(client == NULL || client->handle == NULL) { 100 if (client == NULL || client->handle == NULL) {
96 return IRECV_E_NO_DEVICE; 101 return IRECV_E_NO_DEVICE;
97 } 102 }
98 103
99 debug("Setting to configuration %d", configuration); 104 debug("Setting to configuration %d", configuration);
100 105
101 int current = 0; 106 int current = 0;
102 libusb_get_configuration(client->handle, &current); 107 libusb_get_configuration(client->handle, &current);
103 if(current != configuration) { 108 if (current != configuration) {
104 if (libusb_set_configuration(client->handle, configuration) < 0) { 109 if (libusb_set_configuration(client->handle, configuration) < 0) {
105 return IRECV_E_USB_CONFIGURATION; 110 return IRECV_E_USB_CONFIGURATION;
106 } 111 }
107 } 112 }
108 113
109 client->config = configuration; 114 client->config = configuration;
110 return IRECV_E_SUCCESS; 115 return IRECV_E_SUCCESS;
111} 116}
112 117
113irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface) { 118irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface) {
114 if(client == NULL || client->handle == NULL) { 119 if (client == NULL || client->handle == NULL) {
115 return IRECV_E_NO_DEVICE; 120 return IRECV_E_NO_DEVICE;
116 } 121 }
117 122
118 if(client->interface == interface) { 123 if (client->interface == interface) {
119 return IRECV_E_SUCCESS; 124 return IRECV_E_SUCCESS;
120 } 125 }
121 126
@@ -123,11 +128,11 @@ irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_
123 if (libusb_claim_interface(client->handle, interface) < 0) { 128 if (libusb_claim_interface(client->handle, interface) < 0) {
124 return IRECV_E_USB_INTERFACE; 129 return IRECV_E_USB_INTERFACE;
125 } 130 }
126 131
127 if(libusb_set_interface_alt_setting(client->handle, interface, alt_interface) < 0) { 132 if (libusb_set_interface_alt_setting(client->handle, interface, alt_interface) < 0) {
128 return IRECV_E_USB_INTERFACE; 133 return IRECV_E_USB_INTERFACE;
129 } 134 }
130 135
131 client->interface = interface; 136 client->interface = interface;
132 client->alt_interface = alt_interface; 137 client->alt_interface = alt_interface;
133 return IRECV_E_SUCCESS; 138 return IRECV_E_SUCCESS;
@@ -139,15 +144,48 @@ irecv_error_t irecv_reset(irecv_client_t client) {
139 } 144 }
140 145
141 libusb_reset_device(client->handle); 146 libusb_reset_device(client->handle);
147
148 return IRECV_E_SUCCESS;
149}
150
151irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type, irecv_event_cb_t callback, void* user_data) {
152 switch(type) {
153 case IRECV_PRECOMMAND:
154 client->precommand_callback = callback;
155 break;
156
157 case IRECV_POSTCOMMAND:
158 client->postcommand_callback = callback;
159 break;
160
161 default:
162 return IRECV_E_UNKNOWN_ERROR;
163 }
164
165 return IRECV_E_SUCCESS;
166}
167
168irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type) {
169 switch(type) {
170 case IRECV_PRECOMMAND:
171 client->precommand_callback = NULL;
172 break;
173
174 case IRECV_POSTCOMMAND:
175 client->postcommand_callback = NULL;
176 break;
177
178 default:
179 return IRECV_E_UNKNOWN_ERROR;
180 }
181
142 return IRECV_E_SUCCESS; 182 return IRECV_E_SUCCESS;
143} 183}
144 184
145irecv_error_t irecv_close(irecv_client_t client) { 185irecv_error_t irecv_close(irecv_client_t client) {
146 if (client != NULL) { 186 if (client != NULL) {
147 if (client->handle != NULL) { 187 if (client->handle != NULL) {
148 if(client->interface >= 0) { 188 libusb_release_interface(client->handle, 1);
149 libusb_release_interface(client->handle, client->interface);
150 }
151 libusb_close(client->handle); 189 libusb_close(client->handle);
152 client->handle = NULL; 190 client->handle = NULL;
153 } 191 }
@@ -165,32 +203,32 @@ irecv_error_t irecv_close(irecv_client_t client) {
165} 203}
166 204
167irecv_error_t irecv_set_debug(irecv_client_t client, int level) { 205irecv_error_t irecv_set_debug(irecv_client_t client, int level) {
168 if(client == NULL || client->context == NULL) { 206 if (client == NULL || client->context == NULL) {
169 return IRECV_E_NO_DEVICE; 207 return IRECV_E_NO_DEVICE;
170 } 208 }
171 209
172 libusb_set_debug(client->context, level); 210 libusb_set_debug(client->context, level);
173 client->debug = level; 211 client->debug = level;
174 return IRECV_E_SUCCESS; 212 return IRECV_E_SUCCESS;
175} 213}
176 214
177irecv_error_t irecv_send(irecv_client_t client, unsigned char* command) { 215irecv_error_t irecv_send(irecv_client_t client, unsigned char* command) {
178 if(client == NULL || client->handle == NULL) { 216 if (client == NULL || client->handle == NULL) {
179 return IRECV_E_NO_DEVICE; 217 return IRECV_E_NO_DEVICE;
180 } 218 }
181 219
182 unsigned int length = strlen(command); 220 unsigned int length = strlen(command);
183 if(length >= 0x100) { 221 if (length >= 0x100) {
184 length = 0xFF; 222 length = 0xFF;
185 } 223 }
186 224
187 if(client->send_callback != NULL) { 225 if (client->send_callback != NULL) {
188 // Call our user defined callback first, this must return a number of bytes to send 226 // Call our user defined callback first, this must return a number of bytes to send
189 // or zero to abort send. 227 // or zero to abort send.
190 length = client->send_callback(client, command, length); 228 length = client->send_callback(client, command, length);
191 } 229 }
192 230
193 if(length > 0) { 231 if (length > 0) {
194 irecv_send_command(client, command); 232 irecv_send_command(client, command);
195 } 233 }
196 234
@@ -198,32 +236,49 @@ irecv_error_t irecv_send(irecv_client_t client, unsigned char* command) {
198} 236}
199 237
200irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) { 238irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) {
201 if(client == NULL || client->handle == NULL) { 239 if (client == NULL || client->handle == NULL) {
202 return IRECV_E_NO_DEVICE; 240 return IRECV_E_NO_DEVICE;
203 } 241 }
242 /*
243 irecv_error_t error = irecv_set_interface(client, 1, 1);
244 if(error != IRECV_E_SUCCESS) {
245 return error;
246 }
247 */
248 unsigned int length = strlen(command);
249 if (length >= 0x100) {
250 length = 0xFF;
251 }
204 252
205 irecv_error_t error = irecv_set_interface(client, 1, 1); 253 irecv_event_t event;
206 if(error != IRECV_E_SUCCESS) { 254 if(client->precommand_callback != NULL) {
207 return error; 255 event.data = command;
256 event.type = IRECV_PRECOMMAND;
257 if(client->precommand_callback(client, &event)) {
258 return IRECV_E_SUCCESS;
259 }
208 } 260 }
209 261
210 unsigned int length = strlen(command); 262 if (length > 0) {
211 if(length >= 0x100) { 263 libusb_control_transfer(client->handle, 0x40, 0, 0, 0, command, length + 1, 100);
212 length = 0xFF;
213 } 264 }
214 265
215 if(length > 0) { 266 if(client->postcommand_callback != NULL) {
216 libusb_control_transfer(client->handle, 0x40, 0, 0, 0, command, length+1, 100); 267 event.data = command;
268 event.type = IRECV_POSTCOMMAND;
269 if(client->postcommand_callback(client, &event)) {
270 return IRECV_E_SUCCESS;
271 }
217 } 272 }
218 273
219 return IRECV_E_SUCCESS; 274 return IRECV_E_SUCCESS;
220} 275}
221 276
222irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) { 277irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) {
223 if(client == NULL || client->handle == NULL) { 278 if (client == NULL || client->handle == NULL) {
224 return IRECV_E_NO_DEVICE; 279 return IRECV_E_NO_DEVICE;
225 } 280 }
226 281
227 FILE* file = fopen(filename, "rb"); 282 FILE* file = fopen(filename, "rb");
228 if (file == NULL) { 283 if (file == NULL) {
229 return IRECV_E_FILE_NOT_FOUND; 284 return IRECV_E_FILE_NOT_FOUND;
@@ -242,7 +297,7 @@ irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) {
242 int bytes = fread(buffer, 1, length, file); 297 int bytes = fread(buffer, 1, length, file);
243 fclose(file); 298 fclose(file);
244 299
245 if(bytes != length) { 300 if (bytes != length) {
246 free(buffer); 301 free(buffer);
247 return IRECV_E_UNKNOWN_ERROR; 302 return IRECV_E_UNKNOWN_ERROR;
248 } 303 }
@@ -253,23 +308,23 @@ irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) {
253} 308}
254 309
255irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) { 310irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) {
256 if(client == NULL || client->handle == NULL) { 311 if (client == NULL || client->handle == NULL) {
257 *status = 0; 312 *status = 0;
258 return IRECV_E_NO_DEVICE; 313 return IRECV_E_NO_DEVICE;
259 } 314 }
260 315 /*
261 irecv_error_t error = irecv_set_interface(client, 1, 1); 316 irecv_error_t error = irecv_set_interface(client, 1, 1);
262 if(error != IRECV_E_SUCCESS) { 317 if(error != IRECV_E_SUCCESS) {
263 return error; 318 return error;
264 } 319 }
265 320 */
266 unsigned char buffer[6]; 321 unsigned char buffer[6];
267 memset(buffer, '\0', 6); 322 memset(buffer, '\0', 6);
268 if(libusb_control_transfer(client->handle, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) { 323 if (libusb_control_transfer(client->handle, 0xA1, 3, 0, 0, buffer, 6, 1000) != 6) {
269 *status = 0; 324 *status = 0;
270 return IRECV_E_USB_STATUS; 325 return IRECV_E_USB_STATUS;
271 } 326 }
272 327
273 debug("status: %d\n", (unsigned int) buffer[4]); 328 debug("status: %d\n", (unsigned int) buffer[4]);
274 *status = (unsigned int) buffer[4]; 329 *status = (unsigned int) buffer[4];
275 return IRECV_E_SUCCESS; 330 return IRECV_E_SUCCESS;
@@ -277,15 +332,15 @@ irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) {
277 332
278irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length) { 333irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length) {
279 irecv_error_t error = 0; 334 irecv_error_t error = 0;
280 if(client == NULL || client->handle == NULL) { 335 if (client == NULL || client->handle == NULL) {
281 return IRECV_E_NO_DEVICE; 336 return IRECV_E_NO_DEVICE;
282 } 337 }
283 338 /*
284 error = irecv_set_interface(client, 1, 1); 339 error = irecv_set_interface(client, 1, 1);
285 if(error != IRECV_E_SUCCESS) { 340 if(error != IRECV_E_SUCCESS) {
286 return error; 341 return error;
287 } 342 }
288 343 */
289 int last = length % 0x800; 344 int last = length % 0x800;
290 int packets = length / 0x800; 345 int packets = length / 0x800;
291 if (last != 0) { 346 if (last != 0) {
@@ -296,11 +351,12 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
296 unsigned int status = 0; 351 unsigned int status = 0;
297 for (i = 0; i < packets; i++) { 352 for (i = 0; i < packets; i++) {
298 int size = i + 1 < packets ? 0x800 : last; 353 int size = i + 1 < packets ? 0x800 : last;
299 int bytes = libusb_control_transfer(client->handle, 0x21, 1, 0, 0, &buffer[i * 0x800], size, 1000); 354 int bytes = libusb_control_transfer(client->handle, 0x21, 1, 0, 0, &buffer[i * 0x800],
355 size, 1000);
300 if (bytes != size) { 356 if (bytes != size) {
301 return IRECV_E_USB_UPLOAD; 357 return IRECV_E_USB_UPLOAD;
302 } 358 }
303 359
304 debug("Sent %d bytes\n", bytes); 360 debug("Sent %d bytes\n", bytes);
305 361
306 error = irecv_get_status(client, &status); 362 error = irecv_get_status(client, &status);
@@ -308,7 +364,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
308 return error; 364 return error;
309 } 365 }
310 366
311 if(status != 5) { 367 if (status != 5) {
312 return IRECV_E_USB_UPLOAD; 368 return IRECV_E_USB_UPLOAD;
313 } 369 }
314 370
@@ -317,7 +373,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
317 libusb_control_transfer(client->handle, 0x21, 1, 0, 0, buffer, 0, 1000); 373 libusb_control_transfer(client->handle, 0x21, 1, 0, 0, buffer, 0, 1000);
318 for (i = 0; i < 3; i++) { 374 for (i = 0; i < 3; i++) {
319 error = irecv_get_status(client, &status); 375 error = irecv_get_status(client, &status);
320 if(error != IRECV_E_SUCCESS) { 376 if (error != IRECV_E_SUCCESS) {
321 return error; 377 return error;
322 } 378 }
323 } 379 }
@@ -328,26 +384,27 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
328irecv_error_t irecv_receive(irecv_client_t client) { 384irecv_error_t irecv_receive(irecv_client_t client) {
329 unsigned char buffer[BUFFER_SIZE]; 385 unsigned char buffer[BUFFER_SIZE];
330 memset(buffer, '\0', BUFFER_SIZE); 386 memset(buffer, '\0', BUFFER_SIZE);
331 if(client == NULL || client->handle == NULL) { 387 if (client == NULL || client->handle == NULL) {
332 return IRECV_E_NO_DEVICE; 388 return IRECV_E_NO_DEVICE;
333 } 389 }
334 390 /*
335 irecv_error_t error = irecv_set_interface(client, 1, 1); 391 irecv_error_t error = irecv_set_interface(client, 1, 1);
336 if(error != IRECV_E_SUCCESS) { 392 if(error != IRECV_E_SUCCESS) {
337 return error; 393 return error;
338 } 394 }
339 395 */
340 int bytes = 0; 396 int bytes = 0;
341 while(libusb_bulk_transfer(client->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) { 397 while (libusb_bulk_transfer(client->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) {
342 if(bytes > 0) { 398 if (bytes > 0) {
343 if(client->receive_callback != NULL) { 399 if (client->receive_callback != NULL) {
344 if(client->receive_callback(client, buffer, bytes) != bytes) { 400 if (client->receive_callback(client, buffer, bytes) != bytes) {
345 return IRECV_E_UNKNOWN_ERROR; 401 return IRECV_E_UNKNOWN_ERROR;
346 } 402 }
347 } 403 }
348 } else break; 404 } else
405 break;
349 } 406 }
350 407
351 return IRECV_E_SUCCESS; 408 return IRECV_E_SUCCESS;
352} 409}
353 410
@@ -357,47 +414,47 @@ int irecv_default_sender(irecv_client_t client, unsigned char* data, int size) {
357 414
358int irecv_default_receiver(irecv_client_t client, unsigned char* data, int size) { 415int irecv_default_receiver(irecv_client_t client, unsigned char* data, int size) {
359 int i = 0; 416 int i = 0;
360 for(i = 0; i < size; i++) { 417 for (i = 0; i < size; i++) {
361 printf("%c", data[i]); 418 printf("%c", data[i]);
362 } 419 }
363 return size; 420 return size;
364} 421}
365 422
366irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback) { 423irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback) {
367 if(client == NULL) { 424 if (client == NULL) {
368 return IRECV_E_NO_DEVICE; 425 return IRECV_E_NO_DEVICE;
369 } 426 }
370 427
371 client->receive_callback = callback; 428 client->receive_callback = callback;
372 return IRECV_E_SUCCESS; 429 return IRECV_E_SUCCESS;
373} 430}
374 431
375irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callback) { 432irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callback) {
376 if(client == NULL) { 433 if (client == NULL) {
377 return IRECV_E_NO_DEVICE; 434 return IRECV_E_NO_DEVICE;
378 } 435 }
379 436
380 client->send_callback = callback; 437 client->send_callback = callback;
381 return IRECV_E_SUCCESS; 438 return IRECV_E_SUCCESS;
382} 439}
383 440
384irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) { 441irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) {
385 if(client == NULL || client->handle == NULL) { 442 if (client == NULL || client->handle == NULL) {
386 return IRECV_E_NO_DEVICE; 443 return IRECV_E_NO_DEVICE;
387 } 444 }
388 445 /*
389 irecv_error_t error = irecv_set_interface(client, 1, 1); 446 irecv_error_t error = irecv_set_interface(client, 1, 1);
390 if(error != IRECV_E_SUCCESS) { 447 if(error != IRECV_E_SUCCESS) {
391 return error; 448 return error;
392 } 449 }
393 450 */
394 unsigned char* value = (unsigned char*) malloc(256); 451 unsigned char* value = (unsigned char*) malloc(256);
395 if(value == NULL) { 452 if (value == NULL) {
396 return IRECV_E_OUT_OF_MEMORY; 453 return IRECV_E_OUT_OF_MEMORY;
397 } 454 }
398 455
399 int ret = libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, value, 256, 500); 456 int ret = libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, value, 256, 500);
400 if(ret < 0) { 457 if (ret < 0) {
401 return IRECV_E_UNKNOWN_ERROR; 458 return IRECV_E_UNKNOWN_ERROR;
402 } 459 }
403 460
@@ -405,12 +462,11 @@ irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) {
405 return IRECV_E_SUCCESS; 462 return IRECV_E_SUCCESS;
406} 463}
407 464
408
409irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) { 465irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) {
410 char info[256]; 466 char info[256];
411 memset(info, '\0', 256); 467 memset(info, '\0', 256);
412 468
413 if(client == NULL || client->handle == NULL) { 469 if (client == NULL || client->handle == NULL) {
414 return IRECV_E_NO_DEVICE; 470 return IRECV_E_NO_DEVICE;
415 } 471 }
416 472
@@ -418,7 +474,7 @@ irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) {
418 printf("%d: %s\n", strlen(info), info); 474 printf("%d: %s\n", strlen(info), info);
419 475
420 unsigned char* ecid_string = strstr(info, "ECID:"); 476 unsigned char* ecid_string = strstr(info, "ECID:");
421 if(ecid_string == NULL) { 477 if (ecid_string == NULL) {
422 *ecid = 0; 478 *ecid = 0;
423 return IRECV_E_UNKNOWN_ERROR; 479 return IRECV_E_UNKNOWN_ERROR;
424 } 480 }
@@ -428,56 +484,55 @@ irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) {
428 return IRECV_E_SUCCESS; 484 return IRECV_E_SUCCESS;
429} 485}
430 486
431
432irecv_error_t irecv_send_exploit(irecv_client_t client) { 487irecv_error_t irecv_send_exploit(irecv_client_t client) {
433 if(client == NULL || client->handle == NULL) { 488 if (client == NULL || client->handle == NULL) {
434 return IRECV_E_NO_DEVICE; 489 return IRECV_E_NO_DEVICE;
435 } 490 }
436 491 /*
437 irecv_error_t error = irecv_set_interface(client, 1, 1); 492 irecv_error_t error = irecv_set_interface(client, 1, 1);
438 if(error != IRECV_E_SUCCESS) { 493 if(error != IRECV_E_SUCCESS) {
439 return error; 494 return error;
440 } 495 }
441 496 */
442 libusb_control_transfer(client->handle, 0x21, 2, 0, 0, NULL, 0, 100); 497 libusb_control_transfer(client->handle, 0x21, 2, 0, 0, NULL, 0, 100);
443 return IRECV_E_SUCCESS; 498 return IRECV_E_SUCCESS;
444} 499}
445 500
446const char* irecv_strerror(irecv_error_t error) { 501const char* irecv_strerror(irecv_error_t error) {
447 switch(error) { 502 switch (error) {
448 case IRECV_E_SUCCESS: 503 case IRECV_E_SUCCESS:
449 return "Command completed successfully"; 504 return "Command completed successfully";
450 505
451 case IRECV_E_NO_DEVICE: 506 case IRECV_E_NO_DEVICE:
452 return "Unable to find device"; 507 return "Unable to find device";
453 508
454 case IRECV_E_OUT_OF_MEMORY: 509 case IRECV_E_OUT_OF_MEMORY:
455 return "Out of memory"; 510 return "Out of memory";
456 511
457 case IRECV_E_UNABLE_TO_CONNECT: 512 case IRECV_E_UNABLE_TO_CONNECT:
458 return "Unable to connect to device"; 513 return "Unable to connect to device";
459 514
460 case IRECV_E_INVALID_INPUT: 515 case IRECV_E_INVALID_INPUT:
461 return "Invalid input"; 516 return "Invalid input";
462 517
463 case IRECV_E_FILE_NOT_FOUND: 518 case IRECV_E_FILE_NOT_FOUND:
464 return "File not found"; 519 return "File not found";
465 520
466 case IRECV_E_USB_UPLOAD: 521 case IRECV_E_USB_UPLOAD:
467 return "Unable to upload data to device"; 522 return "Unable to upload data to device";
468 523
469 case IRECV_E_USB_STATUS: 524 case IRECV_E_USB_STATUS:
470 return "Unable to get device status"; 525 return "Unable to get device status";
471 526
472 case IRECV_E_USB_INTERFACE: 527 case IRECV_E_USB_INTERFACE:
473 return "Unable to set device interface"; 528 return "Unable to set device interface";
474 529
475 case IRECV_E_USB_CONFIGURATION: 530 case IRECV_E_USB_CONFIGURATION:
476 return "Unable to set device configuration"; 531 return "Unable to set device configuration";
477 532
478 default: 533 default:
479 return "Unknown error"; 534 return "Unknown error";
480 } 535 }
481 536
482 return NULL; 537 return NULL;
483} 538}