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()
74 std::memset(fds, 0,
sizeof(fds));
77 fds[0].events = POLLIN;
82 callbacks.beforePoll = CProtoSerial::cbPollBefore;
83 callbacks.afterPoll = CProtoSerial::cbPollAfter;
84 callbacks.onPollReady = CProtoSerial::cbPollOnReady;
89int CProtoSerial::pollBefore(
struct pollfd *pfds, nfds_t nfds)
91 if (pfds ==
nullptr || nfds == 0)
100void CProtoSerial::pollAfter(
int ret)
104 DAWNERR(
"serial poll failed %d\n", -errno);
108int CProtoSerial::pollOnReady(
struct pollfd *pfds, nfds_t nfds,
int pollRet)
113 if (pfds ==
nullptr || nfds == 0 || pollRet <= 0)
118 if ((pfds[0].revents & POLLIN) == 0)
123 ret = read(fd, &
byte, 1);
127 return static_cast<int>(ret);
136 rxbuffer[parserPos] = byte;
147 rxbuffer[parserPos] = byte;
155 parserLen |= (uint16_t)(
byte << 8);
156 if (parserLen > FRAME_MAX_PAYLOAD)
163 rxbuffer[parserPos] = byte;
171 rxbuffer[parserPos++] = byte;
173 if (parserPos >= (
size_t)(FRAME_MIN_LEN + parserLen))
188int CProtoSerial::cbPollBefore(
void *priv,
struct pollfd *pfds, nfds_t nfds)
198 return self->pollBefore(pfds, nfds);
201void CProtoSerial::cbPollAfter(
void *priv,
struct pollfd *pfds, nfds_t nfds,
int ret)
213 self->pollAfter(ret);
216int CProtoSerial::cbPollOnReady(
void *priv,
struct pollfd *pfds, nfds_t nfds,
int pollRet)
226 return self->pollOnReady(pfds, nfds, pollRet);
229int CProtoSerial::configureDesc(
const CDescObject &desc)
236 for (
size_t i = 0; i < desc.
getSize(); i++)
242 DAWNERR(
"Unsupported SERIAL config 0x%08" PRIx32
"\n", item->
cfgid.
v);
248 case PROTO_SERIAL_CFG_IOBIND:
252 SProtoSerialIOBind *tmp;
254 tmp =
reinterpret_cast<SProtoSerialIOBind *
>(item->
data + j);
257 j +=
sizeof(SProtoSerialIOBind) / 4;
263 case PROTO_SERIAL_CFG_PATH:
265 path =
reinterpret_cast<const char *
>(&item->
data);
269 case PROTO_SERIAL_CFG_BAUD:
271 baud =
static_cast<uint32_t
>(item->
data[0]);
277 DAWNERR(
"Unsupported SERIAL config 0x%08" PRIx32
"\n", item->
cfgid.
v);
286int CProtoSerial::serialInit()
290 DAWNERR(
"Serial path not configured\n");
303 fd = open(path, O_RDWR);
309 if (errno != ENOTCONN)
311 DAWNERR(
"Failed to open serial port %s: %d\n", path, errno);
323#ifdef CONFIG_SERIAL_TERMIOS
327 if (tcgetattr(fd, &tio) == 0)
330 if (tcsetattr(fd, TCSANOW, &tio) < 0)
332 DAWNWARN(
"Serial tcsetattr failed for %s\n", path);
337 DAWNWARN(
"Serial tcgetattr failed for %s\n", path);
342 DAWNINFO(
"Serial port initialized: %s (baud=%u)\n", path, baud);
347CProtoSerial::~CProtoSerial()
356 ret = configureDesc(
getDesc());
359 DAWNERR(
"Serial configure failed (error %d)\n", ret);
378 DAWNERR(
"failed to create data %d\n", ret);
382#ifdef CONFIG_DAWN_IO_NOTIFY
383 ret = setupNotifications();
386 DAWNERR(
"failed to setup notifications %d\n", ret);
395#ifdef CONFIG_DAWN_IO_NOTIFY
396 destroyNotifications();
417 DAWNERR(
"failed to start thread %d\n", ret);
421 DAWNINFO(
"Serial protocol started\n");
428#ifdef CONFIG_DAWN_IO_NOTIFY
429 cleanupNotifications();
434 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.