gfaserial.c 19 KB

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