85e357448f616313336698a03ca4b7bc3f6f20b5
[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 IsoTpHandle isotp_send_single_frame(IsoTpShims* shims, IsoTpMessage* message,
15         IsoTpMessageSentHandler callback) {
16     IsoTpHandle handle = {
17         success: false,
18         completed: true,
19         type: ISOTP_HANDLE_SENDING
20     };
21
22     uint8_t can_data[CAN_MESSAGE_BYTE_SIZE] = {0};
23     if(!set_nibble(PCI_NIBBLE_INDEX, PCI_SINGLE, can_data, sizeof(can_data))) {
24         shims->log("Unable to set PCI in CAN data");
25         return handle;
26     }
27
28     if(!set_nibble(PAYLOAD_LENGTH_NIBBLE_INDEX, message->size, can_data,
29                 sizeof(can_data))) {
30         shims->log("Unable to set payload length in CAN data");
31         return handle;
32     }
33
34     if(message->size > 0) {
35         memcpy(&can_data[1], message->payload, message->size);
36     }
37
38     shims->send_can_message(message->arbitration_id, can_data,
39             1 + message->size);
40     handle.success = true;
41     isotp_complete_send(shims, message, true, callback);
42     return handle;
43 }
44
45 IsoTpHandle isotp_send_multi_frame(IsoTpShims* shims, IsoTpMessage* message,
46         IsoTpMessageSentHandler callback) {
47     // TODO make sure to copy payload into a local buffer
48     shims->log("Only single frame messages are supported");
49     IsoTpHandle handle = {
50         success: false,
51         completed: true,
52         type: ISOTP_HANDLE_SENDING
53     };
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)
56     return handle;
57 }
58
59 IsoTpHandle 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,
64         payload: payload,
65         size: size
66     };
67
68     if(size < 8) {
69         return isotp_send_single_frame(shims, &message, callback);
70     } else {
71         return isotp_send_multi_frame(shims, &message, callback);
72     }
73 }