6#include "dawn/proto/serial/simple.hxx"
8#include "dawn/common/poll_loop.hxx"
20int CProtoSerial::sendFrame(uint8_t cmd,
const uint8_t *payload,
size_t len)
22 uint8_t frame[FRAME_MAX_PAYLOAD + FRAME_MIN_LEN];
27 if (len > FRAME_MAX_PAYLOAD || fd < 0)
32 tosend = FRAME_MIN_LEN + len;
35 frame[1] = (uint8_t)(len & 0xFF);
36 frame[2] = (uint8_t)((len >> 8) & 0xFF);
41 std::memcpy(&frame[4], payload, len);
45 frame[4 + len] = (uint8_t)(crc & 0xFF);
46 frame[5 + len] = (uint8_t)((crc >> 8) & 0xFF);
48 ret = write(fd, frame, tosend);
49 if (ret < 0 ||
static_cast<size_t>(ret) != tosend)
52 "Serial sendto failed cmd=0x%02x ret=%zd exp=%zu errno=%d\n", cmd, ret, tosend, errno);
53 return ret < 0 ? static_cast<int>(ret) : -EIO;
59void CProtoSerial::thread()
64 std::memset(fds, 0,
sizeof(fds));
67 fds[0].events = POLLIN;
72 callbacks.beforePoll = CProtoSerial::cbPollBefore;
73 callbacks.afterPoll = CProtoSerial::cbPollAfter;
74 callbacks.onPollReady = CProtoSerial::cbPollOnReady;
79int CProtoSerial::pollBefore(
struct pollfd *pfds, nfds_t nfds)
81 if (pfds ==
nullptr || nfds == 0)
90void CProtoSerial::pollAfter(
int ret)
94 DAWNERR(
"serial poll failed %d\n", -errno);
98int CProtoSerial::pollOnReady(
struct pollfd *pfds, nfds_t nfds,
int pollRet)
103 if (pfds ==
nullptr || nfds == 0 || pollRet <= 0)
108 if ((pfds[0].revents & POLLIN) == 0)
113 ret = read(fd, &
byte, 1);
117 return static_cast<int>(ret);
126 rxbuffer[parserPos] = byte;
137 rxbuffer[parserPos] = byte;
145 parserLen |= (uint16_t)(
byte << 8);
146 if (parserLen > FRAME_MAX_PAYLOAD)
153 rxbuffer[parserPos] = byte;
161 rxbuffer[parserPos++] = byte;
163 if (parserPos >= (
size_t)(FRAME_MIN_LEN + parserLen))
178int CProtoSerial::cbPollBefore(
void *priv,
struct pollfd *pfds, nfds_t nfds)
188 return self->pollBefore(pfds, nfds);
191void CProtoSerial::cbPollAfter(
void *priv,
struct pollfd *pfds, nfds_t nfds,
int ret)
203 self->pollAfter(ret);
206int CProtoSerial::cbPollOnReady(
void *priv,
struct pollfd *pfds, nfds_t nfds,
int pollRet)
216 return self->pollOnReady(pfds, nfds, pollRet);
219int CProtoSerial::configureDesc(
const CDescObject &desc)
226 for (
size_t i = 0; i < desc.
getSize(); i++)
232 DAWNERR(
"Unsupported SERIAL config 0x%08" PRIx32
"\n", item->
cfgid.
v);
238 case PROTO_SERIAL_CFG_IOBIND:
242 SProtoSerialIOBind *tmp;
244 tmp =
reinterpret_cast<SProtoSerialIOBind *
>(item->
data + j);
247 j +=
sizeof(SProtoSerialIOBind) / 4;
253 case PROTO_SERIAL_CFG_PATH:
255 path =
reinterpret_cast<const char *
>(&item->
data);
259 case PROTO_SERIAL_CFG_BAUD:
261 baud =
static_cast<uint32_t
>(item->
data[0]);
267 DAWNERR(
"Unsupported SERIAL config 0x%08" PRIx32
"\n", item->
cfgid.
v);
276int CProtoSerial::serialInit()
282 DAWNERR(
"Serial path not configured\n");
286 fd = open(path, O_RDWR);
289 DAWNERR(
"Failed to open serial port: %s\n", path);
295 tcsetattr(fd, TCSANOW, &tio);
297 DAWNINFO(
"Serial port initialized: %s (baud=%u)\n", path, baud);
302CProtoSerial::~CProtoSerial()
311 ret = configureDesc(
getDesc());
314 DAWNERR(
"Serial configure failed (error %d)\n", ret);
334 DAWNERR(
"failed to create data %d\n", ret);
338#ifdef CONFIG_DAWN_IO_NOTIFY
339 ret = setupNotifications();
342 DAWNERR(
"failed to setup notifications %d\n", ret);
351#ifdef CONFIG_DAWN_IO_NOTIFY
352 destroyNotifications();
373 DAWNERR(
"failed to start thread %d\n", ret);
377 DAWNINFO(
"Serial protocol started\n");
384#ifdef CONFIG_DAWN_IO_NOTIFY
385 cleanupNotifications();
390 DAWNINFO(
"Serial protocol stopped\n");
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemNext(size_t &offset) const
Get config item at current offset and advance past it.
CDescObject & getDesc()
Get descriptor object for this object.
static int run(CThreadedObject &threadCtl, struct pollfd *pfds, nfds_t nfds, int timeoutMs, const SPollLoopCallbacks &callbacks, void *priv)
Run poll loop until quit is requested.
@ PROTO_CLASS_SERIAL
Compact binary protocol over serial port.
Simple binary serial protocol for device communication.
int configure()
Configure object from descriptor data.
int init()
One-time initialize object after bindings are resolved.
int doStart()
Start implementation hook.
bool hasThread() const
Check if a background thread is active.
int doStop()
Stop implementation hook.
int deinit()
De-initialize object.
static uint8_t FRAME_SYNC
Frame structure constants.
void allocObject(SProtoSimpleIOBind *cfg)
Store an allocated IO binding.
uint16_t calculateCrc(const uint8_t *data, size_t len)
Calculate 16-bit CRC checksum.
int handleFrame(const uint8_t *frame, size_t len)
Process a received frame.
int createBuffers()
Allocate shared per-IO data buffers.
int destroyBuffers()
Destroy shared per-IO data buffers.
bool workerThreadRunning() const
Check if the worker thread is running.
int stopWorkerThread()
Stop the worker thread.
int startWorkerThread(Func &&func)
Start the worker thread with a given function.
CThreadedObject & workerThread()
Get a reference to this thread controller.
Out-of-tree user-extension hooks for Dawn.
Single configuration item within object.
ObjectCfgData_t data[]
Configuration data array (flexible, size from cfgid.s.size).
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
Callback set for poll-based worker loops.
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
uint32_t cls
Object class (bits 21-29, max 511).
uint32_t id
Configuration identifier (bits 0-4, max 31).
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.