gfaserial.c 21 KB

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