From 980d26f9dfc4eb5b8da0dc786f733110be265aea Mon Sep 17 00:00:00 2001 From: Christopher Peplin Date: Fri, 3 Jan 2014 14:29:55 -0500 Subject: Document all functions in header files. --- README.mkd | 4 +- src/isotp/isotp.h | 25 +++++++----- src/isotp/isotp_types.h | 102 +++++++++++++++++++++++++++++++++++------------- src/isotp/receive.h | 65 +++++++++++++++++++++++++++++- src/isotp/send.h | 62 ++++++++++++++++++++++++++--- 5 files changed, 212 insertions(+), 46 deletions(-) diff --git a/README.mkd b/README.mkd index 6c3efa94..ac8b67bc 100644 --- a/README.mkd +++ b/README.mkd @@ -43,9 +43,9 @@ system: ... } -With your shims in place, create an IsoTpShim object to pass them around: +With your shims in place, create an IsoTpShims object to pass them around: - IsoTpShim shims = isotp_init_shims(debug, send_can, set_timer); + IsoTpShims shims = isotp_init_shims(debug, send_can, set_timer); ### API diff --git a/src/isotp/isotp.h b/src/isotp/isotp.h index 1b52ad35..3a3658c7 100644 --- a/src/isotp/isotp.h +++ b/src/isotp/isotp.h @@ -12,22 +12,27 @@ extern "C" { #endif +/* Public: Initialize an IsoTpShims with the given callback functions. + * + * If any callbacks are not to be used, set them to NULL. For documentation of + * the function type signatures, see isotp_types.h. This struct is a handy + * encapsulation used to pass the shims around to the various isotp_* functions. + * + * Returns a struct with the fields initailized to the callbacks. + */ IsoTpShims isotp_init_shims(LogShim log, SendCanMessageShim send_can_message, SetTimerShim set_timer); -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. - * - * If this function is not used, the conventional 100ms is used by default. +/* Public: Render an IsoTpMessage as a string into the given buffer. * - * handler - the ISO-TP handler to modify. - * timeout - the new timeout in milliseconds. + * message - the message to convert to a string, for debug logging. + * destination - the target string buffer. + * destination_length - the size of the destination buffer, i.e. the max size + * for the rendered string. */ -// void isotp_set_timeout(IsoTpHandler* handler, uint16_t timeout_ms); - +void isotp_message_to_string(const IsoTpMessage* message, char* destination, + size_t destination_length); #ifdef __cplusplus } diff --git a/src/isotp/isotp_types.h b/src/isotp/isotp_types.h index 64497458..aabca740 100644 --- a/src/isotp/isotp_types.h +++ b/src/isotp/isotp_types.h @@ -16,49 +16,95 @@ extern "C" { #endif +/* Private: The default timeout to use when waiting for a response during a + * multi-frame send or receive. + */ 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; +/* Private: Determines if by default, padding is added to ISO-TP message frames. + */ +const bool ISO_TP_DEFAULT_FRAME_PADDING_STATUS; +/* Public: The type signature for an optional logging function, if the user + * wishes to provide one. It should print, store or otherwise display the + * message. + * + * message - A format string to log using the given parameters. + * ... (vargs) - the parameters for the format string. + */ typedef void (*LogShim)(const char* message, ...); +/* Public: The type signature for a function to send a single CAN message. + * + * arbitration_id - The arbitration ID of the message. + * data - The data payload for the message. NULL is valid if size is also 0. + * size - The size of the data payload, in bytes. + * + * Returns true if the CAN message was sent successfully. + */ typedef bool (*SendCanMessageShim)(const uint16_t arbitration_id, const uint8_t* data, const uint8_t size); + +/* Public: The type signature for a... TODO, not used yet. + */ typedef bool (*SetTimerShim)(uint16_t time_ms, void (*callback)); -typedef void (*IsoTpMessageReceivedHandler)(const IsoTpMessage* message); -typedef void (*IsoTpMessageSentHandler)(const IsoTpMessage* message, +/* Public: The signature for a function to be called when an ISO-TP message has + * been completely received. + * + * message - The received message. + */ +typedef void (*IsoTpMessageReceivedHandler)(const struct IsoTpMessage* message); + +/* Public: the signature for a function to be called when an ISO-TP message has + * been completely sent, or had a fatal error during sending. + * + * message - The sent message. + * success - True if the message was sent successfully. + */ +typedef void (*IsoTpMessageSentHandler)(const struct IsoTpMessage* message, const bool success); -typedef void (*IsoTpCanFrameSentHandler)(const IsoTpMessage* message); +/* Public: The signature for a function to be called when a CAN frame has been + * sent as as part of sending or receive an ISO-TP message. + * + * This is really only useful for debugging the library itself. + * + * message - The ISO-TP message that generated this CAN frame. + */ +typedef void (*IsoTpCanFrameSentHandler)(const struct IsoTpMessage* message); + +/* Public: A container for a sent or received ISO-TP message. + * + * completed - An IsoTpMessage is the return value from a few functions - this + * attribute will be true if the message is actually completely received. + * If the function returns but is only partially through receiving the + * message, this will be false and you should not consider the other data + * to be valid. + * arbitration_id - The arbitration ID of the message. + * payload - The optional payload of the message - don't forget to check the + * size! + * size - The size of the payload. The size will be 0 if there is no payload. + */ +typedef struct { + const uint16_t arbitration_id; + uint8_t payload[OUR_MAX_ISO_TP_MESSAGE_SIZE]; + uint16_t size; + bool completed; +} IsoTpMessage; + +/* Public: A container for the 3 shim functions used by the library to interact + * with the wider system. + * + * Use the isotp_init_shims(...) function to create an instance of this struct. + */ 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; - +/* Private: PCI types, for identifying each frame of an ISO-TP message. + */ typedef enum { PCI_SINGLE = 0x0, PCI_FIRST_FRAME = 0x1, @@ -66,6 +112,8 @@ typedef enum { PCI_FLOW_CONTROL_FRAME = 0x3 } IsoTpProtocolControlInformation; +/* Private: PCI flow control identifiers. + */ typedef enum { PCI_FLOW_STATUS_CONTINUE = 0x0, PCI_FLOW_STATUS_WAIT = 0x1, diff --git a/src/isotp/receive.h b/src/isotp/receive.h index 438d0824..e7e56d61 100644 --- a/src/isotp/receive.h +++ b/src/isotp/receive.h @@ -9,13 +9,74 @@ extern "C" { #endif -void isotp_complete_receive(IsoTpReceiveHandle* handle, IsoTpMessage* message); +/* Public: A handle for beginning and continuing receiving a single ISO-TP + * message - both single and multi-frame. + * + * Since an ISO-TP message may contain multiple frames, we need to keep a handle + * around while waiting for subsequent CAN messages to complete the message. + * This struct encapsulates the local state required. + * + * completed - True if the received message request is completely finished. + * success - True if the message request was successful. The value if this field + * isn't valid if 'completed' isn't true. + */ +typedef struct { + bool completed; + bool success; -bool isotp_handle_single_frame(IsoTpReceiveHandle* handle, IsoTpMessage* message); + // Private + uint16_t arbitration_id; + IsoTpMessageReceivedHandler message_received_callback; + 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; +/* Public: Initiate receiving a single ISO-TP message on a particular + * arbitration ID. + * + * Note that no actual CAN data has been received at this point - this just sets + * up a handle to be used when new CAN messages to arrive, so they can be parsed + * as potential single or multi-frame ISO-TP messages. + * + * shims - Low-level shims required to send and receive CAN messages, etc. + * arbitration_id - The arbitration ID to receive the message on. + * callback - an optional function to be called when the message is completely + * received (use NULL if no callback required). + * + * Returns a handle to be used with isotp_continue_receive when a new CAN frame + * arrives. The 'completed' field in the returned IsoTpReceiveHandle will be true + * when the message is completely sent. + */ IsoTpReceiveHandle isotp_receive(IsoTpShims* shims, const uint16_t arbitration_id, IsoTpMessageReceivedHandler callback); +/* Public: Continue to receive a an ISO-TP message, based on a freshly + * received CAN message. + * + * For a multi-frame ISO-TP message, this function must be called + * repeatedly whenever a new CAN message is received in order to complete + * receipt. + * + * TODO does this API work for if we wanted to receive an ISO-TP message and + * send our own flow control messages back? + * + * shims - Low-level shims required to send and receive CAN messages, etc. + * handle - An IsoTpReceiveHandle previously returned by isotp_receive(...). + * arbitration_id - The arbitration_id of the received CAN message. + * data - The data of the received CAN message. + * size - The size of the data in the received CAN message. + * + * Returns an IsoTpMessage with the 'completed' field set to true if a message + * was completely received. If 'completed' is false, more CAN frames are + * required to complete the messages, or the arbitration ID didn't match this + * handle. Keep passing the same handle to this function when CAN frames arrive. + */ IsoTpMessage isotp_continue_receive(IsoTpShims* shims, IsoTpReceiveHandle* handle, const uint16_t arbitration_id, const uint8_t data[], const uint8_t size); diff --git a/src/isotp/send.h b/src/isotp/send.h index 90930d8c..1af32668 100644 --- a/src/isotp/send.h +++ b/src/isotp/send.h @@ -9,9 +9,23 @@ extern "C" { #endif +/* Public: A handle for beginning and continuing sending a single ISO-TP + * message - both single and multi-frame. + * + * Since an ISO-TP message may contain multiple frames, we need to keep a handle + * around while waiting for flow control messages from the receiver. + * This struct encapsulates the local state required. + * + * completed - True if the message was completely sent, or the send was + * otherwise cancelled. + * success - True if the message send request was successful. The value if this + * field isn't valid if 'completed' isn't true. + */ typedef struct { - bool success; bool completed; + bool success; + + // Private uint16_t sending_arbitration_id; uint16_t receiving_arbitration_id; IsoTpMessageSentHandler message_sent_callback; @@ -19,14 +33,52 @@ typedef struct { // 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); - +/* Public: Initiate sending a single ISO-TP message. + * + * If the message fits in a single ISO-TP frame (i.e. the payload isn't more + * than 7 bytes) it will be sent immediately and the returned IsoTpSendHandle's + * 'completed' flag will be true. + * + * For multi-frame messages, see isotp_continue_send(...). + * + * shims - Low-level shims required to send CAN messages, etc. + * arbitration_id - The arbitration ID to send the message on. + * payload - The payload for the message. If no payload, NULL is valid is size + * is also 0. + * size - The size of the payload, or 0 if no payload. + * callback - an optional function to be called when the message is completely + * sent (use NULL if no callback required). + * + * Returns a handle to be used with isotp_continue_send to continue sending + * multi-frame messages. The 'completed' field in the returned IsoTpSendHandle + * will be true when the message is completely sent. + */ IsoTpSendHandle isotp_send(IsoTpShims* shims, const uint16_t arbitration_id, const uint8_t payload[], uint16_t size, IsoTpMessageSentHandler callback); +/* Public: Continue to send a multi-frame ISO-TP message, based on a freshly + * received CAN message (potentially from the receiver about flow control). + * + * For a multi-frame ISO-TP message, this function must be called + * repeatedly whenever a new CAN message is received in order to complete the + * send. The sender can't just blast everything onto the bus at once - it must + * wait for some response from the receiver to know how much to send at once. + * + * shims - Low-level shims required to send CAN messages, etc. + * handle - An IsoTpSendHandle previously returned by isotp_send(...). + * arbitration_id - The arbitration_id of the received CAN message. + * data - The data of the received CAN message. + * size - The size of the data in the received CAN message. + * + * Returns true if the message was completely sent, or the send was + * otherwise cancelled. Check the 'success' field of the handle to see if + * it was successful. + */ +bool isotp_continue_send(IsoTpShims* shims, IsoTpSendHandle* handle, + const uint16_t arbitration_id, const uint8_t data[], + const uint8_t size); + #ifdef __cplusplus } #endif -- cgit 1.2.3-korg