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
|
||||
|
||||
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);
|
||||
}
|
||||
isotp_destroy(&handler);
|
||||
First, set up some shim functions to your lower level system:
|
||||
|
||||
// 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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue