2020-12-14 08:42:48 +01:00
|
|
|
#include "CspComIF.h"
|
2020-12-29 13:59:31 +01:00
|
|
|
|
2020-12-14 08:42:48 +01:00
|
|
|
#include <csp/drivers/can_socketcan.h>
|
|
|
|
#include <fsfw/serialize/SerializeAdapter.h>
|
2022-01-17 15:58:27 +01:00
|
|
|
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
#include "CspCookie.h"
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
CspComIF::CspComIF(object_id_t objectId) : SystemObject(objectId) {}
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
CspComIF::~CspComIF() {}
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
ReturnValue_t CspComIF::initializeInterface(CookieIF* cookie) {
|
|
|
|
if (cookie == nullptr) {
|
|
|
|
return NULLPOINTER;
|
|
|
|
}
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
CspCookie* cspCookie = dynamic_cast<CspCookie*>(cookie);
|
|
|
|
if (cspCookie == nullptr) {
|
|
|
|
return NULLPOINTER;
|
|
|
|
}
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
/* Perform CAN and CSP initialization only once */
|
|
|
|
if (cspDeviceMap.empty()) {
|
|
|
|
sif::info << "Performing " << canInterface << " initialization.." << std::endl;
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
/* Define the memory to allocate for the CSP stack */
|
|
|
|
int buf_count = 10;
|
|
|
|
int buf_size = 300;
|
|
|
|
/* Init CSP and CSP buffer system */
|
|
|
|
if (csp_init(cspOwnAddress) != CSP_ERR_NONE ||
|
|
|
|
csp_buffer_init(buf_count, buf_size) != CSP_ERR_NONE) {
|
|
|
|
sif::error << "Failed to init CSP\r\n" << std::endl;
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
int promisc = 0; // Set filter mode on
|
|
|
|
csp_iface_t* csp_if_ptr = &csp_if;
|
|
|
|
csp_if_ptr = csp_can_socketcan_init(canInterface, bitrate, promisc);
|
|
|
|
|
|
|
|
/* Set default route and start router */
|
|
|
|
uint8_t address = CSP_DEFAULT_ROUTE;
|
|
|
|
uint8_t netmask = 0;
|
|
|
|
uint8_t mac = CSP_NODE_MAC;
|
|
|
|
int result = csp_rtable_set(address, netmask, csp_if_ptr, mac);
|
|
|
|
if (result != CSP_ERR_NONE) {
|
|
|
|
sif::error << "Failed to add can interface to router table" << std::endl;
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
/* Start the route task */
|
|
|
|
unsigned int task_stack_size = 500;
|
|
|
|
unsigned int priority = 0;
|
|
|
|
result = csp_route_start_task(task_stack_size, priority);
|
|
|
|
if (result != CSP_ERR_NONE) {
|
|
|
|
sif::error << "Failed to start csp route task" << std::endl;
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
sif::info << canInterface << " initialized successfully" << std::endl;
|
|
|
|
}
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
uint8_t cspAddress = cspCookie->getCspAddress();
|
|
|
|
uint16_t maxReplyLength = cspCookie->getMaxReplyLength();
|
|
|
|
if (cspDeviceMap.find(cspAddress) == cspDeviceMap.end()) {
|
|
|
|
/* Insert device information in CSP map */
|
|
|
|
cspDeviceMap.emplace(cspAddress, vectorBuffer(maxReplyLength));
|
|
|
|
}
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
2020-12-14 08:42:48 +01:00
|
|
|
}
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
ReturnValue_t CspComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
|
|
|
|
int result;
|
|
|
|
if (cookie == NULL) {
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
CspCookie* cspCookie = dynamic_cast<CspCookie*>(cookie);
|
|
|
|
if (cspCookie == NULL) {
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Extract csp port and bytes to query from command buffer */
|
|
|
|
uint8_t cspPort;
|
|
|
|
uint16_t querySize = 0;
|
|
|
|
result = getPortAndQuerySize(&sendData, &sendLen, &cspPort, &querySize);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
uint8_t cspAddress = cspCookie->getCspAddress();
|
|
|
|
switch (cspPort) {
|
|
|
|
case (Ports::CSP_PING): {
|
|
|
|
initiatePingRequest(cspAddress, querySize);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case (Ports::CSP_REBOOT): {
|
|
|
|
csp_reboot(cspAddress);
|
|
|
|
break;
|
2021-02-05 07:37:21 +01:00
|
|
|
}
|
2022-01-17 15:58:27 +01:00
|
|
|
case (Ports::P60_PORT_GNDWDT_RESET):
|
|
|
|
case (Ports::P60_PORT_RPARAM): {
|
|
|
|
/* No CSP fixed port was selected. Send data to the specified port and
|
|
|
|
* wait for querySize number of bytes */
|
|
|
|
result = cspTransfer(cspAddress, cspPort, sendData, sendLen, querySize);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
replySize = querySize;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
sif::error << "CspComIF: Invalid port specified" << std::endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
2021-02-05 07:37:21 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
ReturnValue_t CspComIF::getSendSuccess(CookieIF* cookie) { return HasReturnvaluesIF::RETURN_OK; }
|
2021-02-05 07:37:21 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
ReturnValue_t CspComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
2021-02-05 07:37:21 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
ReturnValue_t CspComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
|
|
|
|
if (cookie == NULL) {
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
CspCookie* cspCookie = dynamic_cast<CspCookie*>(cookie);
|
|
|
|
if (cspCookie == NULL) {
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
2021-02-05 07:37:21 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
uint8_t cspAddress = cspCookie->getCspAddress();
|
|
|
|
|
|
|
|
*buffer = cspDeviceMap[cspAddress].data();
|
|
|
|
*size = replySize;
|
|
|
|
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t CspComIF::cspTransfer(uint8_t cspAddress, uint8_t cspPort, const uint8_t* cmdBuffer,
|
|
|
|
int cmdLen, uint16_t querySize) {
|
|
|
|
uint32_t timeout_ms = 1000;
|
|
|
|
uint16_t bytesRead = 0;
|
2022-04-11 17:16:25 +02:00
|
|
|
int32_t expectedSize = static_cast<int32_t>(querySize);
|
2022-01-17 15:58:27 +01:00
|
|
|
vectorBufferIter iter = cspDeviceMap.find(cspAddress);
|
|
|
|
if (iter == cspDeviceMap.end()) {
|
|
|
|
sif::error << "CSP device with address " << cspAddress << " no found in"
|
|
|
|
<< " device map" << std::endl;
|
2022-04-11 17:16:25 +02:00
|
|
|
return RETURN_FAILED;
|
2022-01-17 15:58:27 +01:00
|
|
|
}
|
|
|
|
uint8_t* replyBuffer = iter->second.data();
|
|
|
|
|
|
|
|
csp_conn_t* conn = csp_connect(CSP_PRIO_HIGH, cspAddress, cspPort, 0, CSP_O_NONE);
|
|
|
|
|
|
|
|
csp_packet_t* commandPacket = (csp_packet_t*)csp_buffer_get(cmdLen);
|
|
|
|
if (commandPacket == NULL) {
|
|
|
|
sif::error << "CspComIF::cspTransfer: Failed to get memory for a csp packet from the csp "
|
|
|
|
<< "stack" << std::endl;
|
|
|
|
csp_close(conn);
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(commandPacket->data, cmdBuffer, cmdLen);
|
|
|
|
commandPacket->length = cmdLen;
|
|
|
|
|
|
|
|
if (!csp_send(conn, commandPacket, timeout_ms)) {
|
|
|
|
csp_buffer_free(commandPacket);
|
|
|
|
sif::error << "CspComIF::cspTransfer: Failed to send csp packet" << std::endl;
|
|
|
|
csp_close(conn);
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return when no reply is expected */
|
|
|
|
if (expectedSize == 0) {
|
|
|
|
return RETURN_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
csp_packet_t* reply;
|
|
|
|
reply = csp_read(conn, timeout_ms);
|
|
|
|
if (reply == NULL) {
|
|
|
|
sif::error << "CspComIF::cspTransfer: Failed to read csp packet" << std::endl;
|
|
|
|
csp_close(conn);
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
memcpy(replyBuffer, reply->data, reply->length);
|
|
|
|
expectedSize = expectedSize - reply->length;
|
|
|
|
bytesRead += reply->length;
|
|
|
|
csp_buffer_free(reply);
|
|
|
|
while (expectedSize > 0) {
|
2021-02-05 07:37:21 +01:00
|
|
|
reply = csp_read(conn, timeout_ms);
|
|
|
|
if (reply == NULL) {
|
2022-01-17 15:58:27 +01:00
|
|
|
sif::error << "CspComIF::cspTransfer: Failed to read csp packet" << std::endl;
|
|
|
|
csp_close(conn);
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
if ((reply->length + bytesRead) > iter->second.size()) {
|
|
|
|
sif::error << "CspComIF::cspTransfer: Reply buffer to short" << std::endl;
|
|
|
|
csp_buffer_free(reply);
|
|
|
|
csp_close(conn);
|
|
|
|
return RETURN_FAILED;
|
2021-02-05 07:37:21 +01:00
|
|
|
}
|
2022-01-17 15:58:27 +01:00
|
|
|
memcpy(replyBuffer + bytesRead, reply->data, reply->length);
|
2021-02-05 07:37:21 +01:00
|
|
|
expectedSize = expectedSize - reply->length;
|
|
|
|
bytesRead += reply->length;
|
|
|
|
csp_buffer_free(reply);
|
2022-01-17 15:58:27 +01:00
|
|
|
}
|
2021-02-05 07:37:21 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
if (expectedSize != 0) {
|
|
|
|
sif::error << "CspComIF::cspTransfer: Received more bytes than requested" << std::endl;
|
|
|
|
sif::debug << "CspComIF::cspTransfer: Received bytes: " << bytesRead << std::endl;
|
|
|
|
csp_close(conn);
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
csp_close(conn);
|
2020-12-14 08:42:48 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
2020-12-14 08:42:48 +01:00
|
|
|
}
|
2020-12-20 13:31:44 +01:00
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
ReturnValue_t CspComIF::getPortAndQuerySize(const uint8_t** sendData, size_t* sendLen,
|
|
|
|
uint8_t* cspPort, uint16_t* querySize) {
|
|
|
|
ReturnValue_t result =
|
|
|
|
SerializeAdapter::deSerialize(cspPort, sendData, sendLen, SerializeIF::Endianness::BIG);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
sif::error << "CspComIF: Failed to deserialize CSP port from command "
|
|
|
|
<< "buffer" << std::endl;
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
SerializeAdapter::deSerialize(querySize, sendData, sendLen, SerializeIF::Endianness::BIG);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
sif::error << "CspComIF: Failed to deserialize querySize from command "
|
|
|
|
<< "buffer" << std::endl;
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
2020-12-20 13:31:44 +01:00
|
|
|
}
|
|
|
|
|
2022-01-17 15:58:27 +01:00
|
|
|
void CspComIF::initiatePingRequest(uint8_t cspAddress, uint16_t querySize) {
|
|
|
|
uint32_t timeout_ms = 500;
|
|
|
|
uint32_t replyTime = csp_ping(cspAddress, timeout_ms, querySize, CSP_O_NONE);
|
|
|
|
sif::info << "Ping address: " << cspAddress << ", reply after " << replyTime << " ms"
|
|
|
|
<< std::endl;
|
|
|
|
/* Store reply time in reply buffer * */
|
|
|
|
uint8_t* replyBuffer = cspDeviceMap[cspAddress].data();
|
|
|
|
memcpy(replyBuffer, &replyTime, sizeof(replyTime));
|
|
|
|
replySize = sizeof(replyTime);
|
2020-12-20 13:31:44 +01:00
|
|
|
}
|