irecv_error_t irecv_set_configuration(irecv_client_t client, int configuration) { if (check_context(client) != IRECV_E_SUCCESS) return IRECV_E_NO_DEVICE; #ifndef WIN32 debug("Setting to configuration %d\n", configuration); int current = 0; irecv_usb_get_configuration(client->handle, ¤t); if (current != configuration) { if (irecv_usb_set_configuration(client->handle, configuration) < 0) { return IRECV_E_USB_CONFIGURATION; } } client->config = configuration; #endif return IRECV_E_SUCCESS; }
int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_identity) { irecv_error_t dfu_error = IRECV_E_SUCCESS; int mode = 0; if (dfu_client_new(client) < 0) { error("ERROR: Unable to connect to DFU device\n"); return -1; } irecv_get_mode(client->dfu->client, &mode); if (mode != IRECV_K_DFU_MODE) { info("NOTE: device is not in DFU mode, assuming recovery mode.\n"); client->mode = &idevicerestore_modes[MODE_RECOVERY]; return 0; } if (dfu_send_component(client, build_identity, "iBSS") < 0) { error("ERROR: Unable to send iBSS to device\n"); irecv_close(client->dfu->client); client->dfu->client = NULL; return -1; } irecv_usb_control_transfer(client->dfu->client, 0x21, 1, 0, 0, 0, 0, 5000); dfu_error = irecv_reset(client->dfu->client); if (dfu_error != IRECV_E_SUCCESS) { error("ERROR: Unable to reset device\n"); irecv_close(client->dfu->client); client->dfu->client = NULL; return -1; } if (client->build_major > 8) { /* reconnect */ dfu_client_free(client); sleep(2); dfu_client_new(client); /* get nonce */ unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (dfu_get_ap_nonce(client, &nonce, &nonce_size) < 0) { error("ERROR: Unable to get ApNonce from device!\n"); return -1; } if (!client->nonce || (nonce_size != client->nonce_size) || (memcmp(nonce, client->nonce, nonce_size) != 0)) { nonce_changed = 1; if (client->nonce) { free(client->nonce); } client->nonce = nonce; client->nonce_size = nonce_size; } else { free(nonce); } info("Nonce: "); int i; for (i = 0; i < client->nonce_size; i++) { info("%02x ", client->nonce[i]); } info("\n"); if (nonce_changed && !(client->flags & FLAG_CUSTOM)) { // Welcome iOS5. We have to re-request the TSS with our nonce. plist_free(client->tss); if (get_tss_response(client, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); return -1; } if (!client->tss) { error("ERROR: can't continue without TSS\n"); return -1; } fixup_tss(client->tss); } if (irecv_usb_set_configuration(client->dfu->client, 1) < 0) { error("ERROR: set configuration failed\n"); } /* send iBEC */ if (dfu_send_component(client, build_identity, "iBEC") < 0) { error("ERROR: Unable to send iBEC to device\n"); irecv_close(client->dfu->client); client->dfu->client = NULL; return -1; } irecv_usb_control_transfer(client->dfu->client, 0x21, 1, 0, 0, 0, 0, 5000); dfu_error = irecv_reset(client->dfu->client); if (dfu_error != IRECV_E_SUCCESS) { error("ERROR: Unable to reset device\n"); irecv_close(client->dfu->client); client->dfu->client = NULL; return -1; } } dfu_client_free(client); sleep(7); // Reconnect to device, but this time make sure we're not still in DFU mode if (recovery_client_new(client) < 0) { error("ERROR: Unable to connect to recovery device\n"); if (client->recovery->client) { irecv_close(client->recovery->client); client->recovery->client = NULL; } return -1; } irecv_get_mode(client->recovery->client, &mode); if (mode == IRECV_K_DFU_MODE) { error("ERROR: Unable to connect to recovery device\n"); if (client->recovery->client) { irecv_close(client->recovery->client); client->recovery->client = NULL; } return -1; } return 0; }