mirror of https://github.com/rusefi/isotp-c.git
Split up functions in send/receive files for clarity.
This commit is contained in:
parent
330358c978
commit
a5e9107147
|
@ -1,5 +1,4 @@
|
||||||
#include <isotp/isotp.h>
|
#include <isotp/isotp.h>
|
||||||
#include <isotp/receive.h>
|
|
||||||
#include <bitfield/bitfield.h>
|
#include <bitfield/bitfield.h>
|
||||||
|
|
||||||
const uint8_t ISO_TP_DEFAULT_RESPONSE_TIMEOUT = 100;
|
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[6],
|
||||||
message->payload[7]);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,103 +1,23 @@
|
||||||
#ifndef __ISOTP_H__
|
#ifndef __ISOTP_H__
|
||||||
#define __ISOTP_H__
|
#define __ISOTP_H__
|
||||||
|
|
||||||
|
#include <isotp/isotp_types.h>
|
||||||
|
#include <isotp/send.h>
|
||||||
|
#include <isotp/receive.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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,
|
IsoTpShims isotp_init_shims(LogShim log,
|
||||||
SendCanMessageShim send_can_message,
|
SendCanMessageShim send_can_message,
|
||||||
SetTimerShim set_timer);
|
SetTimerShim set_timer);
|
||||||
|
|
||||||
IsoTpMessage isotp_continue_receive(IsoTpShims* shims,
|
void isotp_message_to_string(const IsoTpMessage* message, char* destination,
|
||||||
IsoTpReceiveHandle* handle, const uint16_t arbitration_id,
|
size_t destination_length);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Public: Change the timeout for waiting on an ISO-TP response frame.
|
/* 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_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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__
|
|
@ -22,3 +22,57 @@ IsoTpReceiveHandle isotp_receive(IsoTpShims* shims,
|
||||||
|
|
||||||
return handle;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,13 @@ void isotp_complete_receive(IsoTpReceiveHandle* handle, IsoTpMessage* message);
|
||||||
|
|
||||||
bool isotp_handle_single_frame(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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -69,3 +69,19 @@ IsoTpSendHandle isotp_send(IsoTpShims* shims, const uint16_t arbitration_id,
|
||||||
return isotp_send_multi_frame(shims, &message, callback);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,23 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue