summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2024-03-22 12:04:50 +0100
committerGravatar Nikias Bassen2024-03-22 12:04:50 +0100
commit90cd5efc8fd8ce31ede6121d691324ca2d588436 (patch)
tree73dfa6d84c887ccff6829c7973a1860581176987
parentd3198a50e51674e0ec19284f44f4aeb027d160a3 (diff)
downloadlibirecovery-90cd5efc8fd8ce31ede6121d691324ca2d588436.tar.gz
libirecovery-90cd5efc8fd8ce31ede6121d691324ca2d588436.tar.bz2
Change irecv_send_buffer to accept an options bitfield instead of just one value
This allows to specify different options. To not break existing behavior, a value of 1 or (1 << 0) means IRECV_SEND_OPT_DFU_NOTIFY_FINISH which is used extensively in e.g. idevicerestore. Other options are IRECV_SEND_OPT_DFU_FORCE_ZLP which I don't remember what it was added for, and a new option IRECV_SEND_OPT_DFU_SMALL_PKT which needed for upload in port DFU mode, as it won't accept packets with more than 64 bytes data and also doesn't like a CRC attached to it.
-rw-r--r--include/libirecovery.h11
-rw-r--r--src/libirecovery.c33
-rw-r--r--tools/irecovery.c2
3 files changed, 30 insertions, 16 deletions
diff --git a/include/libirecovery.h b/include/libirecovery.h
index 04892c4..ec9255b 100644
--- a/include/libirecovery.h
+++ b/include/libirecovery.h
@@ -122,6 +122,13 @@ typedef struct {
122typedef struct irecv_client_private irecv_client_private; 122typedef struct irecv_client_private irecv_client_private;
123typedef irecv_client_private* irecv_client_t; 123typedef irecv_client_private* irecv_client_t;
124 124
125enum {
126 IRECV_SEND_OPT_NONE = 0,
127 IRECV_SEND_OPT_DFU_NOTIFY_FINISH = (1 << 0),
128 IRECV_SEND_OPT_DFU_FORCE_ZLP = (1 << 1),
129 IRECV_SEND_OPT_DFU_SMALL_PKT = (1 << 2)
130};
131
125/* library */ 132/* library */
126IRECV_API void irecv_set_debug_level(int level); 133IRECV_API void irecv_set_debug_level(int level);
127IRECV_API const char* irecv_strerror(irecv_error_t error); 134IRECV_API const char* irecv_strerror(irecv_error_t error);
@@ -160,10 +167,10 @@ IRECV_API irecv_error_t irecv_event_subscribe(irecv_client_t client, irecv_event
160IRECV_API irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type); 167IRECV_API irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type);
161 168
162/* I/O */ 169/* I/O */
163IRECV_API irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, int dfu_notify_finished); 170IRECV_API irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, unsigned int options);
164IRECV_API irecv_error_t irecv_send_command(irecv_client_t client, const char* command); 171IRECV_API irecv_error_t irecv_send_command(irecv_client_t client, const char* command);
165IRECV_API irecv_error_t irecv_send_command_breq(irecv_client_t client, const char* command, uint8_t b_request); 172IRECV_API irecv_error_t irecv_send_command_breq(irecv_client_t client, const char* command, uint8_t b_request);
166IRECV_API irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, int dfu_notify_finished); 173IRECV_API irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, unsigned int options);
167IRECV_API irecv_error_t irecv_recv_buffer(irecv_client_t client, char* buffer, unsigned long length); 174IRECV_API irecv_error_t irecv_recv_buffer(irecv_client_t client, char* buffer, unsigned long length);
168 175
169/* commands */ 176/* commands */
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
3133irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, int dfu_notify_finished) 3133irecv_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
3193static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, int dfu_notify_finished) 3193static 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
3276irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, int dfu_notify_finished) 3276irecv_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 }
diff --git a/tools/irecovery.c b/tools/irecovery.c
index 955d3ca..61d053a 100644
--- a/tools/irecovery.c
+++ b/tools/irecovery.c
@@ -596,7 +596,7 @@ int main(int argc, char* argv[])
596 596
597 case kSendFile: 597 case kSendFile:
598 irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL); 598 irecv_event_subscribe(client, IRECV_PROGRESS, &progress_cb, NULL);
599 error = irecv_send_file(client, argument, 1); 599 error = irecv_send_file(client, argument, IRECV_SEND_OPT_DFU_NOTIFY_FINISH);
600 debug("%s\n", irecv_strerror(error)); 600 debug("%s\n", irecv_strerror(error));
601 break; 601 break;
602 602