@@ -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,55 @@ 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+ /* Special case: NAK response
464+ *
465+ * When a clear faults block is sent to the Digifant ECM 037906023AC
466+ * made by Siemens with EEPROM markings "FAEB09 001584", NAK seems
467+ * to always be returned first. Sending the clear faults block once
468+ * more after the NAK will succeed. Is this a bug in the ECM?
469+ */
470+ if (kwp_rx_buf [2 ] == KWP_NAK ) {
471+ printf ("Received NAK for clear faults; trying once more.\r\n" );
472+
473+ result = _send_clear_faults_block ();
474+ if (result != KWP_SUCCESS ) { return result ; }
475+
476+ kwp_result_t result = kwp_receive_block ();
477+ if (result != KWP_SUCCESS ) { return result ; }
478+ }
479+
480+ /* Special case: ACK response
481+ *
482+ * When a clear faults block is sent to most modules, they will respond
483+ * with a fault data block. The Digifant ECM mentioned above instead
484+ * responds with ACK. To make clearing the faults on that module work
485+ * like the others, we detect the ACK and send a read faults block
486+ * in order to receive a fault data block.
487+ */
488+ if (kwp_rx_buf [2 ] == KWP_ACK ) {
489+ printf ("Received ACK for clear faults; trying read faults.\r\n" );
490+
491+ result = _send_read_faults_block ();
492+ if (result != KWP_SUCCESS ) { return result ; }
493+
494+ result = kwp_receive_block_expect (KWP_R_FAULTS );
495+ if (result != KWP_SUCCESS ) { return result ; }
496+ }
497+
498+ // However we got here (special cases hit or not), we should
499+ // have a fault data block in the receive buffer now.
500+ if (kwp_rx_buf [2 ] != KWP_R_FAULTS ) {
501+ return KWP_UNEXPECTED ;
502+ }
503+
504+ result = _process_fault_block_and_receive_more ();
505+ if (result != KWP_SUCCESS ) { return result ; }
506+
507+ printf ("Clear faults finished.\r\n" );
508+ return KWP_SUCCESS ;
455509}
456510
457511
0 commit comments