1 #include <isotp/send.h>
2 #include <bitfield/bitfield.h>
5 #define PCI_NIBBLE_INDEX 0
6 #define PAYLOAD_LENGTH_NIBBLE_INDEX 1
7 #define PAYLOAD_BYTE_INDEX 1
9 void isotp_complete_send(IsoTpShims* shims, IsoTpMessage* message,
10 bool status, IsoTpMessageSentHandler callback) {
11 if(callback != NULL) {
12 callback(message, status);
16 IsoTpSendHandle isotp_send_single_frame(IsoTpShims* shims, IsoTpMessage* message,
17 IsoTpMessageSentHandler callback) {
18 IsoTpSendHandle handle = {
23 uint8_t can_data[CAN_MESSAGE_BYTE_SIZE] = {0};
24 if(!set_nibble(PCI_NIBBLE_INDEX, PCI_SINGLE, can_data, sizeof(can_data))) {
25 shims->log("Unable to set PCI in CAN data");
29 if(!set_nibble(PAYLOAD_LENGTH_NIBBLE_INDEX, message->size, can_data,
31 shims->log("Unable to set payload length in CAN data");
35 if(message->size > 0) {
36 memcpy(&can_data[1], message->payload, message->size);
39 shims->send_can_message(message->arbitration_id, can_data,
40 shims->frame_padding ? 8 : 1 + message->size);
41 handle.success = true;
42 isotp_complete_send(shims, message, true, callback);
46 IsoTpSendHandle isotp_send_multi_frame(IsoTpShims* shims, IsoTpMessage* message,
47 IsoTpMessageSentHandler callback) {
48 // TODO make sure to copy message into a local buffer
49 shims->log("Only single frame messages are supported");
50 IsoTpSendHandle handle = {
54 // TODO need to set sending and receiving arbitration IDs separately if we
55 // can't always just add 0x8 (and I think we can't)
59 IsoTpSendHandle isotp_send(IsoTpShims* shims, const uint16_t arbitration_id,
60 const uint8_t payload[], uint16_t size,
61 IsoTpMessageSentHandler callback) {
62 IsoTpMessage message = {
63 arbitration_id: arbitration_id,
67 memcpy(message.payload, payload, size);
69 return isotp_send_single_frame(shims, &message, callback);
71 return isotp_send_multi_frame(shims, &message, callback);
75 bool isotp_continue_send(IsoTpShims* shims, IsoTpSendHandle* handle,
76 const uint16_t arbitration_id, const uint8_t data[],
78 // TODO this will need to be tested when we add multi-frame support,
79 // which is when it'll be necessary to pass in CAN messages to SENDING
81 if(handle->receiving_arbitration_id != arbitration_id) {
82 if(shims->log != NULL) {
83 shims->log("The arb ID 0x%x doesn't match the expected tx continuation ID 0x%x",
84 arbitration_id, handle->receiving_arbitration_id);