aboutsummaryrefslogtreecommitdiffstats
path: root/libs/isotp-c/src/isotp/send.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/isotp-c/src/isotp/send.c')
-rw-r--r--libs/isotp-c/src/isotp/send.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/libs/isotp-c/src/isotp/send.c b/libs/isotp-c/src/isotp/send.c
new file mode 100644
index 00000000..e849bb2c
--- /dev/null
+++ b/libs/isotp-c/src/isotp/send.c
@@ -0,0 +1,89 @@
+#include <isotp/send.h>
+#include <bitfield/bitfield.h>
+#include <string.h>
+
+#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) {
+ if(callback != NULL) {
+ callback(message, status);
+ }
+}
+
+IsoTpSendHandle isotp_send_single_frame(IsoTpShims* shims, IsoTpMessage* message,
+ IsoTpMessageSentHandler callback) {
+ IsoTpSendHandle handle = {
+ success: false,
+ completed: true
+ };
+
+ 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;
+ }
+
+ 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;
+ }
+
+ if(message->size > 0) {
+ memcpy(&can_data[1], message->payload, message->size);
+ }
+
+ shims->send_can_message(message->arbitration_id, can_data,
+ shims->frame_padding ? 8 : 1 + message->size);
+ handle.success = true;
+ isotp_complete_send(shims, message, true, callback);
+ return handle;
+}
+
+IsoTpSendHandle isotp_send_multi_frame(IsoTpShims* shims, IsoTpMessage* message,
+ IsoTpMessageSentHandler callback) {
+ // TODO make sure to copy message into a local buffer
+ shims->log("Only single frame messages are supported");
+ IsoTpSendHandle handle = {
+ success: false,
+ completed: true
+ };
+ // TODO need to set sending and receiving arbitration IDs separately if we
+ // can't always just add 0x8 (and I think we can't)
+ return handle;
+}
+
+IsoTpSendHandle isotp_send(IsoTpShims* shims, const uint16_t arbitration_id,
+ const uint8_t payload[], uint16_t size,
+ IsoTpMessageSentHandler callback) {
+ IsoTpMessage message = {
+ arbitration_id: arbitration_id,
+ size: size
+ };
+
+ memcpy(message.payload, payload, size);
+ if(size < 8) {
+ return isotp_send_single_frame(shims, &message, callback);
+ } else {
+ return isotp_send_multi_frame(shims, &message, callback);
+ }
+}
+
+bool isotp_continue_send(IsoTpShims* shims, IsoTpSendHandle* handle,
+ const uint16_t arbitration_id, const uint8_t data[],
+ const uint8_t size) {
+ // TODO this will need to be tested when we add multi-frame support,
+ // which is when it'll be necessary to pass in CAN messages to SENDING
+ // handles.
+ if(handle->receiving_arbitration_id != arbitration_id) {
+ if(shims->log != NULL) {
+ shims->log("The arb ID 0x%x doesn't match the expected tx continuation ID 0x%x",
+ arbitration_id, handle->receiving_arbitration_id);
+ }
+ return false;
+ }
+ return false;
+}