Skip to content

Commit 90cd5ef

Browse files
committed
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.
1 parent d3198a5 commit 90cd5ef

3 files changed

Lines changed: 30 additions & 16 deletions

File tree

include/libirecovery.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,13 @@ typedef struct {
122122
typedef struct irecv_client_private irecv_client_private;
123123
typedef irecv_client_private* irecv_client_t;
124124

125+
enum {
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+
125132
/* library */
126133
IRECV_API void irecv_set_debug_level(int level);
127134
IRECV_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
160167
IRECV_API irecv_error_t irecv_event_unsubscribe(irecv_client_t client, irecv_event_type type);
161168

162169
/* I/O */
163-
IRECV_API irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, int dfu_notify_finished);
170+
IRECV_API irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, unsigned int options);
164171
IRECV_API irecv_error_t irecv_send_command(irecv_client_t client, const char* command);
165172
IRECV_API irecv_error_t irecv_send_command_breq(irecv_client_t client, const char* command, uint8_t b_request);
166-
IRECV_API irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, int dfu_notify_finished);
173+
IRECV_API irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, unsigned int options);
167174
IRECV_API irecv_error_t irecv_recv_buffer(irecv_client_t client, char* buffer, unsigned long length);
168175

169176
/* commands */

src/libirecovery.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,7 +3130,7 @@ irecv_error_t irecv_send_command(irecv_client_t client, const char* command)
31303130
return irecv_send_command_breq(client, command, 0);
31313131
}
31323132

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)
31343134
{
31353135
#ifdef USE_DUMMY
31363136
return IRECV_E_UNSUPPORTED;
@@ -3163,7 +3163,7 @@ irecv_error_t irecv_send_file(irecv_client_t client, const char* filename, int d
31633163
return IRECV_E_UNKNOWN_ERROR;
31643164
}
31653165

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);
31673167
free(buffer);
31683168

31693169
return error;
@@ -3190,7 +3190,7 @@ static irecv_error_t irecv_get_status(irecv_client_t client, unsigned int* statu
31903190
return IRECV_E_SUCCESS;
31913191
}
31923192

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)
31943194
{
31953195
if (client->mode != IRECV_K_DFU_MODE) {
31963196
return IRECV_E_UNSUPPORTED;
@@ -3254,7 +3254,7 @@ static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char*
32543254
}
32553255
free(chunk);
32563256

3257-
if (dfu_notify_finished) {
3257+
if (options & IRECV_SEND_OPT_DFU_NOTIFY_FINISH) {
32583258
#ifdef WIN32
32593259
DWORD amount = (DWORD)origLen;
32603260
DWORD transferred = 0;
@@ -3273,13 +3273,13 @@ static irecv_error_t irecv_kis_send_buffer(irecv_client_t client, unsigned char*
32733273
}
32743274
#endif
32753275

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)
32773277
{
32783278
#ifdef USE_DUMMY
32793279
return IRECV_E_UNSUPPORTED;
32803280
#else
32813281
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);
32833283

32843284
irecv_error_t error = 0;
32853285
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
32893289

32903290
unsigned int h1 = 0xFFFFFFFF;
32913291
unsigned char dfu_xbuf[12] = {0xff, 0xff, 0xff, 0xff, 0xac, 0x05, 0x00, 0x01, 0x55, 0x46, 0x44, 0x10};
3292+
int dfu_crc = 1;
32923293
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+
}
32933298
int last = length % packet_size;
32943299
int packets = length / packet_size;
32953300

@@ -3341,11 +3346,14 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
33413346
if (recovery_mode) {
33423347
error = irecv_usb_bulk_transfer(client, 0x04, &buffer[i * packet_size], size, &bytes, USB_TIMEOUT);
33433348
} else {
3344-
int j;
3345-
for (j = 0; j < size; j++) {
3346-
crc32_step(h1, buffer[i*packet_size + j]);
3349+
if (dfu_crc) {
3350+
int j;
3351+
for (j = 0; j < size; j++) {
3352+
crc32_step(h1, buffer[i*packet_size + j]);
3353+
}
33473354
}
3348-
if (i+1 == packets) {
3355+
if (dfu_crc && i+1 == packets) {
3356+
int j;
33493357
if (size+16 > packet_size) {
33503358
bytes = irecv_usb_control_transfer(client, 0x21, 1, i, 0, &buffer[i * packet_size], size, USB_TIMEOUT);
33513359
if (bytes != size) {
@@ -3354,7 +3362,6 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
33543362
count += size;
33553363
size = 0;
33563364
}
3357-
33583365
for (j = 0; j < 2; j++) {
33593366
crc32_step(h1, dfu_xbuf[j*6 + 0]);
33603367
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
34283435
irecv_usb_bulk_transfer(client, 0x04, buffer, 0, &bytes, USB_TIMEOUT);
34293436
}
34303437

3431-
if (dfu_notify_finished && !recovery_mode) {
3438+
if ((options & IRECV_SEND_OPT_DFU_NOTIFY_FINISH) && !recovery_mode) {
34323439
irecv_usb_control_transfer(client, 0x21, 1, packets, 0, (unsigned char*) buffer, 0, USB_TIMEOUT);
34333440

34343441
for (i = 0; i < 2; i++) {
@@ -3438,7 +3445,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
34383445
}
34393446
}
34403447

3441-
if (dfu_notify_finished == 2) {
3448+
if ((options & IRECV_SEND_OPT_DFU_FORCE_ZLP)) {
34423449
/* we send a pseudo ZLP here just in case */
34433450
irecv_usb_control_transfer(client, 0x21, 1, 0, 0, 0, 0, USB_TIMEOUT);
34443451
}

tools/irecovery.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ int main(int argc, char* argv[])
596596

597597
case kSendFile:
598598
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);
600600
debug("%s\n", irecv_strerror(error));
601601
break;
602602

0 commit comments

Comments
 (0)