Mac OS X gamepad emulator for serial RC transmitters
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.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * ----------------------------------------------------------------------------
  3. * "THE BEER-WARE LICENSE" (Revision 42):
  4. * <xythobuz@xythobuz.de> wrote this file. As long as you retain this notice
  5. * you can do whatever you want with this stuff. If we meet some day, and you
  6. * think this stuff is worth it, you can buy me a beer in return. Thomas Buck
  7. * ----------------------------------------------------------------------------
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <fcntl.h>
  14. #include <termios.h>
  15. #include <dirent.h>
  16. #include <errno.h>
  17. #include <time.h>
  18. #include <poll.h>
  19. #include "serial.h"
  20. #ifndef XON
  21. #define XON 0x11
  22. #endif
  23. #ifndef XOFF
  24. #define XOFF 0x13
  25. #endif
  26. #ifndef TIMEOUT
  27. #define TIMEOUT 2
  28. #endif
  29. int serialOpen(const char *port, unsigned int baud) {
  30. struct termios options;
  31. int fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
  32. if (fd == -1) {
  33. fprintf(stderr, "Couldn't open port \"%s\": %s\n", port, strerror(errno));
  34. return -1;
  35. }
  36. tcgetattr(fd, &options);
  37. options.c_lflag = 0;
  38. options.c_oflag = 0;
  39. options.c_iflag = 0;
  40. // Set Baudrate
  41. switch (baud) {
  42. case 9600:
  43. cfsetispeed(&options, B9600);
  44. cfsetospeed(&options, B9600);
  45. break;
  46. case 19200:
  47. cfsetispeed(&options, B19200);
  48. cfsetospeed(&options, B19200);
  49. break;
  50. case 38400:
  51. cfsetispeed(&options, B38400);
  52. cfsetospeed(&options, B38400);
  53. break;
  54. case 76800:
  55. cfsetispeed(&options, B76800);
  56. cfsetospeed(&options, B76800);
  57. break;
  58. case 115200:
  59. cfsetispeed(&options, B115200);
  60. cfsetospeed(&options, B115200);
  61. break;
  62. default:
  63. fprintf(stderr, "Warning: Baudrate not supported!\n");
  64. serialClose(fd);
  65. return -1;
  66. }
  67. // Input Modes
  68. options.c_iflag |= IGNCR; // Ignore CR
  69. #ifdef XONXOFF
  70. options.c_iflag |= IXON; // XON-XOFF Flow Control
  71. #endif
  72. // Output Modes
  73. options.c_oflag |= OPOST; // Post-process output
  74. // Control Modes
  75. options.c_cflag |= CS8; // 8 data bits
  76. options.c_cflag |= CREAD; // Enable Receiver
  77. options.c_cflag |= CLOCAL; // Ignore modem status lines
  78. // Local Modes
  79. options.c_lflag |= IEXTEN; // Extended input character processing
  80. // Special characters
  81. options.c_cc[VMIN] = 0; // Always return...
  82. options.c_cc[VTIME] = 0; // ..immediately from read()
  83. #ifdef XONXOFF
  84. options.c_cc[VSTOP] = XOFF;
  85. options.c_cc[VSTART] = XON;
  86. #endif
  87. tcsetattr(fd, TCSANOW, &options);
  88. tcflush(fd, TCIOFLUSH);
  89. return fd;
  90. }
  91. void serialClose(int fd) {
  92. tcflush(fd, TCIOFLUSH);
  93. close(fd);
  94. }
  95. int serialHasChar(int fd) {
  96. struct pollfd fds;
  97. fds.fd = fd;
  98. fds.events = (POLLIN | POLLPRI); // Data may be read
  99. if (poll(&fds, 1, 0) > 0) {
  100. return 1;
  101. } else {
  102. return 0;
  103. }
  104. }
  105. void serialWaitUntilSent(int fd) {
  106. while (tcdrain(fd) == -1) {
  107. fprintf(stderr, "Could not drain data: %s\n", strerror(errno));
  108. }
  109. }
  110. unsigned int serialWriteRaw(int fd, const char *d, int len) {
  111. unsigned int processed = 0;
  112. time_t start = time(NULL);
  113. while ((processed < len) && (difftime(time(NULL), start) < TIMEOUT)) {
  114. int t = write(fd, (d + processed), (len - processed));
  115. if (t == -1) {
  116. fprintf(stderr, "Error while writing: %s\n", strerror(errno));
  117. return processed;
  118. } else {
  119. processed += t;
  120. }
  121. }
  122. return processed;
  123. }
  124. unsigned int serialReadRaw(int fd, char *d, int len) {
  125. unsigned int processed = 0;
  126. time_t start = time(NULL);
  127. while ((processed < len) && (difftime(time(NULL), start) < TIMEOUT)) {
  128. int t = read(fd, (d + processed), (len - processed));
  129. if (t == -1) {
  130. fprintf(stderr, "Error while reading: %s\n", strerror(errno));
  131. return processed;
  132. } else {
  133. processed += t;
  134. }
  135. }
  136. return processed;
  137. }
  138. void serialWriteChar(int fd, char c) {
  139. while (serialWriteRaw(fd, &c, 1) != 1);
  140. }
  141. void serialReadChar(int fd, char *c) {
  142. while (serialReadRaw(fd, c, 1) != 1);
  143. #ifdef XONXOFF
  144. if (*c == XON) {
  145. if (tcflow(fd, TCOON) == -1) {
  146. fprintf(stderr, "Could not restart flow: %s\n", strerror(errno));
  147. }
  148. serialReadChar(fd, c);
  149. } else if (*c == XOFF) {
  150. if (tcflow(fd, TCOOFF) == -1) {
  151. fprintf(stderr, "Could not stop flow: %s\n", strerror(errno));
  152. }
  153. serialReadChar(fd, c);
  154. }
  155. #endif
  156. }
  157. void serialWriteString(int fd, const char *s) {
  158. while (*s)
  159. serialWriteChar(fd, *(s++));
  160. }
  161. char** getSerialPorts(void) {
  162. DIR *dir;
  163. struct dirent *ent;
  164. int size = 0;
  165. dir = opendir("/dev/");
  166. while ((ent = readdir(dir)) != NULL) {
  167. #ifdef SEARCH
  168. if (strstr(ent->d_name, SEARCH) != NULL)
  169. #endif
  170. size++;
  171. }
  172. closedir(dir);
  173. char **files = (char **)malloc((size + 1) * sizeof(char *));
  174. int i = 0;
  175. dir = opendir("/dev/");
  176. while (((ent = readdir(dir)) != NULL) && (i < size)) {
  177. #ifdef SEARCH
  178. if (strstr(ent->d_name, SEARCH) != NULL) {
  179. #endif
  180. int tmp = strlen(ent->d_name) + 6;
  181. files[i] = (char *)malloc(tmp * sizeof(char));
  182. strcpy(files[i], "/dev/");
  183. strcpy(files[i] + 5, ent->d_name);
  184. files[i][tmp - 1] = '\0';
  185. #ifdef TRY_TO_OPEN_PORTS
  186. int fdtmp = serialOpen(files[i], 9600);
  187. if (fdtmp != -1) {
  188. serialClose(fdtmp);
  189. #endif
  190. i++;
  191. #ifdef TRY_TO_OPEN_PORTS
  192. } else {
  193. free(files[i]);
  194. }
  195. #endif
  196. #ifdef SEARCH
  197. }
  198. #endif
  199. }
  200. closedir(dir);
  201. files[i] = NULL;
  202. return files;
  203. }