irecv_error_t irecv_receive(irecv_client_t client) { unsigned char buffer[BUFFER_SIZE]; memset(buffer, '\0', BUFFER_SIZE); if (client == NULL || client->handle == NULL) { return IRECV_E_NO_DEVICE; } int bytes = 0; while (libusb_bulk_transfer(client->handle, 0x81, buffer, BUFFER_SIZE, &bytes, 100) == 0) { if (bytes > 0) { if (client->received_callback != NULL) { irecv_event_t event; event.size = bytes; event.data = buffer; event.type = IRECV_RECEIVED; if (client->received_callback(client, &event) != 0) { return IRECV_E_SUCCESS; } } } else break; } return IRECV_E_SUCCESS; }
irecv_error_t irecv_close(irecv_client_t client) { if (client != NULL) { if(client->disconnected_callback != NULL) { irecv_event_t event; event.size = 0; event.data = NULL; event.progress = 0; event.type = IRECV_DISCONNECTED; client->disconnected_callback(client, &event); } #ifndef WIN32 if (client->handle != NULL) { if (client->mode != kDfuMode) { libusb_release_interface(client->handle, client->interface); } libusb_close(client->handle); client->handle = NULL; } #else if (client->iBootPath!=NULL) { free(client->iBootPath); client->iBootPath = NULL; } if (client->DfuPath!=NULL) { free(client->DfuPath); client->DfuPath = NULL; } mobiledevice_closepipes(client); #endif free(client); client = NULL; } return IRECV_E_SUCCESS; }
irecv_error_t irecv_close(irecv_client_t client) { if (client != NULL) { if(client->disconnected_callback != NULL) { irecv_event_t event; event.size = 0; event.data = NULL; event.progress = 0; event.type = IRECV_DISCONNECTED; client->disconnected_callback(client, &event); } if (client->handle != NULL) { libusb_release_interface(client->handle, client->interface); libusb_close(client->handle); client->handle = NULL; } if (libirecovery_context != NULL) { libusb_exit(libirecovery_context); libirecovery_context = NULL; } free(client); client = NULL; } return IRECV_E_SUCCESS; }
irecv_error_t irecv_receive(irecv_client_t client) { char buffer[BUFFER_SIZE]; int bytes = 0; memset(buffer, '\0', BUFFER_SIZE); if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; while (irecv_bulk_transfer (client, 0x81, (unsigned char *)buffer, BUFFER_SIZE, &bytes, 500) == 0) { if (bytes > 0) { if (client->received_callback != NULL) { irecv_event_t event; event.size = bytes; event.data = buffer; event.type = IRECV_RECEIVED; if (client->received_callback(client, &event) != 0) { return IRECV_E_SUCCESS; } } if (bytes < BUFFER_SIZE) break; } else break; } return IRECV_E_SUCCESS; }
irecv_error_t irecv_send_command(irecv_client_t client, char *command) { irecv_error_t error = 0; unsigned int length; irecv_event_t event; if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; length = strlen(command); if (length >= 0x100) { length = 0xFF; } if (client->precommand_callback != NULL) { event.size = length; event.data = command; event.type = IRECV_PRECOMMAND; if (client->precommand_callback(client, &event)) { return IRECV_E_SUCCESS; } } error = irecv_send_command_raw(client, command); if (error != IRECV_E_SUCCESS) { DPRINT("Failed to send command %s\n", command); if (error != IRECV_E_PIPE) return error; } if (client->postcommand_callback != NULL) { event.size = length; event.data = command; event.type = IRECV_POSTCOMMAND; if (client->postcommand_callback(client, &event)) { return IRECV_E_SUCCESS; } } return IRECV_E_SUCCESS; }
irecv_error_t irecv_recv_buffer(irecv_client_t client, char *buffer, unsigned long length) { int recovery_mode = (client->mode != kDfuMode); int packet_size, last, packets; int i = 0; int bytes = 0; unsigned long count = 0; if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; packet_size = recovery_mode ? 0x2000 : 0x800; last = length % packet_size; packets = length / packet_size; if (last != 0) { packets++; } else { last = packet_size; } for (i = 0; i < packets; i++) { unsigned short size = (i + 1) < packets ? packet_size : last; bytes = irecv_control_transfer(client, 0xA1, 2, 0, 0, (unsigned char *)&buffer[i * packet_size], size, 1000); if (bytes != size) { return IRECV_E_USB_UPLOAD; } count += size; if (client->progress_callback != NULL) { irecv_event_t event; event.progress = ((double)count / (double)length) * 100.0; event.type = IRECV_PROGRESS; event.data = "Downloading"; event.size = count; client->progress_callback(client, &event); } else { DPRINT("Sent: %d bytes - %lu of %lu\n", bytes, count, length); } } return IRECV_E_SUCCESS; }
irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, unsigned long length, int dfuNotifyFinished) { irecv_error_t error = 0; int recovery_mode = (client->mode != kDfuMode); if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; int packet_size = 0x800; int last = length % packet_size; int packets = length / packet_size; if (last != 0) { packets++; } else { last = packet_size; } /* initiate transfer */ if (recovery_mode) { error = irecv_control_transfer(client, 0x41, 0, 0, 0, NULL, 0, 1000); } else { error = irecv_control_transfer(client, 0x21, 4, 0, 0, NULL, 0, 1000); } if (error != IRECV_E_SUCCESS) { return error; } int i = 0; double progress = 0; unsigned long count = 0; unsigned int status = 0; int bytes = 0; for (i = 0; i < packets; i++) { int size = (i + 1) < packets ? packet_size : last; /* Use bulk transfer for recovery mode and control transfer for DFU and WTF mode */ if (recovery_mode) { error = irecv_bulk_transfer(client, 0x04, &buffer[i * packet_size], size, &bytes, 1000); } else { bytes = irecv_control_transfer(client, 0x21, 1, 0, 0, &buffer[i * packet_size], size, 1000); } if (bytes != size) { return IRECV_E_USB_UPLOAD; } if (!recovery_mode) { error = irecv_get_status(client, &status); } if (error != IRECV_E_SUCCESS) { return error; } if (!recovery_mode && status != 5) { return IRECV_E_USB_UPLOAD; } count += size; if(client->progress_callback != NULL) { irecv_event_t event; event.progress = ((double) count/ (double) length) * 100.0; event.type = IRECV_PROGRESS; event.data = "Uploading"; event.size = count; client->progress_callback(client, &event); } else { debug("Sent: %d bytes - %lu of %lu\n", bytes, count, length); } } if (dfuNotifyFinished && !recovery_mode) { irecv_control_transfer(client, 0x21, 1, 0, 0, (unsigned char*) buffer, 0, 1000); for (i = 0; i < 3; i++) { error = irecv_get_status(client, &status); if (error != IRECV_E_SUCCESS) { return error; } } irecv_reset(client); } return IRECV_E_SUCCESS; }