summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Peplin <chris.peplin@rhubarbtech.com>2013-12-31 16:29:07 -0500
committerChristopher Peplin <chris.peplin@rhubarbtech.com>2013-12-31 16:29:07 -0500
commit03c3696d34a064e40c98bb5d53c9b68967353cea (patch)
treef546d19b16f0594d48a9a3c534794dc1d409a7e2
parent6bbc83bd1daac73f9e0dcccb848154a3c3b972fa (diff)
Return completion status when receiving CAN frames.
-rw-r--r--README.mkd83
-rw-r--r--src/isotp/isotp.c14
-rw-r--r--src/isotp/isotp.h8
-rw-r--r--src/isotp/receive.c4
-rw-r--r--src/isotp/receive.h3
-rw-r--r--tests/test_receive.c8
6 files changed, 100 insertions, 20 deletions
diff --git a/README.mkd b/README.mkd
index 2371561d..ba09d28a 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 f5b20795..58243123 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 e3ec588a..4f58dac4 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 1d623384..e69c59b7 100644
--- a/src/isotp/receive.c
+++ b/src/isotp/receive.c
@@ -1,8 +1,8 @@
#include <isotp/receive.h>
-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 b7c17963..b01e12de 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 17df9046..0559c065 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);