mirror of https://github.com/rusefi/isotp-c.git
Return completion status when receiving CAN frames.
This commit is contained in:
parent
6bbc83bd1d
commit
03c3696d34
85
README.mkd
85
README.mkd
|
@ -3,14 +3,85 @@ ISO-TP (ISO 15765-2) Support Library in C
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
IspTpHandler handler = isotp_init(42, NULL, NULL, NULL);
|
First, set up some shim functions to your lower level system:
|
||||||
isotp_send(const uint8_t* payload, uint16_t payload_size);
|
|
||||||
while(true) {
|
|
||||||
isotp_handle_can_frame(42, data, 8);
|
|
||||||
}
|
|
||||||
isotp_destroy(&handler);
|
|
||||||
|
|
||||||
// TODO should handlers take a context? depends on how we want to use this
|
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)) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// TODO add an optional dispatcher to handle multiple open requests
|
||||||
|
|
||||||
|
|
|
@ -33,23 +33,26 @@ void isotp_message_to_string(const IsoTpMessage* message, char* destination,
|
||||||
message->arbitration_id, message->payload);
|
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 uint16_t arbitration_id, const uint8_t data[],
|
||||||
const uint8_t data_length) {
|
const uint8_t data_length) {
|
||||||
|
bool message_completed = false;
|
||||||
|
|
||||||
if(data_length < 1) {
|
if(data_length < 1) {
|
||||||
return;
|
return message_completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handle->type == ISOTP_HANDLE_RECEIVING) {
|
if(handle->type == ISOTP_HANDLE_RECEIVING) {
|
||||||
if(handle->receive_handle.arbitration_id != arbitration_id) {
|
if(handle->receive_handle.arbitration_id != arbitration_id) {
|
||||||
return;
|
return message_completed;
|
||||||
}
|
}
|
||||||
} else if(handle->type == ISOTP_HANDLE_SENDING) {
|
} else if(handle->type == ISOTP_HANDLE_SENDING) {
|
||||||
if(handle->send_handle.receiving_arbitration_id != arbitration_id) {
|
if(handle->send_handle.receiving_arbitration_id != arbitration_id) {
|
||||||
return;
|
return message_completed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
shims->log("The ISO-TP handle is corrupt");
|
shims->log("The ISO-TP handle is corrupt");
|
||||||
|
return message_completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
IsoTpProtocolControlInformation pci = (IsoTpProtocolControlInformation)
|
IsoTpProtocolControlInformation pci = (IsoTpProtocolControlInformation)
|
||||||
|
@ -73,11 +76,12 @@ void isotp_receive_can_frame(IsoTpShims* shims, IsoTpHandle* handle,
|
||||||
size: payload_length
|
size: payload_length
|
||||||
};
|
};
|
||||||
|
|
||||||
isotp_handle_single_frame(handle, &message);
|
message_completed = isotp_handle_single_frame(handle, &message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
shims->log("Only single frame messages are supported");
|
shims->log("Only single frame messages are supported");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return message_completed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,13 @@ IsoTpShims isotp_init_shims(LogShim log,
|
||||||
SendCanMessageShim send_can_message,
|
SendCanMessageShim send_can_message,
|
||||||
SetTimerShim set_timer);
|
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 uint16_t arbitration_id, const uint8_t data[],
|
||||||
const uint8_t size);
|
const uint8_t size);
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include <isotp/receive.h>
|
#include <isotp/receive.h>
|
||||||
|
|
||||||
void isotp_handle_single_frame(IsoTpHandle* handle,
|
bool isotp_handle_single_frame(IsoTpHandle* handle, IsoTpMessage* message) {
|
||||||
IsoTpMessage* message) {
|
|
||||||
isotp_complete_receive(handle, message);
|
isotp_complete_receive(handle, message);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void isotp_complete_receive(IsoTpHandle* handle, IsoTpMessage* message) {
|
void isotp_complete_receive(IsoTpHandle* handle, IsoTpMessage* message) {
|
||||||
|
|
|
@ -11,8 +11,7 @@ extern "C" {
|
||||||
|
|
||||||
void isotp_complete_receive(IsoTpHandle* handle, IsoTpMessage* message);
|
void isotp_complete_receive(IsoTpHandle* handle, IsoTpMessage* message);
|
||||||
|
|
||||||
void isotp_handle_single_frame(IsoTpHandle* handle,
|
bool isotp_handle_single_frame(IsoTpHandle* handle, IsoTpMessage* message);
|
||||||
IsoTpMessage* message);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ extern void setup();
|
||||||
START_TEST (test_receive_wrong_id)
|
START_TEST (test_receive_wrong_id)
|
||||||
{
|
{
|
||||||
const uint8_t data[CAN_MESSAGE_BYTE_SIZE] = {0};
|
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);
|
fail_if(message_was_received);
|
||||||
}
|
}
|
||||||
END_TEST
|
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
|
// 4 is a reserved number for the PCI field - only 0-3 are allowed
|
||||||
const uint8_t data[CAN_MESSAGE_BYTE_SIZE] = {0x40};
|
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);
|
fail_if(message_was_received);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -45,7 +45,7 @@ END_TEST
|
||||||
START_TEST (test_receive_single_frame_empty_payload)
|
START_TEST (test_receive_single_frame_empty_payload)
|
||||||
{
|
{
|
||||||
const uint8_t data[CAN_MESSAGE_BYTE_SIZE] = {0x00, 0x12, 0x34};
|
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);
|
fail_unless(message_was_received);
|
||||||
ck_assert_int_eq(last_message_received_arb_id, 0x2a);
|
ck_assert_int_eq(last_message_received_arb_id, 0x2a);
|
||||||
ck_assert_int_eq(last_message_received_payload_size, 0);
|
ck_assert_int_eq(last_message_received_payload_size, 0);
|
||||||
|
@ -55,7 +55,7 @@ END_TEST
|
||||||
START_TEST (test_receive_single_frame)
|
START_TEST (test_receive_single_frame)
|
||||||
{
|
{
|
||||||
const uint8_t data[CAN_MESSAGE_BYTE_SIZE] = {0x02, 0x12, 0x34};
|
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);
|
fail_unless(message_was_received);
|
||||||
ck_assert_int_eq(last_message_received_arb_id, 0x2a);
|
ck_assert_int_eq(last_message_received_arb_id, 0x2a);
|
||||||
ck_assert_int_eq(last_message_received_payload_size, 2);
|
ck_assert_int_eq(last_message_received_payload_size, 2);
|
||||||
|
|
Loading…
Reference in New Issue