@@ -308,8 +308,9 @@ kwp_result_t kwp_login_safe(uint16_t safe_code)
308308 return result ;
309309}
310310
311- /* Receive all fault blocks. This is used to handle the responses
312- * for both reading faults and clearing faults.
311+ /* A fault data block is in the receive buffer. Process it and receive
312+ * more fault data blocks if available. This function is used to handle
313+ * the responses for both reading faults and clearing faults.
313314 *
314315 * It has been observed with several modules that if there are no
315316 * faults, the module will send a faults response block with one
@@ -327,10 +328,11 @@ kwp_result_t kwp_login_safe(uint16_t safe_code)
327328 * function will make as many requests as needed to retrieve all of
328329 * the faults.
329330 */
330- static kwp_result_t _receive_all_fault_blocks ( void )
331+ static kwp_result_t _process_fault_block_and_receive_more ( )
331332{
332- kwp_result_t result = kwp_receive_block_expect (KWP_R_FAULTS );
333- if (result != KWP_SUCCESS ) { return result ; }
333+ // the caller should have received the first fault block
334+ // already, which is now in the buffer.
335+ if (kwp_rx_buf [2 ] != KWP_R_FAULTS ) { return KWP_UNEXPECTED ; }
334336
335337 uint8_t faults_count = 0 ;
336338
@@ -386,7 +388,7 @@ static kwp_result_t _receive_all_fault_blocks(void)
386388 // send an ack block to check for more faults
387389 // (if the last response returned fewer than 4 faults, we may be
388390 // able to stop here, but it seems safer to always do this.)
389- result = _send_ack_block ();
391+ kwp_result_t result = _send_ack_block ();
390392 if (result != KWP_SUCCESS ) { return result ; }
391393 result = kwp_receive_block ();
392394 if (result != KWP_SUCCESS ) { return result ; }
@@ -401,6 +403,7 @@ static kwp_result_t _receive_all_fault_blocks(void)
401403 if (faults_count > 200 ) { return KWP_UNEXPECTED ; }
402404 }
403405
406+ printf ("Module sent %d faults total.\r\n" , faults_count );
404407 return KWP_SUCCESS ;
405408}
406409
@@ -425,7 +428,10 @@ kwp_result_t kwp_read_faults(void)
425428 kwp_result_t result = _send_read_faults_block ();
426429 if (result != KWP_SUCCESS ) { return result ; }
427430
428- return _receive_all_fault_blocks ();
431+ result = kwp_receive_block_expect (KWP_R_FAULTS );
432+ if (result != KWP_SUCCESS ) { return result ; }
433+
434+ return _process_fault_block_and_receive_more (false);
429435}
430436
431437static kwp_result_t _send_clear_faults_block (void )
@@ -451,7 +457,45 @@ kwp_result_t kwp_clear_faults(void)
451457 kwp_result_t result = _send_clear_faults_block ();
452458 if (result != KWP_SUCCESS ) { return result ; }
453459
454- return _receive_all_fault_blocks ();
460+ result = kwp_receive_block ();
461+ if (result != KWP_SUCCESS ) { return result ; }
462+
463+ /* When a clear faults block is sent to the Digifant ECM 037906023AC
464+ * made by Siemens with EEPROM markings "FAEB09 001584", NAK seems
465+ * to always be returned first. Sending the clear faults block once
466+ * more after the NAK will succeed. Is this a bug in the ECM?
467+ */
468+ if (kwp_rx_buf [2 ] == KWP_NAK ) {
469+ printf ("Received NAK for clear faults; trying once more.\r\n" );
470+
471+ result = _send_clear_faults_block ();
472+ if (result != KWP_SUCCESS ) { return result ; }
473+
474+ kwp_result_t result = kwp_receive_block ();
475+ if (result != KWP_SUCCESS ) { return result ; }
476+ }
477+
478+ /* When a clear faults block is sent to most modules, they will respond
479+ * with a fault data block. The Digifant ECM mentioned above instead
480+ * responds with ACK. To make clearing the faults on that module work
481+ * like the others, we detect the ACK and send a read faults block
482+ * in order to receive a fault data block.
483+ */
484+ if (kwp_rx_buf [2 ] == KWP_ACK ) {
485+ printf ("Received ACK for clear faults; trying read faults.\r\n" );
486+
487+ result = _send_read_faults_block ();
488+ if (result != KWP_SUCCESS ) { return result ; }
489+ }
490+
491+ result = kwp_receive_block_expect (KWP_R_FAULTS );
492+ if (result != KWP_SUCCESS ) { return result ; }
493+
494+ result = _process_fault_block_and_receive_more ();
495+ if (result != KWP_SUCCESS ) { return result ; }
496+
497+ printf ("Clear faults finished.\r\n" );
498+ return KWP_SUCCESS ;
455499}
456500
457501
0 commit comments