serial.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. #include "serial.h"
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/time.h>
  9. #include <termios.h>
  10. #include <unistd.h>
  11. #define DBG_ENABLE
  12. #define DBG_COLOR
  13. #define DBG_SECTION_NAME "serial"
  14. #define DBG_LEVEL DBG_LOG
  15. #include "dbg_log.h"
  16. int serial_init(const char *device,
  17. int baud, char parity, int data_bit,
  18. int stop_bit, struct termios *old_tios)
  19. {
  20. struct termios tios;
  21. speed_t speed;
  22. int flags;
  23. /* The O_NOCTTY flag tells UNIX that this program doesn't want
  24. to be the "controlling terminal" for that port. If you
  25. don't specify this then any input (such as keyboard abort
  26. signals and so forth) will affect your process
  27. Timeouts are ignored in canonical input mode or when the
  28. NDELAY option is set on the file via open or fcntl */
  29. flags = O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL;
  30. #ifdef O_CLOEXEC
  31. flags |= O_CLOEXEC;
  32. #endif
  33. int s = open(device, flags);
  34. if (s == -1) {
  35. LOG_E("ERROR Can't open the device %s (%s)", device, strerror(errno));
  36. return -1;
  37. }
  38. flags = fcntl(s, F_GETFL, 0);
  39. flags |= O_NONBLOCK;
  40. fcntl(s, F_SETFL, flags);
  41. flags = fcntl(s, F_GETFD);
  42. flags |= FD_CLOEXEC;
  43. fcntl(s, F_SETFD, flags);
  44. /* Save */
  45. tcgetattr(s, old_tios);
  46. memset(&tios, 0, sizeof(struct termios));
  47. /* C_ISPEED Input baud (new interface)
  48. C_OSPEED Output baud (new interface)
  49. */
  50. switch (baud) {
  51. case 110:
  52. speed = B110;
  53. break;
  54. case 300:
  55. speed = B300;
  56. break;
  57. case 600:
  58. speed = B600;
  59. break;
  60. case 1200:
  61. speed = B1200;
  62. break;
  63. case 2400:
  64. speed = B2400;
  65. break;
  66. case 4800:
  67. speed = B4800;
  68. break;
  69. case 9600:
  70. speed = B9600;
  71. break;
  72. case 19200:
  73. speed = B19200;
  74. break;
  75. case 38400:
  76. speed = B38400;
  77. break;
  78. #ifdef B57600
  79. case 57600:
  80. speed = B57600;
  81. break;
  82. #endif
  83. #ifdef B115200
  84. case 115200:
  85. speed = B115200;
  86. break;
  87. #endif
  88. #ifdef B230400
  89. case 230400:
  90. speed = B230400;
  91. break;
  92. #endif
  93. #ifdef B460800
  94. case 460800:
  95. speed = B460800;
  96. break;
  97. #endif
  98. #ifdef B500000
  99. case 500000:
  100. speed = B500000;
  101. break;
  102. #endif
  103. #ifdef B576000
  104. case 576000:
  105. speed = B576000;
  106. break;
  107. #endif
  108. #ifdef B921600
  109. case 921600:
  110. speed = B921600;
  111. break;
  112. #endif
  113. #ifdef B1000000
  114. case 1000000:
  115. speed = B1000000;
  116. break;
  117. #endif
  118. #ifdef B1152000
  119. case 1152000:
  120. speed = B1152000;
  121. break;
  122. #endif
  123. #ifdef B1500000
  124. case 1500000:
  125. speed = B1500000;
  126. break;
  127. #endif
  128. #ifdef B2500000
  129. case 2500000:
  130. speed = B2500000;
  131. break;
  132. #endif
  133. #ifdef B3000000
  134. case 3000000:
  135. speed = B3000000;
  136. break;
  137. #endif
  138. #ifdef B3500000
  139. case 3500000:
  140. speed = B3500000;
  141. break;
  142. #endif
  143. #ifdef B4000000
  144. case 4000000:
  145. speed = B4000000;
  146. break;
  147. #endif
  148. default:
  149. speed = B9600;
  150. LOG_W("WARNING Unknown baud rate %d for %s (B9600 used)", baud, device);
  151. }
  152. /* Set the baud rate */
  153. if ((cfsetispeed(&tios, speed) < 0) ||
  154. (cfsetospeed(&tios, speed) < 0)) {
  155. close(s);
  156. s = -1;
  157. return -1;
  158. }
  159. /* C_CFLAG Control options
  160. CLOCAL Local line - do not change "owner" of port
  161. CREAD Enable receiver
  162. */
  163. tios.c_cflag |= (CREAD | CLOCAL);
  164. /* CSIZE, HUPCL, CRTSCTS (hardware flow control) */
  165. /* Set data bits (5, 6, 7, 8 bits)
  166. CSIZE Bit mask for data bits
  167. */
  168. tios.c_cflag &= ~CSIZE;
  169. switch (data_bit) {
  170. case 5:
  171. tios.c_cflag |= CS5;
  172. break;
  173. case 6:
  174. tios.c_cflag |= CS6;
  175. break;
  176. case 7:
  177. tios.c_cflag |= CS7;
  178. break;
  179. case 8:
  180. default:
  181. tios.c_cflag |= CS8;
  182. break;
  183. }
  184. /* Stop bit (1 or 2) */
  185. if (stop_bit == 1)
  186. tios.c_cflag &= ~CSTOPB;
  187. else /* 2 */
  188. tios.c_cflag |= CSTOPB;
  189. /* PARENB Enable parity bit
  190. PARODD Use odd parity instead of even */
  191. if (parity == 'N') {
  192. /* None */
  193. tios.c_cflag &= ~PARENB;
  194. } else if (parity == 'E') {
  195. /* Even */
  196. tios.c_cflag |= PARENB;
  197. tios.c_cflag &= ~PARODD;
  198. } else {
  199. /* Odd */
  200. tios.c_cflag |= PARENB;
  201. tios.c_cflag |= PARODD;
  202. }
  203. /* Read the man page of termios if you need more information. */
  204. /* This field isn't used on POSIX systems
  205. tios.c_line = 0;
  206. */
  207. /* C_LFLAG Line options
  208. ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals
  209. ICANON Enable canonical input (else raw)
  210. XCASE Map uppercase \lowercase (obsolete)
  211. ECHO Enable echoing of input characters
  212. ECHOE Echo erase character as BS-SP-BS
  213. ECHOK Echo NL after kill character
  214. ECHONL Echo NL
  215. NOFLSH Disable flushing of input buffers after
  216. interrupt or quit characters
  217. IEXTEN Enable extended functions
  218. ECHOCTL Echo control characters as ^char and delete as ~?
  219. ECHOPRT Echo erased character as character erased
  220. ECHOKE BS-SP-BS entire line on line kill
  221. FLUSHO Output being flushed
  222. PENDIN Retype pending input at next read or input char
  223. TOSTOP Send SIGTTOU for background output
  224. Canonical input is line-oriented. Input characters are put
  225. into a buffer which can be edited interactively by the user
  226. until a CR (carriage return) or LF (line feed) character is
  227. received.
  228. Raw input is unprocessed. Input characters are passed
  229. through exactly as they are received, when they are
  230. received. Generally you'll deselect the ICANON, ECHO,
  231. ECHOE, and ISIG options when using raw input
  232. */
  233. /* Raw input */
  234. tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  235. /* C_IFLAG Input options
  236. Constant Description
  237. INPCK Enable parity check
  238. IGNPAR Ignore parity errors
  239. PARMRK Mark parity errors
  240. ISTRIP Strip parity bits
  241. IXON Enable software flow control (outgoing)
  242. IXOFF Enable software flow control (incoming)
  243. IXANY Allow any character to start flow again
  244. IGNBRK Ignore break condition
  245. BRKINT Send a SIGINT when a break condition is detected
  246. INLCR Map NL to CR
  247. IGNCR Ignore CR
  248. ICRNL Map CR to NL
  249. IUCLC Map uppercase to lowercase
  250. IMAXBEL Echo BEL on input line too long
  251. */
  252. if (parity == 'N') {
  253. /* None */
  254. tios.c_iflag &= ~INPCK;
  255. } else {
  256. tios.c_iflag |= INPCK;
  257. }
  258. /* Software flow control is disabled */
  259. tios.c_iflag &= ~(IXON | IXOFF | IXANY);
  260. /* C_OFLAG Output options
  261. OPOST Postprocess output (not set = raw output)
  262. ONLCR Map NL to CR-NL
  263. ONCLR ant others needs OPOST to be enabled
  264. */
  265. /* Raw ouput */
  266. tios.c_oflag &= ~OPOST;
  267. /* C_CC Control characters
  268. VMIN Minimum number of characters to read
  269. VTIME Time to wait for data (tenths of seconds)
  270. UNIX serial interface drivers provide the ability to
  271. specify character and packet timeouts. Two elements of the
  272. c_cc array are used for timeouts: VMIN and VTIME. Timeouts
  273. are ignored in canonical input mode or when the NDELAY
  274. option is set on the file via open or fcntl.
  275. VMIN specifies the minimum number of characters to read. If
  276. it is set to 0, then the VTIME value specifies the time to
  277. wait for every character read. Note that this does not mean
  278. that a read call for N bytes will wait for N characters to
  279. come in. Rather, the timeout will apply to the first
  280. character and the read call will return the number of
  281. characters immediately available (up to the number you
  282. request).
  283. If VMIN is non-zero, VTIME specifies the time to wait for
  284. the first character read. If a character is read within the
  285. time given, any read will block (wait) until all VMIN
  286. characters are read. That is, once the first character is
  287. read, the serial interface driver expects to receive an
  288. entire packet of characters (VMIN bytes total). If no
  289. character is read within the time allowed, then the call to
  290. read returns 0. This method allows you to tell the serial
  291. driver you need exactly N bytes and any read call will
  292. return 0 or N bytes. However, the timeout only applies to
  293. the first character read, so if for some reason the driver
  294. misses one character inside the N byte packet then the read
  295. call could block forever waiting for additional input
  296. characters.
  297. VTIME specifies the amount of time to wait for incoming
  298. characters in tenths of seconds. If VTIME is set to 0 (the
  299. default), reads will block (wait) indefinitely unless the
  300. NDELAY option is set on the port with open or fcntl.
  301. */
  302. /* Unused because we use open with the NDELAY option */
  303. tios.c_cc[VMIN] = 0;
  304. tios.c_cc[VTIME] = 0;
  305. if (tcsetattr(s, TCSANOW, &tios) < 0) {
  306. close(s);
  307. s = -1;
  308. return -1;
  309. }
  310. return s;
  311. }
  312. void serial_close(int s, struct termios *old_tios)
  313. {
  314. if (s != -1) {
  315. tcsetattr(s, TCSANOW, old_tios);
  316. close(s);
  317. }
  318. }
  319. int serial_send(int s, const uint8_t *buf, int length)
  320. {
  321. return write(s, buf, length);
  322. }
  323. int serial_receive(int s, uint8_t *buf, int bufsz, int timeout)
  324. {
  325. int len = 0;
  326. int rc = 0;
  327. fd_set rset;
  328. struct timeval tv;
  329. while (bufsz > 0) {
  330. FD_ZERO(&rset);
  331. FD_SET(s, &rset);
  332. tv.tv_sec = timeout / 1000;
  333. tv.tv_usec = (timeout % 1000) * 1000;
  334. rc = select(s + 1, &rset, NULL, NULL, &tv);
  335. if (rc == -1) {
  336. if (errno == EINTR)
  337. continue;
  338. }
  339. if (rc <= 0) {
  340. break;
  341. }
  342. rc = read(s, buf + len, bufsz);
  343. if (rc <= 0) {
  344. break;
  345. }
  346. len += rc;
  347. bufsz -= rc;
  348. timeout = 20;
  349. }
  350. if (rc >= 0) {
  351. rc = len;
  352. }
  353. return rc;
  354. }
  355. int serial_flush(int s)
  356. {
  357. if (s != -1) {
  358. tcflush(s, TCIOFLUSH);
  359. }
  360. return 0;
  361. }