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