//| Copyright: (C) 2020-2024 Kevin Larke //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file. #include "cwCommon.h" #include "cwLog.h" #include "cwCommonImpl.h" #include "cwMem.h" #include "cwThread.h" #include "cwSerialPort.h" #include "cwSerialPortSrv.h" namespace cw { namespace serialPortSrv { typedef struct this_str { serialPort::handle_t mgrH; thread::handle_t threadH; unsigned pollPeriodMs; } this_t; inline this_t* _handleToPtr( handle_t h ) { return handleToPtr(h); } rc_t _destroy( this_t* p ) { rc_t rc = kOkRC; if((rc = thread::destroy(p->threadH)) != kOkRC ) return rc; if((rc = serialPort::destroy(p->mgrH)) != kOkRC ) return rc; mem::release(p); return rc; } // Do periodic non-blocking reads of each serial port and sleep between reads. bool threadCallbackAlt( void* arg ) { this_t* p = static_cast(arg); unsigned portN = serialPort::portCount( p->mgrH ); unsigned readN; for(unsigned i=0; imgrH, serialPort::portIndexToId(p->mgrH,i), readN ); if( rc != kOkRC && rc != kTimeOutRC ) { cwLogError(rc,"Serial server receive failed."); return false; } } if( readN == 0) sleepMs(20); return true; } // Wait for data to arrive on any port. bool threadCallback( void* arg ) { this_t* p = static_cast(arg); unsigned readN; rc_t rc = serialPort::receive(p->mgrH,p->pollPeriodMs,readN); if( rc != kOkRC && rc != kTimeOutRC ) { cwLogError(rc,"Serial server receive failed."); return false; } return true; } } } cw::rc_t cw::serialPortSrv::create( handle_t& h, unsigned pollPeriodMs, unsigned recvBufByteN ) { rc_t rc = kOkRC; this_t* p = mem::allocZ(); if((rc = serialPort::create( p->mgrH, recvBufByteN)) != kOkRC ) goto errLabel; if((rc = thread::create( p->threadH, threadCallback, p, "serial_srv")) != kOkRC ) goto errLabel; p->pollPeriodMs = pollPeriodMs; errLabel: if( rc != kOkRC ) _destroy(p); else h.set(p); return rc; } cw::rc_t cw::serialPortSrv::destroy(handle_t& h ) { rc_t rc = kOkRC; if( !h.isValid() ) return rc; this_t* p = _handleToPtr(h); if((rc = _destroy(p)) != kOkRC ) return rc; h.clear(); return rc; } cw::serialPort::handle_t cw::serialPortSrv::serialHandle( handle_t h ) { this_t* p = _handleToPtr(h); return p->mgrH; } cw::thread::handle_t cw::serialPortSrv::threadHandle( handle_t h ) { this_t* p = _handleToPtr(h); return p->threadH; } cw::rc_t cw::serialPortSrv::start( handle_t h ) { this_t* p = _handleToPtr(h); return cw::thread::pause(p->threadH, thread::kWaitFl ); } cw::rc_t cw::serialPortSrv::pause( handle_t h ) { this_t* p = _handleToPtr(h); return cw::thread::pause(p->threadH, thread::kPauseFl | thread::kWaitFl ); } cw::rc_t cw::serialPortSrv::send( handle_t h, unsigned portId, const void* byteA, unsigned byteN ) { this_t* p = _handleToPtr(h); return cw::serialPort::send(p->mgrH,portId,byteA,byteN); } namespace cw { void serialPortSrvTestCb( void* arg, unsigned userId, const void* byteA, unsigned byteN ) { const char* text = static_cast(byteA); for(unsigned i=0; i