serialPort.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #include "serialPort.h"
  2. # if ORT_SERIAL_PORT_ENABLED == 1
  3. // includes
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <termios.h>
  10. #include <unistd.h>
  11. #include "runtime.h"
  12. // defines
  13. // TODO: setup ifndef's and define BAUD_RATE
  14. #define FD_DEFAULT -1
  15. // global vars
  16. int serialFd = FD_DEFAULT;
  17. // local functions
  18. int set_interface_attribs(int fd, int speed)
  19. {
  20. struct termios tty;
  21. if (tcgetattr(fd, &tty) < 0) {
  22. printf("Error from tcgetattr: %s\n", strerror(errno));
  23. return -1;
  24. }
  25. cfsetospeed(&tty, (speed_t)speed);
  26. cfsetispeed(&tty, (speed_t)speed);
  27. tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
  28. tty.c_cflag &= ~CSIZE;
  29. tty.c_cflag |= CS8; /* 8-bit characters */
  30. tty.c_cflag &= ~PARENB; /* no parity bit */
  31. tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
  32. tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
  33. /* setup for non-canonical mode */
  34. tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
  35. tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  36. tty.c_oflag &= ~OPOST;
  37. /* fetch bytes as they become available */
  38. /* set at least 1 byte and enable inter-byte timeout - will lead to a blocking call until at least 1 byte is read */
  39. // tty.c_cc[VMIN] = 1;
  40. // tty.c_cc[VTIME] = 1;
  41. /* set polling mode - reading all available bytes */
  42. tty.c_cc[VMIN] = 0;
  43. tty.c_cc[VTIME] = 0;
  44. if (tcsetattr(fd, TCSANOW, &tty) != 0) {
  45. printf("Error from tcsetattr: %s\n", strerror(errno));
  46. return -1;
  47. }
  48. return 0;
  49. }
  50. void set_mincount(int fd, int mcount)
  51. {
  52. struct termios tty;
  53. if (tcgetattr(fd, &tty) < 0) {
  54. printf("Error tcgetattr: %s\n", strerror(errno));
  55. return;
  56. }
  57. // 0 - non-blocking read, 1 - blocking read
  58. tty.c_cc[VMIN] = mcount ? 1 : 0;
  59. tty.c_cc[VTIME] = 5; /* half second timer */
  60. if (tcsetattr(fd, TCSANOW, &tty) < 0)
  61. printf("Error tcsetattr: %s\n", strerror(errno));
  62. }
  63. void set_blocking (int fd, int should_block)
  64. {
  65. struct termios tty;
  66. memset (&tty, 0, sizeof tty);
  67. if (tcgetattr (fd, &tty) != 0)
  68. {
  69. printf("ERROR: %d from tggetattr", errno);
  70. return;
  71. }
  72. tty.c_cc[VMIN] = should_block ? 1 : 0;
  73. tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
  74. if (tcsetattr (fd, TCSANOW, &tty) != 0)
  75. printf("ERROR: %d setting term attributes", errno);
  76. }
  77. #endif // ORT_SERIAL_PORT_ENABLED
  78. int initSerialPort(char* portname, int baudrate){
  79. # if ORT_SERIAL_PORT_ENABLED == 1
  80. speed_t baud;
  81. printf("Attempting to initialize serial port '%s' with baudrate '%d'...\n", portname, baudrate);
  82. serialFd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
  83. if (serialFd < 0) {
  84. printf("Error opening %s: %s\n", portname, strerror(errno));
  85. return -1;
  86. }
  87. // convert baudrate int
  88. switch (baudrate) {
  89. case 115200:
  90. baud = B115200;
  91. break;
  92. case 9600:
  93. default:
  94. baud = B9600;
  95. break;
  96. }
  97. /*baudrate 115200, 8 bits, no parity, 1 stop bit */
  98. set_interface_attribs(serialFd, baud);
  99. // set_blocking (serialFd, 0); // set no blocking - read function returns however many characters are available without waiting
  100. printf("... success!\n");
  101. #endif // ORT_SERIAL_PORT_ENABLED
  102. return 0;
  103. }
  104. void destroySerialPort() {
  105. # if ORT_SERIAL_PORT_ENABLED == 1
  106. close(serialFd);
  107. #endif // ORT_SERIAL_PORT_ENABLED
  108. }
  109. int writeSerialPort(char* msg) {
  110. int wlen;
  111. int expLen = strlen(msg);
  112. if (serialFd != FD_DEFAULT) {
  113. // printf(" writeSerialPort writing message of length %d\n", expLen);
  114. wlen = write(serialFd, msg, expLen);
  115. if (wlen != expLen) {
  116. printf("Error from write: %d, %d\n", wlen, errno);
  117. return -1;
  118. }
  119. // printf(" pause...");
  120. // onion.io: tcdrain occasionally causes seg fault...
  121. // tcdrain(serialFd); /* delay for output */
  122. // onion.io: manual wait based on length of message (9600 bits per second)
  123. usleep(expLen*8*104); // 9600 bits per second = 104.16 us/bit, 8 bits per character
  124. // printf(" complete\n");
  125. }
  126. else {
  127. printf("ERROR: no file descriptor for serial port\n");
  128. return -1;
  129. }
  130. return 0;
  131. }
  132. int writeCharSerialPort(unsigned char c) {
  133. int wlen;
  134. int expLen = 1;
  135. if (serialFd != FD_DEFAULT) {
  136. wlen = write(serialFd, &c, expLen);
  137. if (wlen != expLen) {
  138. printf("Error from write: %d, %d\n", wlen, errno);
  139. return -1;
  140. }
  141. // onion.io: manual wait based on length of message (9600 bits per second)
  142. usleep(expLen*8*104); // 9600 bits per second = 104.16 us/bit, 8 bits per character
  143. }
  144. else {
  145. printf("ERROR: no file descriptor for serial port\n");
  146. return -1;
  147. }
  148. return 0;
  149. }
  150. int readSerialPort(char *msg) {
  151. unsigned char buf[MAX_CHAR_LEN];
  152. int rdlen;
  153. rdlen = read(serialFd, buf, sizeof(buf) - 1);
  154. if (rdlen > 0) {
  155. buf[rdlen] = 0;
  156. printf("Read %d: \"%s\"\n", rdlen, buf);
  157. strncpy(msg, buf, rdlen);
  158. } else if (rdlen < 0) {
  159. printf("Error from read: %d: %s\n", rdlen, strerror(errno));
  160. }
  161. return rdlen;
  162. }