Monitoring du Phytotron
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

serial.c 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <sys/select.h>
  5. #include <string.h>
  6. #include <unistd.h> //Used for UART
  7. #include <fcntl.h> //Used for UART
  8. #include <termios.h> //Used for UART
  9. #include "serial.h"
  10. extern int verbosity;
  11. /* -------------------------------------------------------------------- */
  12. static int baudrate2const(int bauds)
  13. {
  14. int br;
  15. switch (bauds)
  16. {
  17. case 1200: br = B1200; break;
  18. case 2400: br = B2400; break;
  19. case 4800: br = B4800; break;
  20. case 9600: br = B9600; break;
  21. case 19200: br = B19200; break;
  22. case 38400: br = B38400; break;
  23. case 57600: br = B57600; break;
  24. case 115200: br = B115200; break;
  25. default:
  26. fprintf(stderr, "baudrate %d invalide\n", bauds);
  27. exit(1);
  28. break;
  29. }
  30. return br;
  31. }
  32. /* -------------------------------------------------------------------- */
  33. int prepare_UART(char *port, int baudrate)
  34. {
  35. int uart0 = -1;
  36. int baudbits;
  37. struct termios options;
  38. #if DEBUG_LEVEL
  39. fprintf(stderr, ">>> %s ( %s %d )\n", __func__, port, baudrate);
  40. #endif
  41. // OPEN THE UART
  42. // The flags (defined in fcntl.h):
  43. // Access modes (use 1 of these):
  44. // O_RDONLY - Open for reading only.
  45. // O_RDWR - Open for reading and writing.
  46. // O_WRONLY - Open for writing only.
  47. //
  48. // O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode.
  49. // When set read requests on the file can return immediately with a
  50. // failure status
  51. // if there is no input immediately available (instead of blocking).
  52. // Likewise, write requests can also return
  53. // immediately with a failure status if the output can't be written
  54. // immediately.
  55. //
  56. // O_NOCTTY - When set and path identifies a terminal device, open()
  57. // shall not cause the terminal device to become the controlling terminal
  58. // for the process.
  59. uart0 = open(port, O_RDWR | O_NOCTTY);
  60. if (uart0 < 0)
  61. {
  62. perror("unable to open uart ");
  63. return -1;
  64. }
  65. // CONFIGURE THE UART
  66. // The flags defined in /usr/include/termios.h -
  67. // see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html
  68. // Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600,
  69. // B115200, B230400, B460800, B500000, B576000, B921600, B1000000,
  70. // B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000
  71. // CSIZE:- CS5, CS6, CS7, CS8
  72. // CLOCAL - Ignore modem status lines
  73. // CREAD - Enable receiver
  74. // IGNPAR = Ignore characters with parity errors
  75. // ICRNL - Map CR to NL on input (Use for ASCII comms where you want
  76. // to auto correct end of line characters - don't use for bianry comms!)
  77. // PARENB - Parity enable
  78. // PARODD - Odd parity (else even)
  79. baudbits = baudrate2const(baudrate);
  80. #if DEBUG_LEVEL
  81. fprintf(stderr, "%d -> 0x%04x\n", baudrate, baudbits);
  82. #endif
  83. memset(&options, 0, sizeof(options));
  84. tcgetattr(uart0, &options);
  85. options.c_cflag = baudbits | CS8 | CLOCAL | CREAD;
  86. options.c_iflag = IGNPAR;
  87. options.c_oflag = IGNPAR;
  88. options.c_lflag = 0;
  89. cfmakeraw(&options); /* XXX */
  90. options.c_cc[VMIN] = 1; /* ask for blocking read */
  91. tcflush(uart0, TCIOFLUSH);
  92. tcsetattr(uart0, TCSANOW, &options);
  93. tcflush(uart0, TCIOFLUSH); /* do it again, sam */
  94. if (verbosity) {
  95. fprintf(stderr, "%s %s uart0 = %d\n",
  96. __FILE__, __func__, uart0);
  97. }
  98. return uart0;
  99. }
  100. /* -------------------------------------------------------------------- */
  101. /*
  102. * this function have NO timeout !
  103. * blocking read is not blocking, wtf ?
  104. */
  105. int getbyte(int fd)
  106. {
  107. unsigned char byte;
  108. int foo;
  109. byte = 0;
  110. foo = read(fd, &byte, 1);
  111. if (1 != foo)
  112. {
  113. fprintf(stderr, "%s : byte %d rd %d errno %d\n",
  114. __func__, byte, foo, errno);
  115. /* XXX */
  116. exit(1);
  117. return -1;
  118. }
  119. return (int)byte;
  120. }
  121. /* -------------------------------------------------------------------- */
  122. int putbyte(int fd, unsigned char byte)
  123. {
  124. int foo = -1;
  125. foo = write(fd, &byte, 1);
  126. if (1 != foo)
  127. {
  128. fprintf(stderr, "%s : %d -> %d errno %d\n",
  129. __func__, byte, foo, errno);
  130. }
  131. return foo;
  132. }
  133. /* -------------------------------------------------------------------- */
  134. /* timeout is in milliseconds */
  135. int getbyte_to (int fd, int to_ms)
  136. {
  137. unsigned char byte;
  138. struct timeval timeout;
  139. fd_set rfds;
  140. int retval;
  141. timeout.tv_sec = to_ms / 1000;
  142. timeout.tv_usec = (to_ms % 1000) * 1000;
  143. #if DEBUG_LEVEL > 1
  144. fprintf(stderr, "timeout %6d is %4ld.%6ld\n", to_ms,
  145. timeout.tv_sec, timeout.tv_usec);
  146. #endif
  147. FD_ZERO (&rfds);
  148. FD_SET (fd, &rfds);
  149. retval = select(1, &rfds, NULL, NULL, &timeout);
  150. #if DEBUG_LEVEL
  151. fprintf(stderr, "%s : select on fd %d -> %d\n", __func__, fd, retval);
  152. #endif
  153. switch (retval) {
  154. case -1:
  155. fprintf(stderr, "omg ?\n");
  156. retval = -1;
  157. break;
  158. case 0:
  159. fprintf(stderr, "timeout %ld.%ld\n",
  160. timeout.tv_sec, timeout.tv_usec);
  161. retval = -99;
  162. break;
  163. default:
  164. fprintf(stderr, "%s default -> %d\n", __func__, retval);
  165. if (retval==fd) {
  166. read(fd, &byte, 1);
  167. fprintf(stderr, "got 0x%02x\n", byte);
  168. retval = byte;
  169. }
  170. else {
  171. fprintf(stderr, "%d bad fd ?\n", retval);
  172. retval = -3;
  173. }
  174. break;
  175. }
  176. return retval;
  177. }
  178. /* -------------------------------------------------------------------- */
  179. /* timeout is in milliseconds */
  180. int getline_to(int fd, char *where, int szm, int to_ms)
  181. {
  182. int curpos, byte, retval;
  183. #if DEBUG_LEVEL > 1
  184. fprintf(stderr, ">>> %s ( %d %p %d %d )\n", __func__,
  185. fd, where, szm, to_ms);
  186. #endif
  187. curpos = 0;
  188. retval = -7; /* magic number powa */
  189. where[0] = '\0'; /* erase all the bs */
  190. for(;;) {
  191. if (to_ms) {
  192. byte = getbyte_to (fd, to_ms);
  193. }
  194. else {
  195. byte = getbyte(fd);
  196. }
  197. if (byte < 0) {
  198. fprintf(stderr, "%s : something is wrong %d\n",
  199. __func__, byte);
  200. retval = byte;
  201. break;
  202. }
  203. if ('\n' == byte) { /* got an EOL ? */
  204. where[curpos] = '\0';
  205. retval = curpos;
  206. break;
  207. }
  208. if (curpos < szm) { /* ya de la place */
  209. where[curpos] = byte;
  210. curpos++;
  211. }
  212. else { /* oups overflow */
  213. retval = -6;
  214. break;
  215. }
  216. }
  217. #if DEBUG_LEVEL > 1
  218. fprintf(stderr, "%s -> '%s'\n", __func__, where);
  219. #endif
  220. return retval;
  221. }
  222. /* -------------------------------------------------------------------- */