X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fisotp%2Fsend.c;h=e849bb2c8eed3bc9b8bdd75c2a2cf29d0696c24f;hb=ee24440b7c123ab1b0317e57be33e837a1cb51f1;hp=b72d1b91d4d6a45935aa9b2624b9f787f530dea5;hpb=fd2f9c3b0d869e8243c871e66d31da62bc65887a;p=apps%2Flow-level-can-service.git diff --git a/src/isotp/send.c b/src/isotp/send.c index b72d1b9..e849bb2 100644 --- a/src/isotp/send.c +++ b/src/isotp/send.c @@ -1,54 +1,89 @@ #include +#include +#include -#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 +#define PCI_NIBBLE_INDEX 0 +#define PAYLOAD_LENGTH_NIBBLE_INDEX 1 +#define PAYLOAD_BYTE_INDEX 1 -void isotp_complete_send(IsoTpHandler* handler, IsoTpMessage* message, - bool status) { - handler->message_sent_callback(message, status); +void isotp_complete_send(IsoTpShims* shims, IsoTpMessage* message, + bool status, IsoTpMessageSentHandler callback) { + if(callback != NULL) { + 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); +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; } - 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, + shims->frame_padding ? 8 : 1 + message->size); + handle.success = true; + isotp_complete_send(shims, message, true, callback); + return handle; } -bool isotp_send_multi_frame(IsoTpHandler* handler, IsoTpMessage* message) { - // TODO make sure to copy payload into a local buffer - handler->shims->log("Only single frame messages are supported"); - return false; +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; } -bool isotp_send(IsoTpHandler* handler, const uint8_t* payload, - uint16_t size) { - // we determine if it's single/multi frame and start the send +IsoTpSendHandle 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, - payload: payload, + arbitration_id: arbitration_id, size: size }; + memcpy(message.payload, payload, 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); + } +} + +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; }