Draft reworking of API.
[apps/low-level-can-service.git] / src / isotp / send.c
index b72d1b9..67703ca 100644 (file)
@@ -1,54 +1,69 @@
 #include <isotp/send.h>
 
-#define PCI_START_BIT 0
-#define PCI_WIDTH 4
-#define PAYLOAD_LENGTH_START_BIT PCI_START_BIT + PCI_WIDTH
-#define PAYLOAD_LENGTH_WIDTH 4
-#define PAYLOAD_START_BIT PAYLOAD_LENGTH_START_BIT + PAYLOAD_LENGTH_WIDTH
-
-void isotp_complete_send(IsoTpHandler* handler, IsoTpMessage* message,
-        bool status) {
-    handler->message_sent_callback(message, status);
+#define PCI_NIBBLE_INDEX 0
+#define PAYLOAD_LENGTH_NIBBLE_INDEX 1
+#define PAYLOAD_BYTE_INDEX 1
+
+void isotp_complete_send(IsoTpShims* shims, IsoTpMessage* message,
+        bool status, IsoTpMessageSentHandler callback) {
+    callback(message, status);
 }
 
-bool isotp_send_single_frame(IsoTpHandler* handler, IsoTpMessage* message) {
-    uint64_t data = 0;
-    setBitField(&data, PCI_SINGLE, PCI_START_BIT, PCI_WIDTH);
-    setBitField(&data, message->size, PAYLOAD_LENGTH_START_BIT, PAYLOAD_LENGTH_WIDTH);
-    // TODO need a better bitfield API to support this - use byte array instead
-    // of uint64_t and specify desired total width
-    for(int i = 0; i < message->size; i++) {
-        setBitField(&data, message->payload[i], PAYLOAD_START_BIT + i * 8, 8);
+IsoTpHandle isotp_send_single_frame(IsoTpShims* shims, IsoTpMessage* message,
+        IsoTpMessageSentHandler callback) {
+    IsoTpHandle handle = {
+        success: false,
+        completed: true,
+        type: ISOTP_HANDLE_SENDING
+    };
+
+    uint8_t can_data[CAN_MESSAGE_BYTE_SIZE] = {0};
+    if(!set_nibble(PCI_NIBBLE_INDEX, PCI_SINGLE, can_data, sizeof(can_data))) {
+        shims->log("Unable to set PCI in CAN data");
+        return handle;
     }
 
-    uint8_t data_array[message->size + 1];
-    for(int i = 0; i < sizeof(data_array); i++) {
-        // TODO need getByte(x) function
-        data_array[i] = getBitField(data, i * 8, 8, false);
+    if(!set_nibble(PAYLOAD_LENGTH_NIBBLE_INDEX, message->size, can_data,
+                sizeof(can_data))) {
+        shims->log("Unable to set payload length in CAN data");
+        return handle;
     }
-    handler->shims->send_can_message(message->arbitration_id, data_array, sizeof(data_array));
-    isotp_complete_send(handler, message, true);
-    return true;
+
+    if(message->size > 0) {
+        memcpy(&can_data[1], message->payload, message->size);
+    }
+
+    shims->send_can_message(message->arbitration_id, can_data,
+            1 + message->size);
+    handle.success = true;
+    isotp_complete_send(shims, message, true, callback);
+    return handle;
 }
 
-bool isotp_send_multi_frame(IsoTpHandler* handler, IsoTpMessage* message) {
+IsoTpHandle isotp_send_multi_frame(IsoTpShims* shims, IsoTpMessage* message,
+        IsoTpMessageSentHandler callback) {
     // TODO make sure to copy payload into a local buffer
-    handler->shims->log("Only single frame messages are supported");
-    return false;
+    shims->log("Only single frame messages are supported");
+    IsoTpHandle handle = {
+        success: false,
+        completed: true,
+        type: ISOTP_HANDLE_SENDING
+    };
+    return handle;
 }
 
-bool isotp_send(IsoTpHandler* handler, const uint8_t* payload,
-        uint16_t size) {
-    // we determine if it's single/multi frame and start the send
+IsoTpHandle isotp_send(IsoTpShims* shims, const uint16_t arbitration_id,
+        const uint8_t* payload, uint16_t size,
+        IsoTpMessageSentHandler callback) {
     IsoTpMessage message = {
-        arbitration_id: handler->arbitration_id,
+        arbitration_id: arbitration_id,
         payload: payload,
         size: size
     };
 
     if(size < 8) {
-        return isotp_send_single_frame(handler, &message);
+        return isotp_send_single_frame(shims, &message, callback);
     } else {
-        return isotp_send_multi_frame(handler, &message);
+        return isotp_send_multi_frame(shims, &message, callback);
     }
 }