@@ -795,6 +795,7 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons
795795 ptr = strstr (iboot_string , "CPID:" );
796796 if (ptr != NULL ) {
797797 sscanf (ptr , "CPID:%x" , & client -> device_info .cpid );
798+ client -> device_info .have_cpid = 1 ;
798799 } else {
799800 // early iOS 1 doesn't identify itself
800801 client -> device_info .cpid = 0x8900 ;
@@ -803,33 +804,39 @@ static void irecv_load_device_info_from_iboot_string(irecv_client_t client, cons
803804 ptr = strstr (iboot_string , "CPRV:" );
804805 if (ptr != NULL ) {
805806 sscanf (ptr , "CPRV:%x" , & client -> device_info .cprv );
807+ client -> device_info .have_cprv = 1 ;
806808 }
807809
808810 ptr = strstr (iboot_string , "CPFM:" );
809811 if (ptr != NULL ) {
810812 sscanf (ptr , "CPFM:%x" , & client -> device_info .cpfm );
813+ client -> device_info .have_cpfm = 1 ;
811814 }
812815
813816 ptr = strstr (iboot_string , "SCEP:" );
814817 if (ptr != NULL ) {
815818 sscanf (ptr , "SCEP:%x" , & client -> device_info .scep );
819+ client -> device_info .have_scep = 1 ;
816820 }
817821
818822 ptr = strstr (iboot_string , "BDID:" );
819823 if (ptr != NULL ) {
820824 uint64_t bdid = 0 ;
821825 sscanf (ptr , "BDID:%" SCNx64 , & bdid );
822826 client -> device_info .bdid = (unsigned int )bdid ;
827+ client -> device_info .have_bdid = 1 ;
823828 }
824829
825830 ptr = strstr (iboot_string , "ECID:" );
826831 if (ptr != NULL ) {
827832 sscanf (ptr , "ECID:%" SCNx64 , & client -> device_info .ecid );
833+ client -> device_info .have_ecid = 1 ;
828834 }
829835
830836 ptr = strstr (iboot_string , "IBFL:" );
831837 if (ptr != NULL ) {
832838 sscanf (ptr , "IBFL:%x" , & client -> device_info .ibfl );
839+ client -> device_info .have_ibfl = 1 ;
833840 }
834841
835842 char tmp [256 ];
@@ -3143,7 +3150,7 @@ irecv_error_t irecv_device_event_unsubscribe(irecv_device_event_context_t contex
31433150#endif
31443151}
31453152
3146- irecv_error_t irecv_close (irecv_client_t client )
3153+ static irecv_error_t irecv_cleanup (irecv_client_t client )
31473154{
31483155#ifdef USE_DUMMY
31493156 return IRECV_E_UNSUPPORTED ;
@@ -3187,15 +3194,23 @@ irecv_error_t irecv_close(irecv_client_t client)
31873194 free (client -> device_info .serial_string );
31883195 free (client -> device_info .ap_nonce );
31893196 free (client -> device_info .sep_nonce );
3190-
3191- free (client );
3192- client = NULL ;
31933197 }
31943198
31953199 return IRECV_E_SUCCESS ;
31963200#endif
31973201}
31983202
3203+ irecv_error_t irecv_close (irecv_client_t client )
3204+ {
3205+ irecv_error_t ret = IRECV_E_SUCCESS ;
3206+ if (client ) {
3207+ ret = irecv_cleanup (client );
3208+ free (client );
3209+ client = NULL ;
3210+ }
3211+ return ret ;
3212+ }
3213+
31993214void irecv_set_debug_level (int level )
32003215{
32013216 libirecovery_debug = level ;
@@ -3472,6 +3487,7 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
34723487 irecv_error_t error = 0 ;
34733488 int recovery_mode = ((client -> mode != IRECV_K_DFU_MODE ) && (client -> mode != IRECV_K_PORT_DFU_MODE ) && (client -> mode != IRECV_K_WTF_MODE ));
34743489 int legacy_recovery_mode = 0 ;
3490+ int isiOS2 = 0 ;
34753491
34763492 if (recovery_mode && client -> device_info .cpid == 0x8900 && !client -> device_info .ecid ) {
34773493#ifdef DEBUG
@@ -3484,6 +3500,17 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
34843500 legacy_recovery_mode = 1 ;
34853501 }
34863502
3503+ if (recovery_mode && !legacy_recovery_mode ) {
3504+ // we are in recovery mode and we are not dealing with iOS 1.x
3505+ if ((client -> device_info .cpid == 0x8900 || client -> device_info .cpid == 0x8720 ) && !client -> device_info .have_ibfl ) {
3506+ // iOS 2.x doesn't have IBFL tag, but iOS 3 does
3507+ // Also, to avoid false activation of this codepath, restrict it to the only two CPID which can run iOS 2
3508+ recovery_mode = 0 ; // iOS 2 recovery mode works same as DFU mode
3509+ isiOS2 = 1 ;
3510+ options |= IRECV_SEND_OPT_DFU_NOTIFY_FINISH ;
3511+ }
3512+ }
3513+
34873514 if (check_context (client ) != IRECV_E_SUCCESS )
34883515 return IRECV_E_NO_DEVICE ;
34893516
@@ -3536,6 +3563,14 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
35363563 case 2 :
35373564 /* DFU IDLE */
35383565 break ;
3566+ case 8 :
3567+ /* DFU WAIT RESET */
3568+ if (!isiOS2 ) {
3569+ debug ("Unexpected state %d in non-iOS2 mode!, issuing ABORT\n" , state );
3570+ irecv_usb_control_transfer (client , 0x21 , 6 , 0 , 0 , NULL , 0 , USB_TIMEOUT );
3571+ error = IRECV_E_USB_UPLOAD ;
3572+ }
3573+ break ;
35393574 case 10 :
35403575 debug ("DFU ERROR, issuing CLRSTATUS\n" );
35413576 irecv_usb_control_transfer (client , 0x21 , 4 , 0 , 0 , NULL , 0 , USB_TIMEOUT );
@@ -3673,6 +3708,10 @@ irecv_error_t irecv_send_buffer(irecv_client_t client, unsigned char* buffer, un
36733708 }
36743709
36753710 irecv_reset (client );
3711+
3712+ if (isiOS2 ) {
3713+ irecv_reconnect (client , 0 );
3714+ }
36763715 }
36773716
36783717 if (legacy_recovery_mode ) {
@@ -4228,7 +4267,7 @@ irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause)
42284267 uint64_t ecid = client -> device_info .ecid ;
42294268
42304269 if (check_context (client ) == IRECV_E_SUCCESS ) {
4231- irecv_close (client );
4270+ irecv_cleanup (client );
42324271 }
42334272
42344273 if (initial_pause > 0 ) {
@@ -4248,6 +4287,11 @@ irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause)
42484287 new_client -> postcommand_callback = postcommand_callback ;
42494288 new_client -> disconnected_callback = disconnected_callback ;
42504289
4290+ // keep old handle valid
4291+ memcpy (client , new_client , sizeof (* client ));
4292+ free (new_client );
4293+ new_client = client ;
4294+
42514295 if (new_client -> connected_callback != NULL ) {
42524296 irecv_event_t event ;
42534297 event .size = 0 ;
0 commit comments