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.7KB

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. #ifdef XONXOFF
  69. options.c_iflag |= IXON; // XON-XOFF Flow Control
  70. #endif
  71. // Output Modes
  72. options.c_oflag |= OPOST; // Post-process output
  73. // Control Modes
  74. options.c_cflag |= CS8; // 8 data bits
  75. options.c_cflag |= CREAD; // Enable Receiver
  76. options.c_cflag |= CLOCAL; // Ignore modem status lines
  77. // Special characters
  78. options.c_cc[VMIN] = 0; // Always return...
  79. options.c_cc[VTIME] = 0; // ..immediately from read()
  80. #ifdef XONXOFF
  81. options.c_cc[VSTOP] = XOFF;
  82. options.c_cc[VSTART] = XON;
  83. #endif
  84. tcsetattr(fd, TCSANOW, &options);
  85. tcflush(fd, TCIOFLUSH);
  86. return fd;
  87. }
  88. void serialClose(int fd) {
  89. tcflush(fd, TCIOFLUSH);
  90. close(fd);
  91. }
  92. int serialHasChar(int fd) {
  93. struct pollfd fds;
  94. fds.fd = fd;
  95. fds.events = (POLLIN | POLLPRI); // Data may be read
  96. if (poll(&fds, 1, 0) > 0) {
  97. return 1;
  98. } else {
  99. return 0;
  100. }
  101. }
  102. void serialWaitUntilSent(int fd) {
  103. while (tcdrain(fd) == -1) {
  104. fprintf(stderr, "Could not drain data: %s\n", strerror(errno));
  105. }
  106. }
  107. unsigned int serialWriteRaw(int fd, const char *d, int len) {
  108. unsigned int processed = 0;
  109. time_t start = time(NULL);
  110. while ((processed < len) && (difftime(time(NULL), start) < TIMEOUT)) {
  111. int t = write(fd, (d + processed), (len - processed));
  112. if (t == -1) {
  113. fprintf(stderr, "Error while writing: %s\n", strerror(errno));
  114. return processed;
  115. } else {
  116. processed += t;
  117. }
  118. usleep(1000);
  119. }
  120. return processed;
  121. }
  122. unsigned int serialReadRaw(int fd, char *d, int len) {
  123. unsigned int processed = 0;
  124. time_t start = time(NULL);
  125. while ((processed < len) && (difftime(time(NULL), start) < TIMEOUT)) {
  126. int t = read(fd, (d + processed), (len - processed));
  127. if (t == -1) {
  128. fprintf(stderr, "Error while reading: %s\n", strerror(errno));
  129. return processed;
  130. } else {
  131. processed += t;
  132. }
  133. usleep(1000);
  134. }
  135. return processed;
  136. }
  137. void serialWriteChar(int fd, char c) {
  138. while (serialWriteRaw(fd, &c, 1) != 1);
  139. }
  140. void serialReadChar(int fd, char *c) {
  141. while (serialReadRaw(fd, c, 1) != 1);
  142. #ifdef XONXOFF
  143. if (*c == XON) {
  144. if (tcflow(fd, TCOON) == -1) {
  145. fprintf(stderr, "Could not restart flow: %s\n", strerror(errno));
  146. }
  147. serialReadChar(fd, c);
  148. } else if (*c == XOFF) {
  149. if (tcflow(fd, TCOOFF) == -1) {
  150. fprintf(stderr, "Could not stop flow: %s\n", strerror(errno));
  151. }
  152. serialReadChar(fd, c);
  153. }
  154. #endif
  155. }
  156. void serialWriteString(int fd, const char *s) {
  157. while (*s)
  158. serialWriteChar(fd, *(s++));
  159. }
  160. char** getSerialPorts(void) {
  161. DIR *dir;
  162. struct dirent *ent;
  163. int size = 0;
  164. dir = opendir("/dev/");
  165. while ((ent = readdir(dir)) != NULL) {
  166. #ifdef SEARCH
  167. if (strstr(ent->d_name, SEARCH) != NULL)
  168. #endif
  169. size++;
  170. }
  171. closedir(dir);
  172. char **files = (char **)malloc((size + 1) * sizeof(char *));
  173. int i = 0;
  174. dir = opendir("/dev/");
  175. while (((ent = readdir(dir)) != NULL) && (i < size)) {
  176. #ifdef SEARCH
  177. if (strstr(ent->d_name, SEARCH) != NULL) {
  178. #endif
  179. int tmp = strlen(ent->d_name) + 6;
  180. files[i] = (char *)malloc(tmp * sizeof(char));
  181. strcpy(files[i], "/dev/");
  182. strcpy(files[i] + 5, ent->d_name);
  183. files[i][tmp - 1] = '\0';
  184. #ifdef TRY_TO_OPEN_PORTS
  185. int fdtmp = serialOpen(files[i], 9600);
  186. if (fdtmp != -1) {
  187. serialClose(fdtmp);
  188. #endif
  189. i++;
  190. #ifdef TRY_TO_OPEN_PORTS
  191. } else {
  192. free(files[i]);
  193. }
  194. #endif
  195. #ifdef SEARCH
  196. }
  197. #endif
  198. }
  199. closedir(dir);
  200. files[i] = NULL;
  201. return files;
  202. }