Encapsulate arb_id, payload and size into a data type.
[apps/agl-service-can-low-level.git] / src / isotp / send.c
1 #include <isotp/send.h>
2
3 #define PCI_START_BIT 0
4 #define PCI_WIDTH 4
5 #define PAYLOAD_LENGTH_START_BIT PCI_START_BIT + PCI_WIDTH
6 #define PAYLOAD_LENGTH_WIDTH 4
7 #define PAYLOAD_START_BIT PAYLOAD_LENGTH_START_BIT + PAYLOAD_LENGTH_WIDTH
8
9 void isotp_complete_send(IsoTpHandler* handler, IsoTpMessage* message,
10         bool status) {
11     handler->message_sent_callback(message, status);
12 }
13
14 bool isotp_send_single_frame(IsoTpHandler* handler, IsoTpMessage* message) {
15     uint64_t data = 0;
16     setBitField(&data, PCI_SINGLE, PCI_START_BIT, PCI_WIDTH);
17     setBitField(&data, message->size, PAYLOAD_LENGTH_START_BIT, PAYLOAD_LENGTH_WIDTH);
18     // TODO need a better bitfield API to support this - use byte array instead
19     // of uint64_t and specify desired total width
20     for(int i = 0; i < message->size; i++) {
21         setBitField(&data, message->payload[i], PAYLOAD_START_BIT + i * 8, 8);
22     }
23
24     uint8_t data_array[message->size + 1];
25     for(int i = 0; i < sizeof(data_array); i++) {
26         // TODO need getByte(x) function
27         data_array[i] = getBitField(data, i * 8, 8, false);
28     }
29     handler->shims->send_can_message(message->arbitration_id, data_array, sizeof(data_array));
30     isotp_complete_send(handler, message, true);
31     return true;
32 }
33
34 bool isotp_send_multi_frame(IsoTpHandler* handler, IsoTpMessage* message) {
35     // TODO make sure to copy payload into a local buffer
36     handler->shims->log("Only single frame messages are supported");
37     return false;
38 }
39
40 bool isotp_send(IsoTpHandler* handler, const uint8_t* payload,
41         uint16_t size) {
42     // we determine if it's single/multi frame and start the send
43     IsoTpMessage message = {
44         arbitration_id: handler->arbitration_id,
45         payload: payload,
46         size: size
47     };
48
49     if(size < 8) {
50         return isotp_send_single_frame(handler, &message);
51     } else {
52         return isotp_send_multi_frame(handler, &message);
53     }
54 }