gfaserial.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <malloc.h>
  5. #include <fcntl.h>
  6. #include <errno.h>
  7. #include <termios.h>
  8. #include <unistd.h>
  9. #include <ctype.h>
  10. #include <sys/file.h>
  11. #include "gfaserial.h"
  12. #define min(a, b) (((a) < (b)) ? (a) : (b))
  13. /////////////////////////////////////////////////////////////////////////////
  14. // https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/#everything-is-a-file
  15. /////////////////////////////////////////////////////////////////////////////
  16. typedef struct _GFA_SERIAL_DEVICE
  17. {
  18. int fd;
  19. char *pszDeviceName;
  20. GFA_SER_CFG_PARAMS cfg;
  21. struct termios tty;
  22. struct termios ttySave;
  23. struct timeval tvRX;
  24. struct timeval tvTX;
  25. struct timeval tvEcho;
  26. struct timeval tvPurge;
  27. }GFA_SERIAL_DEVICE, *LPGFA_SERIAL_DEVICE;
  28. typedef const GFA_SERIAL_DEVICE *LPCGFA_SERIAL_DEVICE;
  29. /////////////////////////////////////////////////////////////////////////////
  30. static speed_t _MapBaudrate(uint32_t b)
  31. {
  32. speed_t s;
  33. switch(b)
  34. {
  35. case 50: s = B50; break;
  36. case 75: s = B75; break;
  37. case 110: s = B110; break;
  38. case 134: s = B134; break;
  39. case 150: s = B150; break;
  40. case 200: s = B200; break;
  41. case 300: s = B300; break;
  42. case 600: s = B600; break;
  43. case 1200: s = B1200; break;
  44. case 1800: s = B1800; break;
  45. case 2400: s = B2400; break;
  46. case 4800: s = B4800; break;
  47. case 9600: s = B9600; break;
  48. case 19200: s = B19200; break;
  49. case 38400: s = B38400; break;
  50. case 57600: s = B57600; break;
  51. case 115200: s = B115200; break;
  52. case 230400: s = B230400; break;
  53. case 460800: s = B460800; break;
  54. case 921600: s = B921600; break;
  55. default: s = (speed_t)-1; break;
  56. }
  57. return s;
  58. }
  59. /////////////////////////////////////////////////////////////////////////////
  60. static void _SetDefaultTimeouts(LPGFA_SERIAL_DEVICE psd)
  61. {
  62. if(psd)
  63. {
  64. psd->tvRX.tv_sec = 0;
  65. psd->tvRX.tv_usec = 200000;
  66. psd->tvTX.tv_sec = 0;
  67. psd->tvTX.tv_usec = 100000;
  68. psd->tvEcho.tv_sec = 0;
  69. psd->tvEcho.tv_usec = 50000;
  70. psd->tvPurge.tv_sec = 0;
  71. psd->tvPurge.tv_usec = 10000;
  72. }
  73. }
  74. static void _CopyTimeval(struct timeval *ptvTo, const struct timeval *ptvFrom)
  75. {
  76. ptvTo->tv_sec = ptvFrom->tv_sec;
  77. ptvTo->tv_usec = ptvFrom->tv_usec;
  78. }
  79. /////////////////////////////////////////////////////////////////////////////
  80. static bool _ReadEcho(HGFADEVICE hSer, const void *pData, size_t nWritten)
  81. {
  82. uint8_t b[256];
  83. ssize_t nRet;
  84. struct timeval tvSave;
  85. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  86. ssize_t nLeft = (ssize_t)nWritten, nRead = 0, nToRead;
  87. const char *pszData = (const char*)pData;
  88. if(!nLeft)
  89. return false;
  90. if( !GfaSerialGetTimeouts(hSer, &tvSave, NULL) ||
  91. !GfaSerialSetTimeouts(hSer, &psd->tvEcho, NULL))
  92. return false;
  93. do
  94. {
  95. nToRead = min(nLeft, (ssize_t)sizeof(b));
  96. if((nRet = GfaSerialReceive(hSer, b, nToRead)) <= 0)
  97. {
  98. GfaSerialSetTimeouts(hSer, &tvSave, NULL);
  99. return false;
  100. }
  101. if(memcmp(b, pszData, nRet))
  102. {
  103. GfaSerialSetTimeouts(hSer, &tvSave, NULL);
  104. return false;
  105. }
  106. pszData += nRet;
  107. nRead += nRet;
  108. nLeft = (ssize_t)nWritten - nRead;
  109. }
  110. while(nLeft > 0);
  111. GfaSerialSetTimeouts(hSer, &tvSave, NULL);
  112. return (nRead == (ssize_t)nWritten);
  113. }
  114. /////////////////////////////////////////////////////////////////////////////
  115. /////////////////////////////////////////////////////////////////////////////
  116. /////////////////////////////////////////////////////////////////////////////
  117. HGFADEVICE GfaSerialOpen(const char *pszDeviceName, LPCGFA_SER_CFG_PARAMS pscp, size_t nSizeCfgParams)
  118. {
  119. if(pszDeviceName && *pszDeviceName && pscp && nSizeCfgParams >= sizeof(GFA_SER_CFG_PARAMS))
  120. {
  121. LPGFA_SERIAL_DEVICE psd = malloc(sizeof(GFA_SERIAL_DEVICE));
  122. memset(psd, 0, sizeof(GFA_SERIAL_DEVICE));
  123. /////////////////////////////////////////////////////////////////////
  124. // Open the device
  125. if((psd->fd = open(pszDeviceName, O_RDWR | O_NONBLOCK)) < 0)
  126. {
  127. GfaSerialClose(psd);
  128. return NULL;
  129. }
  130. /////////////////////////////////////////////////////////////////////
  131. // Lock device descriptor exclusive
  132. if(flock(psd->fd, LOCK_EX | LOCK_NB) < 0)
  133. {
  134. GfaSerialClose(psd);
  135. return NULL;
  136. }
  137. /////////////////////////////////////////////////////////////////////
  138. // Get current config and save it for restore on close
  139. if(tcgetattr(psd->fd, &psd->tty) != 0)
  140. {
  141. GfaSerialClose(psd);
  142. return NULL;
  143. }
  144. memcpy(&psd->ttySave, &psd->tty, sizeof(struct termios));
  145. /////////////////////////////////////////////////////////////////////
  146. // Set new config
  147. if(GfaSerialSetConfig(psd, pscp, nSizeCfgParams) < 0)
  148. {
  149. GfaSerialClose(psd);
  150. return NULL;
  151. }
  152. /////////////////////////////////////////////////////////////////////
  153. // Set deault timeouts.
  154. _SetDefaultTimeouts(psd);
  155. /////////////////////////////////////////////////////////////////////
  156. // Everything ok.
  157. psd->pszDeviceName = strdup(pszDeviceName);
  158. GfaSerialPurgeRXBuffer((HGFADEVICE)psd); // clear RX buffer
  159. return (HGFADEVICE)psd;
  160. }
  161. errno = EINVAL;
  162. return NULL;
  163. }
  164. /////////////////////////////////////////////////////////////////////////////
  165. void GfaSerialClose(HGFADEVICE hSer)
  166. {
  167. if(hSer)
  168. {
  169. int nErrno = errno;
  170. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  171. if(psd->fd >= 0)
  172. {
  173. tcsetattr(psd->fd, TCSAFLUSH, &psd->ttySave);
  174. flock(psd->fd, LOCK_UN | LOCK_NB);
  175. close(psd->fd);
  176. }
  177. if(psd->pszDeviceName)
  178. free(psd->pszDeviceName);
  179. free(psd);
  180. errno = nErrno;
  181. }
  182. }
  183. /////////////////////////////////////////////////////////////////////////////
  184. ssize_t GfaSerialGetConfig(HGFADEVICE hSer, LPGFA_SER_CFG_PARAMS pscp, size_t nSizeCfgParams)
  185. {
  186. if(hSer && pscp && nSizeCfgParams == sizeof(GFA_SER_CFG_PARAMS))
  187. {
  188. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  189. memcpy(pscp, &psd->cfg, sizeof(GFA_SER_CFG_PARAMS));
  190. return sizeof(GFA_SER_CFG_PARAMS);
  191. }
  192. errno = EINVAL;
  193. return -1;
  194. }
  195. /////////////////////////////////////////////////////////////////////////////
  196. int GfaSerialSetConfig(HGFADEVICE hSer, LPCGFA_SER_CFG_PARAMS pscp, size_t nSizeCfgParams)
  197. {
  198. if(hSer && pscp && nSizeCfgParams == sizeof(GFA_SER_CFG_PARAMS))
  199. {
  200. int nRet;
  201. speed_t s;
  202. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  203. /////////////////////////////////////////////////////////////////////
  204. // Baud Rate
  205. if((s = _MapBaudrate(pscp->baud)) == (speed_t)-1)
  206. {
  207. errno = EINVAL;
  208. return -1;
  209. }
  210. if( ((nRet = cfsetispeed(&psd->tty, s)) < 0) ||
  211. ((nRet = cfsetospeed(&psd->tty, s)) < 0))
  212. {
  213. return nRet;
  214. }
  215. /////////////////////////////////////////////////////////////////////
  216. // data bits
  217. switch(pscp->data)
  218. {
  219. case 5:
  220. psd->tty.c_cflag &= ~CSIZE;
  221. psd->tty.c_cflag |= CS5; // 5 bits per byte
  222. break;
  223. case 6:
  224. psd->tty.c_cflag &= ~CSIZE;
  225. psd->tty.c_cflag |= CS6; // 6 bits per byte
  226. break;
  227. case 7:
  228. psd->tty.c_cflag &= ~CSIZE;
  229. psd->tty.c_cflag |= CS7; // 7 bits per byte
  230. break;
  231. case 8:
  232. psd->tty.c_cflag &= ~CSIZE;
  233. psd->tty.c_cflag |= CS8; // 8 bits per byte
  234. break;
  235. default:
  236. errno = EINVAL;
  237. return -1;
  238. }
  239. /////////////////////////////////////////////////////////////////////
  240. // stop bits
  241. switch(pscp->stop)
  242. {
  243. case 1:
  244. psd->tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication
  245. break;
  246. case 2:
  247. psd->tty.c_cflag |= CSTOPB; // Set stop field, two stop bits used in communication
  248. break;
  249. default:
  250. errno = EINVAL;
  251. return -1;
  252. }
  253. /////////////////////////////////////////////////////////////////////
  254. // parity
  255. switch(toupper(pscp->parity))
  256. {
  257. case 'N':
  258. psd->tty.c_cflag &= ~(PARENB | PARODD); // Clear parity bit, disabling parity
  259. break;
  260. case 'E':
  261. psd->tty.c_cflag |= PARENB; // Set parity bit, enabling parity
  262. psd->tty.c_cflag &= ~PARODD; // Clear odd parity bit, enabling even parity
  263. break;
  264. case 'O':
  265. psd->tty.c_cflag |= (PARENB | PARODD); // Set parity bits, enabling odd parity
  266. break;
  267. default:
  268. errno = EINVAL;
  269. return -1;
  270. }
  271. /////////////////////////////////////////////////////////////////////
  272. // RTS/CTS flow control
  273. // If the CRTSCTS field is set, hardware RTS/CTS flow control is enabled. The most common setting here is to disable it.
  274. // Enabling this when it should be disabled can result in your serial port receiving no data, as the sender will buffer
  275. // it indefinitely, waiting for you to be “ready”.
  276. if(pscp->flowHW)
  277. psd->tty.c_cflag |= CRTSCTS; // Enable RTS/CTS hardware flow control
  278. else
  279. psd->tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
  280. /////////////////////////////////////////////////////////////////////
  281. // Setting CLOCAL disables modem-specific signal lines such as carrier detect. It also
  282. // prevents the controlling process from getting sent a SIGHUP signal when a modem disconnect
  283. // is detected, which is usually a good thing here. Setting CLOCAL allows us to read data (we definitely want that!).
  284. psd->tty.c_cflag |= (CREAD | CLOCAL); // Turn on READ & ignore ctrl lines (CLOCAL = 1)
  285. /////////////////////////////////////////////////////////////////////
  286. // UNIX systems provide two basic modes of input, canonical and non-canonical mode. In canonical mode, input is
  287. // processed when a new line character is received. The receiving application receives that data line-by-line.
  288. // This is usually undesirable when dealing with a serial port, and so we normally want to disable canonical mode.
  289. // Also, in canonical mode, some characters such as backspace are treated specially, and are used to edit the
  290. // current line of text (erase). Again, we don’t want this feature if processing raw serial data, as it will
  291. // cause particular bytes to go missing!
  292. psd->tty.c_lflag &= ~ICANON;
  293. /////////////////////////////////////////////////////////////////////
  294. // Echo
  295. // If this bit is set, sent characters will be echoed back. Because we disabled canonical mode,
  296. // I don’t think these bits actually do anything, but it doesn’t harm to disable them just in case!
  297. psd->tty.c_lflag &= ~ECHO; // Disable echo
  298. psd->tty.c_lflag &= ~ECHOE; // Disable erasure
  299. psd->tty.c_lflag &= ~ECHONL; // Disable new-line echo
  300. /////////////////////////////////////////////////////////////////////
  301. // Signal chars
  302. // When the ISIG bit is set, INTR, QUIT and SUSP characters are interpreted.
  303. // We don’t want this with a serial port, so clear this bit.
  304. psd->tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
  305. /////////////////////////////////////////////////////////////////////
  306. // Software Flow Control (IXOFF, IXON, IXANY)
  307. // Clearing IXOFF, IXON and IXANY disables software flow control.
  308. if(pscp->flowSW)
  309. psd->tty.c_iflag |= (IXON | IXOFF); // Turn on s/w flow ctrl
  310. else
  311. psd->tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
  312. /////////////////////////////////////////////////////////////////////
  313. // Disabling Special Handling Of Bytes On Receive
  314. // Clearing all of the following bits disables any special handling of the bytes as they
  315. // are received by the serial port, before they are passed to the application. We just want the raw data!
  316. psd->tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable any special handling of received bytes
  317. /////////////////////////////////////////////////////////////////////
  318. // When configuring a serial port, we want to disable any special handling of output chars/bytes.
  319. psd->tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
  320. psd->tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
  321. /////////////////////////////////////////////////////////////////////
  322. // VMIN and VTIME
  323. psd->tty.c_cc[VTIME] = psd->tty.c_cc[VMIN] = 0; // No blocking, return immediately with what is available
  324. /////////////////////////////////////////////////////////////////////
  325. // set configuration
  326. if((nRet = tcsetattr(psd->fd, TCSAFLUSH, &psd->tty)) == 0)
  327. memcpy(&psd->cfg, pscp, sizeof(GFA_SER_CFG_PARAMS));
  328. return nRet;
  329. }
  330. errno = EINVAL;
  331. return -1;
  332. }
  333. /////////////////////////////////////////////////////////////////////////////
  334. int GfaSerialSetBaudrate(HGFADEVICE hSer, uint32_t nBaudrate)
  335. {
  336. if(hSer && GfaSerialIsValidBaudrate(nBaudrate))
  337. {
  338. GFA_SER_CFG_PARAMS scp;
  339. if(GfaSerialGetConfig(hSer, &scp, sizeof(scp)) == sizeof(scp))
  340. {
  341. scp.baud = nBaudrate;
  342. return GfaSerialSetConfig(hSer, &scp, sizeof(scp));
  343. }
  344. }
  345. errno = EINVAL;
  346. return -1;
  347. }
  348. /////////////////////////////////////////////////////////////////////////////
  349. bool GfaSerialGetDeviceInterface(LPGFA_GENERIC_DEVICE_INTERFACE pDevItf)
  350. {
  351. if(pDevItf)
  352. {
  353. pDevItf->pfnOpen = (PFN_GFA_GENERIC_DEV_OPEN)GfaSerialOpen;
  354. pDevItf->pfnClose = GfaSerialClose;
  355. pDevItf->pfnGetConfig = (PFN_GFA_GENERIC_DEV_GET_CONFIG)GfaSerialGetConfig;
  356. pDevItf->pfnSetConfig = (PFN_GFA_GENERIC_DEV_SET_CONFIG)GfaSerialSetConfig;
  357. pDevItf->pfnIsValidBaudrate = GfaSerialIsValidBaudrate;
  358. pDevItf->pfnSetBaudrate = GfaSerialSetBaudrate;
  359. pDevItf->pfnGetTimeouts = GfaSerialGetTimeouts;
  360. pDevItf->pfnSetTimeouts = GfaSerialSetTimeouts;
  361. pDevItf->pfnPurgeRXBuffer = GfaSerialPurgeRXBuffer;
  362. pDevItf->pfnReceive = GfaSerialReceive;
  363. pDevItf->pfnRead = GfaSerialRead;
  364. pDevItf->pfnPop = GfaSerialPop;
  365. pDevItf->pfnPeek = GfaSerialPeek;
  366. pDevItf->pfnTransmit = GfaSerialTransmit;
  367. pDevItf->pfnWrite = GfaSerialWrite;
  368. pDevItf->pfnPush = GfaSerialPush;
  369. return true;
  370. }
  371. errno = EINVAL;
  372. return false;
  373. }
  374. /////////////////////////////////////////////////////////////////////////////
  375. bool GfaSerialIsValidBaudrate(uint32_t nBaudrate)
  376. {
  377. return _MapBaudrate(nBaudrate) != (speed_t)-1;
  378. }
  379. /////////////////////////////////////////////////////////////////////////////
  380. ssize_t GfaSerialPurgeRXBuffer(HGFADEVICE hSer)
  381. {
  382. struct timeval tvSave;
  383. if(hSer && GfaSerialGetTimeouts(hSer, &tvSave, NULL))
  384. {
  385. uint8_t b[256];
  386. ssize_t nRet = 0, nRx;
  387. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  388. GfaSerialSetTimeouts(hSer, &psd->tvPurge, NULL);
  389. while((nRx = GfaSerialReceive(hSer, b, sizeof(b))) > 0)
  390. nRet += nRx;
  391. GfaSerialSetTimeouts(hSer, &tvSave, NULL);
  392. return nRet;
  393. }
  394. errno = EINVAL;
  395. return -1;
  396. }
  397. /////////////////////////////////////////////////////////////////////////////
  398. bool GfaSerialGetTimeouts(HGFADEVICE hSer, struct timeval *ptvRX, struct timeval *ptvTX)
  399. {
  400. if(hSer && (ptvRX || ptvTX))
  401. {
  402. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  403. if(ptvRX)
  404. memcpy(ptvRX, &psd->tvRX, sizeof(struct timeval));
  405. if(ptvTX)
  406. memcpy(ptvTX, &psd->tvTX, sizeof(struct timeval));
  407. return true;
  408. }
  409. errno = EINVAL;
  410. return false;
  411. }
  412. /////////////////////////////////////////////////////////////////////////////
  413. bool GfaSerialSetTimeouts(HGFADEVICE hSer, const struct timeval *ptvRX, const struct timeval *ptvTX)
  414. {
  415. if(hSer && (ptvRX || ptvTX))
  416. {
  417. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  418. if(ptvRX)
  419. memcpy(&psd->tvRX, ptvRX, sizeof(struct timeval));
  420. if(ptvTX)
  421. memcpy(&psd->tvTX, ptvTX, sizeof(struct timeval));
  422. return true;
  423. }
  424. errno = EINVAL;
  425. return false;
  426. }
  427. /////////////////////////////////////////////////////////////////////////////
  428. ssize_t GfaSerialTransmit(HGFADEVICE hSer, const void *pData, size_t nCbToWrite)
  429. {
  430. if(hSer && pData && nCbToWrite)
  431. {
  432. fd_set fds;
  433. struct timeval tv;
  434. ssize_t nRet = 0;
  435. ssize_t nWritten = 0;
  436. const char *pszData = (const char*)pData;
  437. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  438. _CopyTimeval(&tv, &psd->tvTX);
  439. while(nWritten < (ssize_t)nCbToWrite)
  440. {
  441. FD_ZERO(&fds);
  442. FD_SET(psd->fd, &fds);
  443. nRet = select(psd->fd + 1, NULL, &fds, NULL, &tv);
  444. if(nRet < 0)
  445. return -1;
  446. else if(nRet == 0)
  447. {
  448. errno = ETIMEDOUT;
  449. break;
  450. }
  451. nRet = write(psd->fd, pszData, nCbToWrite - nWritten);
  452. if(nRet < 0)
  453. return -1;
  454. else if(nRet == 0)
  455. {
  456. // should never happen!
  457. errno = ENODATA;
  458. return -1;
  459. }
  460. else
  461. {
  462. if( psd->cfg.bHandleTxEcho &&
  463. !_ReadEcho(hSer, pszData, nRet))
  464. {
  465. GfaSerialPurgeRXBuffer(hSer);
  466. errno = ECOMM;
  467. return -1;
  468. }
  469. pszData += nRet;
  470. nWritten += nRet;
  471. }
  472. }
  473. return nWritten;
  474. }
  475. errno = EINVAL;
  476. return -1;
  477. }
  478. /////////////////////////////////////////////////////////////////////////////
  479. ssize_t GfaSerialWrite(HGFADEVICE hSer, const void *pData, size_t nCbData)
  480. {
  481. if(hSer && pData && nCbData)
  482. {
  483. ssize_t nRet;
  484. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  485. if((nRet = write(psd->fd, pData, nCbData)) > 0)
  486. {
  487. if( psd->cfg.bHandleTxEcho &&
  488. !_ReadEcho(hSer, pData, nRet))
  489. {
  490. GfaSerialPurgeRXBuffer(hSer);
  491. errno = ECOMM;
  492. return -1;
  493. }
  494. }
  495. return nRet;
  496. }
  497. errno = EINVAL;
  498. return -1;
  499. }
  500. /////////////////////////////////////////////////////////////////////////////
  501. ssize_t GfaSerialPush(HGFADEVICE hSer, uint8_t b)
  502. {
  503. if(hSer)
  504. {
  505. fd_set fds;
  506. struct timeval tv;
  507. ssize_t nRet = 0;
  508. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  509. _CopyTimeval(&tv, &psd->tvTX);
  510. FD_ZERO(&fds);
  511. FD_SET(psd->fd, &fds);
  512. nRet = select(psd->fd + 1, NULL, &fds, NULL, &tv);
  513. if(nRet < 0)
  514. return -1;
  515. else if(nRet == 0)
  516. {
  517. errno = ETIMEDOUT;
  518. return 0;
  519. }
  520. if((nRet = write(psd->fd, &b, 1)) == 1)
  521. {
  522. if( psd->cfg.bHandleTxEcho &&
  523. !_ReadEcho(hSer, &b, 1))
  524. {
  525. GfaSerialPurgeRXBuffer(hSer);
  526. errno = ECOMM;
  527. return -1;
  528. }
  529. }
  530. return nRet;
  531. }
  532. errno = EINVAL;
  533. return -1;
  534. }
  535. /////////////////////////////////////////////////////////////////////////////
  536. ssize_t GfaSerialReceive(HGFADEVICE hSer, void *pBuf, size_t nCbToRead)
  537. {
  538. if(hSer && pBuf && nCbToRead)
  539. {
  540. fd_set fds;
  541. struct timeval tv;
  542. ssize_t nRet = 0;
  543. ssize_t nRead = 0;
  544. char *pszBuf = (char*)pBuf;
  545. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  546. _CopyTimeval(&tv, &psd->tvRX);
  547. while(nRead < (ssize_t)nCbToRead)
  548. {
  549. FD_ZERO(&fds);
  550. FD_SET(psd->fd, &fds);
  551. nRet = select(psd->fd + 1, &fds, NULL, NULL, &tv);
  552. if(nRet < 0)
  553. return -1;
  554. else if(nRet == 0)
  555. {
  556. errno = ETIMEDOUT;
  557. break;
  558. }
  559. nRet = read(psd->fd, pszBuf, nCbToRead - nRead);
  560. if(nRet < 0)
  561. return -1;
  562. else if(nRet == 0)
  563. {
  564. // should never happen!
  565. errno = ENODATA;
  566. return -1;
  567. }
  568. else
  569. {
  570. pszBuf += nRet;
  571. nRead += nRet;
  572. }
  573. }
  574. return nRead;
  575. }
  576. errno = EINVAL;
  577. return -1;
  578. }
  579. /////////////////////////////////////////////////////////////////////////////
  580. ssize_t GfaSerialRead(HGFADEVICE hSer, void *pBuf, size_t nCbToRead)
  581. {
  582. if(hSer && pBuf && nCbToRead)
  583. {
  584. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  585. return read(psd->fd, pBuf, nCbToRead);
  586. }
  587. errno = EINVAL;
  588. return -1;
  589. }
  590. /////////////////////////////////////////////////////////////////////////////
  591. ssize_t GfaSerialPop(HGFADEVICE hSer, uint8_t *pb)
  592. {
  593. if(hSer && pb)
  594. {
  595. fd_set fds;
  596. struct timeval tv;
  597. ssize_t nRet = 0;
  598. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  599. FD_ZERO(&fds);
  600. FD_SET(psd->fd, &fds);
  601. _CopyTimeval(&tv, &psd->tvRX);
  602. nRet = select(psd->fd + 1, &fds, NULL, NULL, &tv);
  603. if(nRet < 0)
  604. return -1;
  605. else if(nRet == 0)
  606. {
  607. errno = ETIMEDOUT;
  608. return 0;
  609. }
  610. return read(psd->fd, pb, 1);
  611. }
  612. errno = EINVAL;
  613. return -1;
  614. }
  615. /////////////////////////////////////////////////////////////////////////////
  616. ssize_t GfaSerialPeek(HGFADEVICE hSer)
  617. {
  618. if(hSer)
  619. {
  620. fd_set fds;
  621. struct timeval tvNull = {0, 0};
  622. LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
  623. FD_ZERO(&fds);
  624. FD_SET(psd->fd, &fds);
  625. return select(psd->fd + 1, &fds, NULL, NULL, &tvNull);
  626. }
  627. errno = EINVAL;
  628. return -1;
  629. }