Mac OS X gamepad emulator for serial RC transmitters
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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