diff options
-rw-r--r-- | src/isotp/isotp.c | 72 | ||||
-rw-r--r-- | src/isotp/isotp.h | 99 | ||||
-rw-r--r-- | src/isotp/isotp_types.h | 79 | ||||
-rw-r--r-- | src/isotp/receive.c | 54 | ||||
-rw-r--r-- | src/isotp/receive.h | 7 | ||||
-rw-r--r-- | src/isotp/send.c | 16 | ||||
-rw-r--r-- | src/isotp/send.h | 17 |
7 files changed, 178 insertions, 166 deletions
diff --git a/src/isotp/isotp.c b/src/isotp/isotp.c index 6de40c31..c8b0a561 100644 --- a/src/isotp/isotp.c +++ b/src/isotp/isotp.c @@ -1,5 +1,4 @@ #include <isotp/isotp.h> -#include <isotp/receive.h> #include <bitfield/bitfield.h> const uint8_t ISO_TP_DEFAULT_RESPONSE_TIMEOUT = 100; @@ -32,74 +31,3 @@ void isotp_message_to_string(const IsoTpMessage* message, char* destination, message->payload[6], message->payload[7]); } - -IsoTpMessage isotp_continue_receive(IsoTpShims* shims, - IsoTpReceiveHandle* handle, const uint16_t arbitration_id, - const uint8_t data[], const uint8_t size) { - IsoTpMessage message = { - arbitration_id: arbitration_id, - completed: false, - payload: {0}, - size: 0 - }; - - if(size < 1) { - return message; - } - - if(handle->arbitration_id != arbitration_id) { - if(shims->log != NULL) { - shims->log("The arb ID 0x%x doesn't match the expected rx ID 0x%x", - arbitration_id, handle->arbitration_id); - } - return message; - } - - IsoTpProtocolControlInformation pci = (IsoTpProtocolControlInformation) - get_nibble(data, size, 0); - - uint8_t payload_length = get_nibble(data, size, 1); - uint8_t payload[payload_length]; - if(payload_length > 0 && size > 0) { - memcpy(payload, &data[1], payload_length); - } - - // TODO this is set up to handle rx a response with a payload, but not to - // handle flow control responses for multi frame messages that we're in the - // process of sending - - switch(pci) { - case PCI_SINGLE: { - if(payload_length > 0) { - memcpy(message.payload, payload, payload_length); - } - message.size = payload_length; - message.completed = true; - handle->success = true; - handle->completed = true; - isotp_handle_single_frame(handle, &message); - break; - } - default: - shims->log("Only single frame messages are supported"); - break; - } - return message; -} - -bool isotp_continue_send(IsoTpShims* shims, IsoTpSendHandle* handle, - const uint16_t arbitration_id, const uint8_t data[], - const uint8_t size) { - // TODO this will need to be tested when we add multi-frame support, - // which is when it'll be necessary to pass in CAN messages to SENDING - // handles. - if(handle->receiving_arbitration_id != arbitration_id) { - if(shims->log != NULL) { - shims->log("The arb ID 0x%x doesn't match the expected tx continuation ID 0x%x", - arbitration_id, handle->receiving_arbitration_id); - } - return false; - } - return false; -} - diff --git a/src/isotp/isotp.h b/src/isotp/isotp.h index f4ffa371..1b52ad35 100644 --- a/src/isotp/isotp.h +++ b/src/isotp/isotp.h @@ -1,103 +1,23 @@ #ifndef __ISOTP_H__ #define __ISOTP_H__ +#include <isotp/isotp_types.h> +#include <isotp/send.h> +#include <isotp/receive.h> #include <stdint.h> #include <stdbool.h> #include <stdio.h> -#define CAN_MESSAGE_BYTE_SIZE 8 -#define MAX_ISO_TP_MESSAGE_SIZE 4096 -// TODO we want to avoid malloc, and we can't be allocated 4K on the stack for -// each IsoTpMessage, so for now we're setting an artificial max message size -// here - since we only handle single frame messages, 8 bytes is plenty. -#define OUR_MAX_ISO_TP_MESSAGE_SIZE 8 - #ifdef __cplusplus extern "C" { #endif -const uint8_t ISO_TP_DEFAULT_RESPONSE_TIMEOUT; -const bool ISO_TP_DEFAULT_FRAME_PADDING_STATUS; - -typedef struct { - const uint16_t arbitration_id; - uint8_t payload[OUR_MAX_ISO_TP_MESSAGE_SIZE]; - uint16_t size; - bool completed; -} IsoTpMessage; - -typedef void (*LogShim)(const char* message, ...); -typedef bool (*SendCanMessageShim)(const uint16_t arbitration_id, - const uint8_t* data, const uint8_t size); -typedef bool (*SetTimerShim)(uint16_t time_ms, void (*callback)); - -typedef void (*IsoTpMessageReceivedHandler)(const IsoTpMessage* message); -typedef void (*IsoTpMessageSentHandler)(const IsoTpMessage* message, - const bool success); -typedef void (*IsoTpCanFrameSentHandler)(const IsoTpMessage* message); - -typedef struct { - LogShim log; - SendCanMessageShim send_can_message; - SetTimerShim set_timer; -} IsoTpShims; - -typedef struct { - bool success; - bool completed; - uint16_t arbitration_id; - IsoTpMessageReceivedHandler message_received_callback; - - // Private - uint16_t timeout_ms; - // timeout_ms: ISO_TP_DEFAULT_RESPONSE_TIMEOUT, - bool frame_padding; - // frame_padding: ISO_TP_DEFAULT_FRAME_PADDING_STATUS, - uint8_t* receive_buffer; - uint16_t received_buffer_size; - uint16_t incoming_message_size; - // TODO timer callback for multi frame -} IsoTpReceiveHandle; - -typedef struct { - bool success; - bool completed; - uint16_t sending_arbitration_id; - uint16_t receiving_arbitration_id; - IsoTpMessageSentHandler message_sent_callback; - IsoTpCanFrameSentHandler can_frame_sent_callback; - // TODO going to need some state here for multi frame messages -} IsoTpSendHandle; - -typedef enum { - ISOTP_HANDLE_SENDING, - ISOTP_HANDLE_RECEIVING -} IsoTpHandleType; - -typedef enum { - PCI_SINGLE = 0x0, - PCI_FIRST_FRAME = 0x1, - PCI_CONSECUTIVE_FRAME = 0x2, - PCI_FLOW_CONTROL_FRAME = 0x3 -} IsoTpProtocolControlInformation; - -typedef enum { - PCI_FLOW_STATUS_CONTINUE = 0x0, - PCI_FLOW_STATUS_WAIT = 0x1, - PCI_FLOW_STATUS_OVERFLOW = 0x2 -} IsoTpFlowStatus; - IsoTpShims isotp_init_shims(LogShim log, SendCanMessageShim send_can_message, SetTimerShim set_timer); -IsoTpMessage isotp_continue_receive(IsoTpShims* shims, - IsoTpReceiveHandle* handle, const uint16_t arbitration_id, - const uint8_t data[], const uint8_t size); - -bool isotp_continue_send(IsoTpShims* shims, IsoTpSendHandle* handle, - const uint16_t arbitration_id, const uint8_t data[], - const uint8_t size); +void isotp_message_to_string(const IsoTpMessage* message, char* destination, + size_t destination_length); /* Public: Change the timeout for waiting on an ISO-TP response frame. * @@ -108,15 +28,6 @@ bool isotp_continue_send(IsoTpShims* shims, IsoTpSendHandle* handle, */ // void isotp_set_timeout(IsoTpHandler* handler, uint16_t timeout_ms); -void isotp_message_to_string(const IsoTpMessage* message, char* destination, - size_t destination_length); - -IsoTpSendHandle isotp_send(IsoTpShims* shims, const uint16_t arbitration_id, - const uint8_t payload[], uint16_t size, - IsoTpMessageSentHandler callback); - -IsoTpReceiveHandle isotp_receive(IsoTpShims* shims, - const uint16_t arbitration_id, IsoTpMessageReceivedHandler callback); #ifdef __cplusplus } diff --git a/src/isotp/isotp_types.h b/src/isotp/isotp_types.h new file mode 100644 index 00000000..64497458 --- /dev/null +++ b/src/isotp/isotp_types.h @@ -0,0 +1,79 @@ +#ifndef __ISOTP_TYPES__ +#define __ISOTP_TYPES__ + +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> + +#define CAN_MESSAGE_BYTE_SIZE 8 +#define MAX_ISO_TP_MESSAGE_SIZE 4096 +// TODO we want to avoid malloc, and we can't be allocated 4K on the stack for +// each IsoTpMessage, so for now we're setting an artificial max message size +// here - since we only handle single frame messages, 8 bytes is plenty. +#define OUR_MAX_ISO_TP_MESSAGE_SIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif + +const uint8_t ISO_TP_DEFAULT_RESPONSE_TIMEOUT; +const bool ISO_TP_DEFAULT_FRAME_PADDING_STATUS; + +typedef struct { + const uint16_t arbitration_id; + uint8_t payload[OUR_MAX_ISO_TP_MESSAGE_SIZE]; + uint16_t size; + bool completed; +} IsoTpMessage; + +typedef void (*LogShim)(const char* message, ...); +typedef bool (*SendCanMessageShim)(const uint16_t arbitration_id, + const uint8_t* data, const uint8_t size); +typedef bool (*SetTimerShim)(uint16_t time_ms, void (*callback)); + +typedef void (*IsoTpMessageReceivedHandler)(const IsoTpMessage* message); +typedef void (*IsoTpMessageSentHandler)(const IsoTpMessage* message, + const bool success); +typedef void (*IsoTpCanFrameSentHandler)(const IsoTpMessage* message); + +typedef struct { + LogShim log; + SendCanMessageShim send_can_message; + SetTimerShim set_timer; +} IsoTpShims; + +typedef struct { + bool success; + bool completed; + uint16_t arbitration_id; + IsoTpMessageReceivedHandler message_received_callback; + + // Private + uint16_t timeout_ms; + // timeout_ms: ISO_TP_DEFAULT_RESPONSE_TIMEOUT, + bool frame_padding; + // frame_padding: ISO_TP_DEFAULT_FRAME_PADDING_STATUS, + uint8_t* receive_buffer; + uint16_t received_buffer_size; + uint16_t incoming_message_size; + // TODO timer callback for multi frame +} IsoTpReceiveHandle; + +typedef enum { + PCI_SINGLE = 0x0, + PCI_FIRST_FRAME = 0x1, + PCI_CONSECUTIVE_FRAME = 0x2, + PCI_FLOW_CONTROL_FRAME = 0x3 +} IsoTpProtocolControlInformation; + +typedef enum { + PCI_FLOW_STATUS_CONTINUE = 0x0, + PCI_FLOW_STATUS_WAIT = 0x1, + PCI_FLOW_STATUS_OVERFLOW = 0x2 +} IsoTpFlowStatus; + +#ifdef __cplusplus +} +#endif + +#endif // __ISOTP_TYPES__ diff --git a/src/isotp/receive.c b/src/isotp/receive.c index 3eba9b53..bfbf16fd 100644 --- a/src/isotp/receive.c +++ b/src/isotp/receive.c @@ -22,3 +22,57 @@ IsoTpReceiveHandle isotp_receive(IsoTpShims* shims, return handle; } + +IsoTpMessage isotp_continue_receive(IsoTpShims* shims, + IsoTpReceiveHandle* handle, const uint16_t arbitration_id, + const uint8_t data[], const uint8_t size) { + IsoTpMessage message = { + arbitration_id: arbitration_id, + completed: false, + payload: {0}, + size: 0 + }; + + if(size < 1) { + return message; + } + + if(handle->arbitration_id != arbitration_id) { + if(shims->log != NULL) { + shims->log("The arb ID 0x%x doesn't match the expected rx ID 0x%x", + arbitration_id, handle->arbitration_id); + } + return message; + } + + IsoTpProtocolControlInformation pci = (IsoTpProtocolControlInformation) + get_nibble(data, size, 0); + + uint8_t payload_length = get_nibble(data, size, 1); + uint8_t payload[payload_length]; + if(payload_length > 0 && size > 0) { + memcpy(payload, &data[1], payload_length); + } + + // TODO this is set up to handle rx a response with a payload, but not to + // handle flow control responses for multi frame messages that we're in the + // process of sending + + switch(pci) { + case PCI_SINGLE: { + if(payload_length > 0) { + memcpy(message.payload, payload, payload_length); + } + message.size = payload_length; + message.completed = true; + handle->success = true; + handle->completed = true; + isotp_handle_single_frame(handle, &message); + break; + } + default: + shims->log("Only single frame messages are supported"); + break; + } + return message; +} diff --git a/src/isotp/receive.h b/src/isotp/receive.h index f43d32e2..438d0824 100644 --- a/src/isotp/receive.h +++ b/src/isotp/receive.h @@ -13,6 +13,13 @@ void isotp_complete_receive(IsoTpReceiveHandle* handle, IsoTpMessage* message); bool isotp_handle_single_frame(IsoTpReceiveHandle* handle, IsoTpMessage* message); +IsoTpReceiveHandle isotp_receive(IsoTpShims* shims, + const uint16_t arbitration_id, IsoTpMessageReceivedHandler callback); + +IsoTpMessage isotp_continue_receive(IsoTpShims* shims, + IsoTpReceiveHandle* handle, const uint16_t arbitration_id, + const uint8_t data[], const uint8_t size); + #ifdef __cplusplus } #endif diff --git a/src/isotp/send.c b/src/isotp/send.c index dfba1df3..13db064c 100644 --- a/src/isotp/send.c +++ b/src/isotp/send.c @@ -69,3 +69,19 @@ IsoTpSendHandle isotp_send(IsoTpShims* shims, const uint16_t arbitration_id, return isotp_send_multi_frame(shims, &message, callback); } } + +bool isotp_continue_send(IsoTpShims* shims, IsoTpSendHandle* handle, + const uint16_t arbitration_id, const uint8_t data[], + const uint8_t size) { + // TODO this will need to be tested when we add multi-frame support, + // which is when it'll be necessary to pass in CAN messages to SENDING + // handles. + if(handle->receiving_arbitration_id != arbitration_id) { + if(shims->log != NULL) { + shims->log("The arb ID 0x%x doesn't match the expected tx continuation ID 0x%x", + arbitration_id, handle->receiving_arbitration_id); + } + return false; + } + return false; +} diff --git a/src/isotp/send.h b/src/isotp/send.h index 8f707b29..90930d8c 100644 --- a/src/isotp/send.h +++ b/src/isotp/send.h @@ -9,6 +9,23 @@ extern "C" { #endif +typedef struct { + bool success; + bool completed; + uint16_t sending_arbitration_id; + uint16_t receiving_arbitration_id; + IsoTpMessageSentHandler message_sent_callback; + IsoTpCanFrameSentHandler can_frame_sent_callback; + // TODO going to need some state here for multi frame messages +} IsoTpSendHandle; + +bool isotp_continue_send(IsoTpShims* shims, IsoTpSendHandle* handle, + const uint16_t arbitration_id, const uint8_t data[], + const uint8_t size); + +IsoTpSendHandle isotp_send(IsoTpShims* shims, const uint16_t arbitration_id, + const uint8_t payload[], uint16_t size, + IsoTpMessageSentHandler callback); #ifdef __cplusplus } |