diff options
Diffstat (limited to 'src/libirecovery.c')
-rw-r--r-- | src/libirecovery.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c index b1b81e0..a60782c 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c | |||
@@ -3130,7 +3130,7 @@ irecv_error_t irecv_send_command(irecv_client_t client, const char* command) | |||
3130 | return irecv_send_command_breq(client, command, 0); | 3130 | return irecv_send_command_breq(client, command, 0); |
3131 | } | 3131 | } |
3132 | 3132 | ||
3133 | irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, int dfu_notify_finished) | 3133 | irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, unsigned int options) |
3134 | { | 3134 | { |
3135 | #ifdef USE_DUMMY | 3135 | #ifdef USE_DUMMY |
3136 | return IRECV_E_UNSUPPORTED; | 3136 | return IRECV_E_UNSUPPORTED; |
@@ -3163,7 +3163,7 @@ irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, int d | |||
3163 | return IRECV_E_UNKNOWN_ERROR; | 3163 | return IRECV_E_UNKNOWN_ERROR; |
3164 | } | 3164 | } |
3165 | 3165 | ||
3166 | irecv_error_t error = irecv_send_buffer(client, (unsigned char*)buffer, length, dfu_notify_finished); | 3166 | irecv_error_t error = irecv_send_buffer(client, (unsigned char*)buffer, length, options); |
3167 | free(buffer); | 3167 | free(buffer); |
3168 | 3168 | ||
3169 | return error; | 3169 | return error; |
@@ -3190,7 +3190,7 @@ static irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* statu | |||
3190 | return IRECV_E_SUCCESS; | 3190 | return IRECV_E_SUCCESS; |
3191 | } | 3191 | } |
3192 | 3192 | ||
3193 | static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, int dfu_notify_finished) | 3193 | static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, unsigned int options) |
3194 | { | 3194 | { |
3195 | if (client->mode != IRECV_K_DFU_MODE) { | 3195 | if (client->mode != IRECV_K_DFU_MODE) { |
3196 | return IRECV_E_UNSUPPORTED; | 3196 | return IRECV_E_UNSUPPORTED; |
@@ -3254,7 +3254,7 @@ static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char* | |||
3254 | } | 3254 | } |
3255 | free(chunk); | 3255 | free(chunk); |
3256 | 3256 | ||
3257 | if (dfu_notify_finished) { | 3257 | if (options & IRECV_SEND_OPT_DFU_NOTIFY_FINISH) { |
3258 | #ifdef WIN32 | 3258 | #ifdef WIN32 |
3259 | DWORD amount = (DWORD)origLen; | 3259 | DWORD amount = (DWORD)origLen; |
3260 | DWORD transferred = 0; | 3260 | DWORD transferred = 0; |
@@ -3273,13 +3273,13 @@ static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char* | |||
3273 | } | 3273 | } |
3274 | #endif | 3274 | #endif |
3275 | 3275 | ||
3276 | irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, int dfu_notify_finished) | 3276 | irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, unsigned int options) |
3277 | { | 3277 | { |
3278 | #ifdef USE_DUMMY | 3278 | #ifdef USE_DUMMY |
3279 | return IRECV_E_UNSUPPORTED; | 3279 | return IRECV_E_UNSUPPORTED; |
3280 | #else | 3280 | #else |
3281 | if (client->isKIS) | 3281 | if (client->isKIS) |
3282 | return irecv_kis_send_buffer(client, buffer, length, dfu_notify_finished); | 3282 | return irecv_kis_send_buffer(client, buffer, length, options); |
3283 | 3283 | ||
3284 | irecv_error_t error = 0; | 3284 | irecv_error_t error = 0; |
3285 | int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_PORT_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)); | 3285 | int recovery_mode = ((client->mode != IRECV_K_DFU_MODE) && (client->mode != IRECV_K_PORT_DFU_MODE) && (client->mode != IRECV_K_WTF_MODE)); |
@@ -3289,7 +3289,12 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un | |||
3289 | 3289 | ||
3290 | unsigned int h1 = 0xFFFFFFFF; | 3290 | unsigned int h1 = 0xFFFFFFFF; |
3291 | unsigned char dfu_xbuf[12] = {0xff, 0xff, 0xff, 0xff, 0xac, 0x05, 0x00, 0x01, 0x55, 0x46, 0x44, 0x10}; | 3291 | unsigned char dfu_xbuf[12] = {0xff, 0xff, 0xff, 0xff, 0xac, 0x05, 0x00, 0x01, 0x55, 0x46, 0x44, 0x10}; |
3292 | int dfu_crc = 1; | ||
3292 | int packet_size = recovery_mode ? 0x8000 : 0x800; | 3293 | int packet_size = recovery_mode ? 0x8000 : 0x800; |
3294 | if (!recovery_mode && (options & IRECV_SEND_OPT_DFU_SMALL_PKT)) { | ||
3295 | packet_size = 0x40; | ||
3296 | dfu_crc = 0; | ||
3297 | } | ||
3293 | int last = length % packet_size; | 3298 | int last = length % packet_size; |
3294 | int packets = length / packet_size; | 3299 | int packets = length / packet_size; |
3295 | 3300 | ||
@@ -3341,11 +3346,14 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un | |||
3341 | if (recovery_mode) { | 3346 | if (recovery_mode) { |
3342 | error = irecv_usb_bulk_transfer(client, 0x04, &buffer[i * packet_size], size, &bytes, USB_TIMEOUT); | 3347 | error = irecv_usb_bulk_transfer(client, 0x04, &buffer[i * packet_size], size, &bytes, USB_TIMEOUT); |
3343 | } else { | 3348 | } else { |
3344 | int j; | 3349 | if (dfu_crc) { |
3345 | for (j = 0; j < size; j++) { | 3350 | int j; |
3346 | crc32_step(h1, buffer[i*packet_size + j]); | 3351 | for (j = 0; j < size; j++) { |
3352 | crc32_step(h1, buffer[i*packet_size + j]); | ||
3353 | } | ||
3347 | } | 3354 | } |
3348 | if (i+1 == packets) { | 3355 | if (dfu_crc && i+1 == packets) { |
3356 | int j; | ||
3349 | if (size+16 > packet_size) { | 3357 | if (size+16 > packet_size) { |
3350 | bytes = irecv_usb_control_transfer(client, 0x21, 1, i, 0, &buffer[i * packet_size], size, USB_TIMEOUT); | 3358 | bytes = irecv_usb_control_transfer(client, 0x21, 1, i, 0, &buffer[i * packet_size], size, USB_TIMEOUT); |
3351 | if (bytes != size) { | 3359 | if (bytes != size) { |
@@ -3354,7 +3362,6 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un | |||
3354 | count += size; | 3362 | count += size; |
3355 | size = 0; | 3363 | size = 0; |
3356 | } | 3364 | } |
3357 | |||
3358 | for (j = 0; j < 2; j++) { | 3365 | for (j = 0; j < 2; j++) { |
3359 | crc32_step(h1, dfu_xbuf[j*6 + 0]); | 3366 | crc32_step(h1, dfu_xbuf[j*6 + 0]); |
3360 | crc32_step(h1, dfu_xbuf[j*6 + 1]); | 3367 | crc32_step(h1, dfu_xbuf[j*6 + 1]); |
@@ -3428,7 +3435,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un | |||
3428 | irecv_usb_bulk_transfer(client, 0x04, buffer, 0, &bytes, USB_TIMEOUT); | 3435 | irecv_usb_bulk_transfer(client, 0x04, buffer, 0, &bytes, USB_TIMEOUT); |
3429 | } | 3436 | } |
3430 | 3437 | ||
3431 | if (dfu_notify_finished && !recovery_mode) { | 3438 | if ((options & IRECV_SEND_OPT_DFU_NOTIFY_FINISH) && !recovery_mode) { |
3432 | irecv_usb_control_transfer(client, 0x21, 1, packets, 0, (unsigned char*) buffer, 0, USB_TIMEOUT); | 3439 | irecv_usb_control_transfer(client, 0x21, 1, packets, 0, (unsigned char*) buffer, 0, USB_TIMEOUT); |
3433 | 3440 | ||
3434 | for (i = 0; i < 2; i++) { | 3441 | for (i = 0; i < 2; i++) { |
@@ -3438,7 +3445,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un | |||
3438 | } | 3445 | } |
3439 | } | 3446 | } |
3440 | 3447 | ||
3441 | if (dfu_notify_finished == 2) { | 3448 | if ((options & IRECV_SEND_OPT_DFU_FORCE_ZLP)) { |
3442 | /* we send a pseudo ZLP here just in case */ | 3449 | /* we send a pseudo ZLP here just in case */ |
3443 | irecv_usb_control_transfer(client, 0x21, 1, 0, 0, 0, 0, USB_TIMEOUT); | 3450 | irecv_usb_control_transfer(client, 0x21, 1, 0, 0, 0, 0, USB_TIMEOUT); |
3444 | } | 3451 | } |