Split up functions in send/receive files for clarity.
[apps/agl-service-can-low-level.git] / src / isotp / send.c
1 #include <isotp/send.h>
2
3 #define PCI_NIBBLE_INDEX 0
4 #define PAYLOAD_LENGTH_NIBBLE_INDEX 1
5 #define PAYLOAD_BYTE_INDEX 1
6
7 void isotp_complete_send(IsoTpShims* shims, IsoTpMessage* message,
8         bool status, IsoTpMessageSentHandler callback) {
9     if(callback != NULL) {
10         callback(message, status);
11     }
12 }
13
14 IsoTpSendHandle isotp_send_single_frame(IsoTpShims* shims, IsoTpMessage* message,
15         IsoTpMessageSentHandler callback) {
16     IsoTpSendHandle handle = {
17         success: false,
18         completed: true
19     };
20
21     uint8_t can_data[CAN_MESSAGE_BYTE_SIZE] = {0};
22     if(!set_nibble(PCI_NIBBLE_INDEX, PCI_SINGLE, can_data, sizeof(can_data))) {
23         shims->log("Unable to set PCI in CAN data");
24         return handle;
25     }
26
27     if(!set_nibble(PAYLOAD_LENGTH_NIBBLE_INDEX, message->size, can_data,
28                 sizeof(can_data))) {
29         shims->log("Unable to set payload length in CAN data");
30         return handle;
31     }
32
33     if(message->size > 0) {
34         memcpy(&can_data[1], message->payload, message->size);
35     }
36
37     shims->send_can_message(message->arbitration_id, can_data,
38             1 + message->size);
39     handle.success = true;
40     isotp_complete_send(shims, message, true, callback);
41     return handle;
42 }
43
44 IsoTpSendHandle isotp_send_multi_frame(IsoTpShims* shims, IsoTpMessage* message,
45         IsoTpMessageSentHandler callback) {
46     // TODO make sure to copy message into a local buffer
47     shims->log("Only single frame messages are supported");
48     IsoTpSendHandle handle = {
49         success: false,
50         completed: true
51     };
52     // TODO need to set sending and receiving arbitration IDs separately if we
53     // can't always just add 0x8 (and I think we can't)
54     return handle;
55 }
56
57 IsoTpSendHandle isotp_send(IsoTpShims* shims, const uint16_t arbitration_id,
58         const uint8_t payload[], uint16_t size,
59         IsoTpMessageSentHandler callback) {
60     IsoTpMessage message = {
61         arbitration_id: arbitration_id,
62         size: size
63     };
64
65     memcpy(message.payload, payload, size);
66     if(size < 8) {
67         return isotp_send_single_frame(shims, &message, callback);
68     } else {
69         return isotp_send_multi_frame(shims, &message, callback);
70     }
71 }
72
73 bool isotp_continue_send(IsoTpShims* shims, IsoTpSendHandle* handle,
74         const uint16_t arbitration_id, const uint8_t data[],
75         const uint8_t size) {
76     // TODO this will need to be tested when we add multi-frame support,
77     // which is when it'll be necessary to pass in CAN messages to SENDING
78     // handles.
79     if(handle->receiving_arbitration_id != arbitration_id) {
80         if(shims->log != NULL) {
81             shims->log("The arb ID 0x%x doesn't match the expected tx continuation ID 0x%x",
82                     arbitration_id, handle->receiving_arbitration_id);
83         }
84         return false;
85     }
86     return false;
87 }