diff options
| author | 2010-05-26 00:56:36 -0400 | |
|---|---|---|
| committer | 2010-05-26 00:56:36 -0400 | |
| commit | ce77e6ac8ead2cb4fd204c67eb4d8a67e9a8e608 (patch) | |
| tree | b8b65fc01acc901c776149a136c9f115e67d7b87 /src | |
| parent | 8482031ce77cb4914b5a04ba4704484cc6548dcd (diff) | |
| download | libirecovery-ce77e6ac8ead2cb4fd204c67eb4d8a67e9a8e608.tar.gz libirecovery-ce77e6ac8ead2cb4fd204c67eb4d8a67e9a8e608.tar.bz2 | |
Began work on a new event based callback system
Diffstat (limited to 'src')
| -rw-r--r-- | src/irecovery.c | 118 | ||||
| -rw-r--r-- | src/libirecovery.c | 277 |
2 files changed, 225 insertions, 170 deletions
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() { | |||
| 43 | void parse_command(irecv_client_t client, unsigned char* command, unsigned int size) { | 43 | void 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 | ||
| 64 | int recv_callback(irecv_client_t client, unsigned char* data, int size) { | 64 | int 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 | ||
| 72 | int send_callback(irecv_client_t client, unsigned char* command, int size) { | 72 | int 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 | ||
| 120 | void init_shell(irecv_client_t client) { | 87 | void 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 | ||
| 126 | int 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 | |||
| 135 | int 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 | |||
| 158 | int main(int argc, char** argv) { | 156 | int 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 | ||
| 94 | irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration) { | 99 | irecv_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, ¤t); | 107 | libusb_get_configuration(client->handle, ¤t); |
| 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 | ||
| 113 | irecv_error_t irecv_set_interface(irecv_client_t client, int interface, int alt_interface) { | 118 | irecv_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 | |||
| 151 | irecv_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 | |||
| 168 | irecv_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 | ||
| 145 | irecv_error_t irecv_close(irecv_client_t client) { | 185 | irecv_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 | ||
| 167 | irecv_error_t irecv_set_debug(irecv_client_t client, int level) { | 205 | irecv_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 | ||
| 177 | irecv_error_t irecv_send(irecv_client_t client, unsigned char* command) { | 215 | irecv_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 | ||
| 200 | irecv_error_t irecv_send_command(irecv_client_t client, unsigned char* command) { | 238 | irecv_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 | ||
| 222 | irecv_error_t irecv_send_file(irecv_client_t client, const char* filename) { | 277 | irecv_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 | ||
| 255 | irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* status) { | 310 | irecv_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 | ||
| 278 | irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned int length) { | 333 | irecv_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 | |||
| 328 | irecv_error_t irecv_receive(irecv_client_t client) { | 384 | irecv_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 | ||
| 358 | int irecv_default_receiver(irecv_client_t client, unsigned char* data, int size) { | 415 | int 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 | ||
| 366 | irecv_error_t irecv_set_receiver(irecv_client_t client, irecv_receive_callback callback) { | 423 | irecv_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 | ||
| 375 | irecv_error_t irecv_set_sender(irecv_client_t client, irecv_send_callback callback) { | 432 | irecv_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 | ||
| 384 | irecv_error_t irecv_getenv(irecv_client_t client, unsigned char** var) { | 441 | irecv_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 | |||
| 409 | irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) { | 465 | irecv_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 | |||
| 432 | irecv_error_t irecv_send_exploit(irecv_client_t client) { | 487 | irecv_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 | ||
| 446 | const char* irecv_strerror(irecv_error_t error) { | 501 | const 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 | } |
