From 03c3696d34a064e40c98bb5d53c9b68967353cea Mon Sep 17 00:00:00 2001 From: Christopher Peplin Date: Tue, 31 Dec 2013 16:29:07 -0500 Subject: [PATCH] Return completion status when receiving CAN frames. --- README.mkd | 83 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/isotp/isotp.c | 14 +++++---- src/isotp/isotp.h | 8 ++++- src/isotp/receive.c | 4 +-- src/isotp/receive.h | 3 +- tests/test_receive.c | 8 ++--- 6 files changed, 100 insertions(+), 20 deletions(-) diff --git a/README.mkd b/README.mkd index 2371561..ba09d28 100644 --- a/README.mkd +++ b/README.mkd @@ -3,14 +3,85 @@ ISO-TP (ISO 15765-2) Support Library in C ## API - IspTpHandler handler = isotp_init(42, NULL, NULL, NULL); - isotp_send(const uint8_t* payload, uint16_t payload_size); - while(true) { - isotp_handle_can_frame(42, data, 8); +First, set up some shim functions to your lower level system: + + void debug(const char* format, ...) { + ... + } + + void send_can(const uint16_t arbitration_id, const uint8_t* data, + const uint8_t size) { + ... + } + + void set_timer(uint16_t time_ms, void (*callback)) { + ... } - isotp_destroy(&handler); -// TODO should handlers take a context? depends on how we want to use this +Then, set up a callback and send an ISO-TP message: + + // this is your callback for when the message is completely sent - it's + // optional + void message_sent(const IsoTpMessage* message, const bool success) { + // You received the message! Do something with it. + } + + IsoTpShim shims = isotp_init_shims(debug, send_can, set_timer); + IsoTpHandle handle = isotp_send(&shims, 0x100, NULL, 0, message_sent); + + if(handle.completed) { + if(!handle.success) { + // something happened and it already failed - possibly we aren't able to + // send CAN messages + return; + } else { + // If the message fit in a single frame, it's already been sent and + you're done + } + } else { + while(true) { + // Continue to read from CAN, passing off each message to the handle + bool complete = isotp_receive_can_frame(&shims, &handle, 0x100, data, size); + + if(complete && handle.completed) { + if(handle.success) { + // All frames of the message have now been sent, following + // whatever flow control feedback it got from the receiver + } else { + // the message was unable to be sent and we bailed - fatal + // error! + } + } + } + } + +Finally, receive an ISO-TP message: + + // This is your callback for when a complete ISO-TP message is received at + // the arbitration ID you specify + void message_received(const IsoTpMessage* message) { + } + + IsoTpHandle handle = isotp_receive(&shims, 0x100, message_received); + if(!handle.success) { + // something happened and it already failed - possibly we aren't able to + // send CAN messages + } else { + while(true) { + // Continue to read from CAN, passing off each message to the handle + bool complete = isotp_receive_can_frame(&shims, &handle, 0x100, data, size); + + if(complete && handle.completed) { + if(handle.success) { + // A message has been received successfully + } else { + // Fatal error - we weren't able to receive a message and + // gave up trying. A message using flow control may have + // timed out. + } + } + } + } // TODO add an optional dispatcher to handle multiple open requests diff --git a/src/isotp/isotp.c b/src/isotp/isotp.c index f5b2079..5824312 100644 --- a/src/isotp/isotp.c +++ b/src/isotp/isotp.c @@ -33,23 +33,26 @@ void isotp_message_to_string(const IsoTpMessage* message, char* destination, message->arbitration_id, message->payload); } -void isotp_receive_can_frame(IsoTpShims* shims, IsoTpHandle* handle, +bool isotp_receive_can_frame(IsoTpShims* shims, IsoTpHandle* handle, const uint16_t arbitration_id, const uint8_t data[], const uint8_t data_length) { + bool message_completed = false; + if(data_length < 1) { - return; + return message_completed; } if(handle->type == ISOTP_HANDLE_RECEIVING) { if(handle->receive_handle.arbitration_id != arbitration_id) { - return; + return message_completed; } } else if(handle->type == ISOTP_HANDLE_SENDING) { if(handle->send_handle.receiving_arbitration_id != arbitration_id) { - return; + return message_completed; } } else { shims->log("The ISO-TP handle is corrupt"); + return message_completed; } IsoTpProtocolControlInformation pci = (IsoTpProtocolControlInformation) @@ -73,11 +76,12 @@ void isotp_receive_can_frame(IsoTpShims* shims, IsoTpHandle* handle, size: payload_length }; - isotp_handle_single_frame(handle, &message); + message_completed = isotp_handle_single_frame(handle, &message); break; } default: shims->log("Only single frame messages are supported"); break; } + return message_completed; } diff --git a/src/isotp/isotp.h b/src/isotp/isotp.h index e3ec588..4f58dac 100644 --- a/src/isotp/isotp.h +++ b/src/isotp/isotp.h @@ -93,7 +93,13 @@ IsoTpShims isotp_init_shims(LogShim log, SendCanMessageShim send_can_message, SetTimerShim set_timer); -void isotp_receive_can_frame(IsoTpShims* shims, IsoTpHandle* handle, +/* Public: + * + * Returns true if a complete ISO-TP message was sent or received as of + * processing this CAN frame. Check the 'success' and 'completed' flag on the + * handle to make sure. + */ +bool isotp_receive_can_frame(IsoTpShims* shims, IsoTpHandle* handle, const uint16_t arbitration_id, const uint8_t data[], const uint8_t size); diff --git a/src/isotp/receive.c b/src/isotp/receive.c index 1d62338..e69c59b 100644 --- a/src/isotp/receive.c +++ b/src/isotp/receive.c @@ -1,8 +1,8 @@ #include -void isotp_handle_single_frame(IsoTpHandle* handle, - IsoTpMessage* message) { +bool isotp_handle_single_frame(IsoTpHandle* handle, IsoTpMessage* message) { isotp_complete_receive(handle, message); + return true; } void isotp_complete_receive(IsoTpHandle* handle, IsoTpMessage* message) { diff --git a/src/isotp/receive.h b/src/isotp/receive.h index b7c1796..b01e12d 100644 --- a/src/isotp/receive.h +++ b/src/isotp/receive.h @@ -11,8 +11,7 @@ extern "C" { void isotp_complete_receive(IsoTpHandle* handle, IsoTpMessage* message); -void isotp_handle_single_frame(IsoTpHandle* handle, - IsoTpMessage* message); +bool isotp_handle_single_frame(IsoTpHandle* handle, IsoTpMessage* message); #ifdef __cplusplus } diff --git a/tests/test_receive.c b/tests/test_receive.c index 17df904..0559c06 100644 --- a/tests/test_receive.c +++ b/tests/test_receive.c @@ -28,7 +28,7 @@ extern void setup(); START_TEST (test_receive_wrong_id) { const uint8_t data[CAN_MESSAGE_BYTE_SIZE] = {0}; - isotp_receive_can_frame(&SHIMS, &HANDLE, 0x100, data, 1); + fail_if(isotp_receive_can_frame(&SHIMS, &HANDLE, 0x100, data, 1)); fail_if(message_was_received); } END_TEST @@ -37,7 +37,7 @@ START_TEST (test_receive_bad_pci) { // 4 is a reserved number for the PCI field - only 0-3 are allowed const uint8_t data[CAN_MESSAGE_BYTE_SIZE] = {0x40}; - isotp_receive_can_frame(&SHIMS, &HANDLE, 0x2a, data, 1); + fail_if(isotp_receive_can_frame(&SHIMS, &HANDLE, 0x2a, data, 1)); fail_if(message_was_received); } END_TEST @@ -45,7 +45,7 @@ END_TEST START_TEST (test_receive_single_frame_empty_payload) { const uint8_t data[CAN_MESSAGE_BYTE_SIZE] = {0x00, 0x12, 0x34}; - isotp_receive_can_frame(&SHIMS, &HANDLE, 0x2a, data, 3); + fail_unless(isotp_receive_can_frame(&SHIMS, &HANDLE, 0x2a, data, 3)); fail_unless(message_was_received); ck_assert_int_eq(last_message_received_arb_id, 0x2a); ck_assert_int_eq(last_message_received_payload_size, 0); @@ -55,7 +55,7 @@ END_TEST START_TEST (test_receive_single_frame) { const uint8_t data[CAN_MESSAGE_BYTE_SIZE] = {0x02, 0x12, 0x34}; - isotp_receive_can_frame(&SHIMS, &HANDLE, 0x2a, data, 3); + fail_unless(isotp_receive_can_frame(&SHIMS, &HANDLE, 0x2a, data, 3)); fail_unless(message_was_received); ck_assert_int_eq(last_message_received_arb_id, 0x2a); ck_assert_int_eq(last_message_received_payload_size, 2); -- 2.16.6