diff options
| -rw-r--r-- | TODO | 20 | ||||
| -rw-r--r-- | include/libirecovery.h | 10 | ||||
| -rw-r--r-- | src/irecovery.c | 21 | ||||
| -rw-r--r-- | src/libirecovery.c | 74 |
4 files changed, 102 insertions, 23 deletions
| @@ -1,10 +1,16 @@ | |||
| 1 | TODO List | 1 | TODO List |
| 2 | |||
| 3 | This is just a list of a couple things i've been meaning to get around to, but haven't had the chance. If you finish any of them you can go ahead and remove it from the list. | ||
| 4 | ------------------------------------------------ | 2 | ------------------------------------------------ |
| 5 | 3 | ||
| 6 | 1) Port irecovery to libusb1.0. I've already done this in some of my other projects, and I think westbaer's brach has already been ported but our branches forked off a long time ago. | 4 | 1) libirecovery debug should be as static variable so the client doesn't need to be passed and can be set only once. |
| 7 | 5 | 2) Need to implement irecv_saveenv() | |
| 8 | 2) Add support for getenv command. getenv sends the request variable back in a control message that can be fetched with usb_control_message(handle, 0xC0, 0, 0, 0, buffer, size, 500). | 6 | 3) Need to implement irecv_bootx() |
| 9 | 7 | 4) Neex to implement irecv_go() | |
| 10 | 3) Fix command line parsing so you can send arguments to commands. Currently if you try "irecovery -c bgcolor 0 0 0" only "bgcolor" will be sent and none of it's arguments. | 8 | 5) Need to implement irecv_bgcolor() |
| 9 | 6) Need to implememt irecv_setpicture() | ||
| 10 | 7) Need to impelemnt irecv_reboot() | ||
| 11 | 8) Should figure out a better place to store callbacks so the CONNECTED callback can actually be used | ||
| 12 | 9) would be nice to change to use asyncronous connections | ||
| 13 | 10) could add a function to identify whether we're connected to iBoot/iBEC/iBSS or DFU | ||
| 14 | 11) could add a function to identify which version we're connected to | ||
| 15 | 12) could add a function to return the device serial number | ||
| 16 | 13) fix command parsing to strip quotes \ No newline at end of file | ||
diff --git a/include/libirecovery.h b/include/libirecovery.h index d01e022..50ec5be 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h | |||
| @@ -16,6 +16,9 @@ | |||
| 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | **/ | 17 | **/ |
| 18 | 18 | ||
| 19 | #ifndef LIBIRECOVERY_H | ||
| 20 | #define LIBIRECOVERY_H | ||
| 21 | |||
| 19 | #include <libusb-1.0/libusb.h> | 22 | #include <libusb-1.0/libusb.h> |
| 20 | 23 | ||
| 21 | #define APPLE_VENDOR_ID 0x05AC | 24 | #define APPLE_VENDOR_ID 0x05AC |
| @@ -72,19 +75,22 @@ struct irecv_client { | |||
| 72 | libusb_device_handle* handle; | 75 | libusb_device_handle* handle; |
| 73 | irecv_event_cb_t progress_callback; | 76 | irecv_event_cb_t progress_callback; |
| 74 | irecv_event_cb_t received_callback; | 77 | irecv_event_cb_t received_callback; |
| 78 | irecv_event_cb_t connected_callback; | ||
| 75 | irecv_event_cb_t precommand_callback; | 79 | irecv_event_cb_t precommand_callback; |
| 76 | irecv_event_cb_t postcommand_callback; | 80 | irecv_event_cb_t postcommand_callback; |
| 81 | irecv_event_cb_t disconnected_callback; | ||
| 77 | }; | 82 | }; |
| 78 | 83 | ||
| 79 | irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type, irecv_event_cb_t callback, void *user_data); | 84 | irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type, irecv_event_cb_t callback, void *user_data); |
| 80 | irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type); | 85 | irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type); |
| 86 | irecv_error_t irecv_setenv(irecv_client_t client, const char* variable, const char* value); | ||
| 81 | irecv_error_t irecv_open(irecv_client_t* client); | 87 | irecv_error_t irecv_open(irecv_client_t* client); |
| 82 | irecv_error_t irecv_reset(irecv_client_t client); | 88 | irecv_error_t irecv_reset(irecv_client_t client); |
| 83 | irecv_error_t irecv_close(irecv_client_t client); | 89 | irecv_error_t irecv_close(irecv_client_t client); |
| 84 | irecv_error_t irecv_receive(irecv_client_t client); | 90 | irecv_error_t irecv_receive(irecv_client_t client); |
| 85 | irecv_error_t irecv_send_exploit(irecv_client_t client); | 91 | irecv_error_t irecv_send_exploit(irecv_client_t client); |
| 86 | irecv_error_t irecv_set_debug(irecv_client_t client, int level); | 92 | irecv_error_t irecv_set_debug(irecv_client_t client, int level); |
| 87 | irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var); | 93 | irecv_error_t irecv_getenv(irecv_client_t client, const char* variable, char** value); |
| 88 | irecv_error_t irecv_get_cpid(irecv_client_t client, unsigned int* cpid); | 94 | irecv_error_t irecv_get_cpid(irecv_client_t client, unsigned int* cpid); |
| 89 | irecv_error_t irecv_get_bdid(irecv_client_t client, unsigned int* bdid); | 95 | irecv_error_t irecv_get_bdid(irecv_client_t client, unsigned int* bdid); |
| 90 | irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid); | 96 | irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid); |
| @@ -95,3 +101,5 @@ irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration); | |||
| 95 | irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface); | 101 | irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface); |
| 96 | irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length); | 102 | irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length); |
| 97 | const char* irecv_strerror(irecv_error_t error); | 103 | const char* irecv_strerror(irecv_error_t error); |
| 104 | |||
| 105 | #endif | ||
diff --git a/src/irecovery.c b/src/irecovery.c index fcc745c..baae17e 100644 --- a/src/irecovery.c +++ b/src/irecovery.c | |||
| @@ -139,24 +139,33 @@ int precommand_cb(irecv_client_t client, const irecv_event_t* event) { | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | int postcommand_cb(irecv_client_t client, const irecv_event_t* event) { | 141 | int postcommand_cb(irecv_client_t client, const irecv_event_t* event) { |
| 142 | unsigned char* value = NULL; | 142 | char* value = NULL; |
| 143 | char* action = NULL; | ||
| 144 | char* command = NULL; | ||
| 145 | char* argument = NULL; | ||
| 146 | irecv_error_t error = IRECV_E_SUCCESS; | ||
| 147 | |||
| 143 | if (event->type == IRECV_POSTCOMMAND) { | 148 | if (event->type == IRECV_POSTCOMMAND) { |
| 144 | irecv_error_t error = 0; | 149 | command = strdup(event->data); |
| 145 | if (strstr(event->data, "getenv") != NULL) { | 150 | action = strtok(command, " "); |
| 146 | error = irecv_getenv(client, &value); | 151 | if (!strcmp(action, "getenv")) { |
| 152 | argument = strtok(NULL, " "); | ||
| 153 | error = irecv_getenv(client, argument, &value); | ||
| 147 | if (error != IRECV_E_SUCCESS) { | 154 | if (error != IRECV_E_SUCCESS) { |
| 148 | debug("%s\n", irecv_strerror(error)); | 155 | debug("%s\n", irecv_strerror(error)); |
| 156 | free(command); | ||
| 149 | return error; | 157 | return error; |
| 150 | } | 158 | } |
| 151 | printf("%s\n", value); | 159 | printf("%s\n", value); |
| 160 | free(value); | ||
| 152 | } | 161 | } |
| 153 | 162 | ||
| 154 | if (!strcmp(event->data, "reboot")) { | 163 | if (!strcmp(action, "reboot")) { |
| 155 | quit = 1; | 164 | quit = 1; |
| 156 | } | 165 | } |
| 157 | } | 166 | } |
| 158 | 167 | ||
| 159 | if (value != NULL) free(value); | 168 | if (command) free(command); |
| 160 | return 0; | 169 | return 0; |
| 161 | } | 170 | } |
| 162 | 171 | ||
diff --git a/src/libirecovery.c b/src/libirecovery.c index 4900fbf..05a162f 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c | |||
| @@ -152,6 +152,12 @@ irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type | |||
| 152 | client->received_callback = callback; | 152 | client->received_callback = callback; |
| 153 | break; | 153 | break; |
| 154 | 154 | ||
| 155 | case IRECV_PROGRESS: | ||
| 156 | client->progress_callback = callback; | ||
| 157 | |||
| 158 | case IRECV_CONNECTED: | ||
| 159 | client->connected_callback = callback; | ||
| 160 | |||
| 155 | case IRECV_PRECOMMAND: | 161 | case IRECV_PRECOMMAND: |
| 156 | client->precommand_callback = callback; | 162 | client->precommand_callback = callback; |
| 157 | break; | 163 | break; |
| @@ -160,8 +166,8 @@ irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event_type type | |||
| 160 | client->postcommand_callback = callback; | 166 | client->postcommand_callback = callback; |
| 161 | break; | 167 | break; |
| 162 | 168 | ||
| 163 | case IRECV_PROGRESS: | 169 | case IRECV_DISCONNECTED: |
| 164 | client->progress_callback = callback; | 170 | client->disconnected_callback = callback; |
| 165 | 171 | ||
| 166 | default: | 172 | default: |
| 167 | return IRECV_E_UNKNOWN_ERROR; | 173 | return IRECV_E_UNKNOWN_ERROR; |
| @@ -176,6 +182,12 @@ irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type ty | |||
| 176 | client->received_callback = NULL; | 182 | client->received_callback = NULL; |
| 177 | break; | 183 | break; |
| 178 | 184 | ||
| 185 | case IRECV_PROGRESS: | ||
| 186 | client->progress_callback = NULL; | ||
| 187 | |||
| 188 | case IRECV_CONNECTED: | ||
| 189 | client->connected_callback = NULL; | ||
| 190 | |||
| 179 | case IRECV_PRECOMMAND: | 191 | case IRECV_PRECOMMAND: |
| 180 | client->precommand_callback = NULL; | 192 | client->precommand_callback = NULL; |
| 181 | break; | 193 | break; |
| @@ -184,8 +196,8 @@ irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type ty | |||
| 184 | client->postcommand_callback = NULL; | 196 | client->postcommand_callback = NULL; |
| 185 | break; | 197 | break; |
| 186 | 198 | ||
| 187 | case IRECV_PROGRESS: | 199 | case IRECV_DISCONNECTED: |
| 188 | client->progress_callback = NULL; | 200 | client->disconnected_callback = NULL; |
| 189 | 201 | ||
| 190 | default: | 202 | default: |
| 191 | return IRECV_E_UNKNOWN_ERROR; | 203 | return IRECV_E_UNKNOWN_ERROR; |
| @@ -196,6 +208,15 @@ irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type ty | |||
| 196 | 208 | ||
| 197 | irecv_error_t irecv_close(irecv_client_t client) { | 209 | irecv_error_t irecv_close(irecv_client_t client) { |
| 198 | if (client != NULL) { | 210 | if (client != NULL) { |
| 211 | if(client->disconnected_callback != NULL) { | ||
| 212 | irecv_event_t event; | ||
| 213 | event.size = 0; | ||
| 214 | event.data = NULL; | ||
| 215 | event.progress = 0; | ||
| 216 | event.type = IRECV_DISCONNECTED; | ||
| 217 | client->disconnected_callback(client, &event); | ||
| 218 | } | ||
| 219 | |||
| 199 | if (client->handle != NULL) { | 220 | if (client->handle != NULL) { |
| 200 | libusb_release_interface(client->handle, client->interface); | 221 | libusb_release_interface(client->handle, client->interface); |
| 201 | libusb_close(client->handle); | 222 | libusb_close(client->handle); |
| @@ -393,22 +414,37 @@ irecv_error_t irecv_receive(irecv_client_t client) { | |||
| 393 | return IRECV_E_SUCCESS; | 414 | return IRECV_E_SUCCESS; |
| 394 | } | 415 | } |
| 395 | 416 | ||
| 396 | irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) { | 417 | irecv_error_t irecv_getenv(irecv_client_t client, const char* variable, char** value) { |
| 418 | char command[256]; | ||
| 397 | if (client == NULL || client->handle == NULL) { | 419 | if (client == NULL || client->handle == NULL) { |
| 398 | return IRECV_E_NO_DEVICE; | 420 | return IRECV_E_NO_DEVICE; |
| 399 | } | 421 | } |
| 400 | 422 | ||
| 401 | unsigned char* value = (unsigned char*) malloc(256); | 423 | *value = NULL; |
| 402 | if (value == NULL) { | 424 | |
| 425 | if(variable == NULL) { | ||
| 426 | return IRECV_E_UNKNOWN_ERROR; | ||
| 427 | } | ||
| 428 | |||
| 429 | memset(command, '\0', sizeof(command)); | ||
| 430 | snprintf(command, sizeof(command)-1, "getenv %s", variable); | ||
| 431 | irecv_error_t error = irecv_send_command(client, command); | ||
| 432 | if(error != IRECV_E_SUCCESS) { | ||
| 433 | return error; | ||
| 434 | } | ||
| 435 | |||
| 436 | unsigned char* response = (unsigned char*) malloc(256); | ||
| 437 | if (response == NULL) { | ||
| 403 | return IRECV_E_OUT_OF_MEMORY; | 438 | return IRECV_E_OUT_OF_MEMORY; |
| 404 | } | 439 | } |
| 405 | 440 | ||
| 406 | int ret = libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, value, 256, 500); | 441 | memset(response, '\0', 256); |
| 442 | int ret = libusb_control_transfer(client->handle, 0xC0, 0, 0, 0, response, 255, 500); | ||
| 407 | if (ret < 0) { | 443 | if (ret < 0) { |
| 408 | return IRECV_E_UNKNOWN_ERROR; | 444 | return IRECV_E_UNKNOWN_ERROR; |
| 409 | } | 445 | } |
| 410 | 446 | ||
| 411 | *var = value; | 447 | *value = response; |
| 412 | return IRECV_E_SUCCESS; | 448 | return IRECV_E_SUCCESS; |
| 413 | } | 449 | } |
| 414 | 450 | ||
| @@ -484,6 +520,26 @@ irecv_error_t irecv_send_exploit(irecv_client_t client) { | |||
| 484 | return IRECV_E_SUCCESS; | 520 | return IRECV_E_SUCCESS; |
| 485 | } | 521 | } |
| 486 | 522 | ||
| 523 | irecv_error_t irecv_setenv(irecv_client_t client, const char* variable, const char* value) { | ||
| 524 | char command[256]; | ||
| 525 | if (client == NULL || client->handle == NULL) { | ||
| 526 | return IRECV_E_NO_DEVICE; | ||
| 527 | } | ||
| 528 | |||
| 529 | if(variable == NULL || value == NULL) { | ||
| 530 | return IRECV_E_UNKNOWN_ERROR; | ||
| 531 | } | ||
| 532 | |||
| 533 | memset(command, '\0', sizeof(command)); | ||
| 534 | snprintf(command, sizeof(command)-1, "setenv %s %s", variable, value); | ||
| 535 | irecv_error_t error = irecv_send_command(client, command); | ||
| 536 | if(error != IRECV_E_SUCCESS) { | ||
| 537 | return error; | ||
| 538 | } | ||
| 539 | |||
| 540 | return IRECV_E_SUCCESS; | ||
| 541 | } | ||
| 542 | |||
| 487 | const char* irecv_strerror(irecv_error_t error) { | 543 | const char* irecv_strerror(irecv_error_t error) { |
| 488 | switch (error) { | 544 | switch (error) { |
| 489 | case IRECV_E_SUCCESS: | 545 | case IRECV_E_SUCCESS: |
