serial.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * This file is part of the flashrom project.
  3. *
  4. * Copyright (C) 2009 Urja Rannikko <urjaman@gmail.com>
  5. * Copyright (C) 2009,2010 Carl-Daniel Hailfinger
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include <fcntl.h>
  27. #include <sys/stat.h>
  28. #include <errno.h>
  29. #include <inttypes.h>
  30. #ifdef _WIN32
  31. #include <conio.h>
  32. #else
  33. #include <termios.h>
  34. #endif
  35. #include "flash.h"
  36. #include "programmer.h"
  37. fdtype sp_fd;
  38. void __attribute__((noreturn)) sp_die(char *msg)
  39. {
  40. perror(msg);
  41. exit(1);
  42. }
  43. #ifndef _WIN32
  44. struct baudentry {
  45. int flag;
  46. unsigned int baud;
  47. };
  48. /* I'd like if the C preprocessor could have directives in macros */
  49. #define BAUDENTRY(baud) { B##baud, baud },
  50. static const struct baudentry sp_baudtable[] = {
  51. BAUDENTRY(9600)
  52. BAUDENTRY(19200)
  53. BAUDENTRY(38400)
  54. BAUDENTRY(57600)
  55. BAUDENTRY(115200)
  56. #ifdef B230400
  57. BAUDENTRY(230400)
  58. #endif
  59. #ifdef B460800
  60. BAUDENTRY(460800)
  61. #endif
  62. #ifdef B500000
  63. BAUDENTRY(500000)
  64. #endif
  65. #ifdef B576000
  66. BAUDENTRY(576000)
  67. #endif
  68. #ifdef B921600
  69. BAUDENTRY(921600)
  70. #endif
  71. #ifdef B1000000
  72. BAUDENTRY(1000000)
  73. #endif
  74. #ifdef B1152000
  75. BAUDENTRY(1152000)
  76. #endif
  77. #ifdef B1500000
  78. BAUDENTRY(1500000)
  79. #endif
  80. #ifdef B2000000
  81. BAUDENTRY(2000000)
  82. #endif
  83. #ifdef B2500000
  84. BAUDENTRY(2500000)
  85. #endif
  86. #ifdef B3000000
  87. BAUDENTRY(3000000)
  88. #endif
  89. #ifdef B3500000
  90. BAUDENTRY(3500000)
  91. #endif
  92. #ifdef B4000000
  93. BAUDENTRY(4000000)
  94. #endif
  95. {0, 0} /* Terminator */
  96. };
  97. #endif
  98. fdtype sp_openserport(char *dev, unsigned int baud)
  99. {
  100. #ifdef _WIN32
  101. HANDLE fd;
  102. char *dev2 = dev;
  103. if ((strlen(dev) > 3) && (tolower((unsigned char)dev[0]) == 'c') &&
  104. (tolower((unsigned char)dev[1]) == 'o') &&
  105. (tolower((unsigned char)dev[2]) == 'm')) {
  106. dev2 = malloc(strlen(dev) + 5);
  107. if (!dev2)
  108. sp_die("Error: Out of memory");
  109. strcpy(dev2, "\\\\.\\");
  110. strcpy(dev2 + 4, dev);
  111. }
  112. fd = CreateFile(dev2, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  113. OPEN_EXISTING, 0, NULL);
  114. if (dev2 != dev)
  115. free(dev2);
  116. if (fd == INVALID_HANDLE_VALUE) {
  117. sp_die("Error: cannot open serial port");
  118. }
  119. DCB dcb;
  120. if (!GetCommState(fd, &dcb)) {
  121. sp_die("Error: Could not fetch serial port configuration");
  122. }
  123. switch (baud) {
  124. case 9600: dcb.BaudRate = CBR_9600; break;
  125. case 19200: dcb.BaudRate = CBR_19200; break;
  126. case 38400: dcb.BaudRate = CBR_38400; break;
  127. case 57600: dcb.BaudRate = CBR_57600; break;
  128. case 115200: dcb.BaudRate = CBR_115200; break;
  129. default: sp_die("Error: Could not set baud rate");
  130. }
  131. dcb.ByteSize = 8;
  132. dcb.Parity = NOPARITY;
  133. dcb.StopBits = ONESTOPBIT;
  134. if (!SetCommState(fd, &dcb)) {
  135. sp_die("Error: Could not change serial port configuration");
  136. }
  137. return fd;
  138. #else
  139. struct termios options;
  140. int fd, i;
  141. fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
  142. if (fd < 0)
  143. sp_die("Error: cannot open serial port");
  144. fcntl(fd, F_SETFL, 0);
  145. tcgetattr(fd, &options);
  146. for (i = 0;; i++) {
  147. if (sp_baudtable[i].baud == 0) {
  148. close(fd);
  149. msg_perr("Error: cannot configure for baudrate %d\n",
  150. baud);
  151. exit(1);
  152. }
  153. if (sp_baudtable[i].baud == baud) {
  154. cfsetispeed(&options, sp_baudtable[i].flag);
  155. cfsetospeed(&options, sp_baudtable[i].flag);
  156. break;
  157. }
  158. }
  159. options.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
  160. options.c_cflag |= (CS8 | CLOCAL | CREAD);
  161. options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  162. options.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | IGNCR | INLCR);
  163. options.c_oflag &= ~OPOST;
  164. tcsetattr(fd, TCSANOW, &options);
  165. return fd;
  166. #endif
  167. }
  168. void sp_flush_incoming(void)
  169. {
  170. #ifdef _WIN32
  171. PurgeComm(sp_fd, PURGE_RXCLEAR);
  172. #else
  173. tcflush(sp_fd, TCIFLUSH);
  174. #endif
  175. return;
  176. }
  177. int serialport_shutdown(void *data)
  178. {
  179. #ifdef _WIN32
  180. CloseHandle(sp_fd);
  181. #else
  182. close(sp_fd);
  183. #endif
  184. return 0;
  185. }
  186. int serialport_write(unsigned char *buf, unsigned int writecnt)
  187. {
  188. #ifdef _WIN32
  189. DWORD tmp = 0;
  190. #else
  191. ssize_t tmp = 0;
  192. #endif
  193. while (writecnt > 0) {
  194. #ifdef _WIN32
  195. WriteFile(sp_fd, buf, writecnt, &tmp, NULL);
  196. #else
  197. tmp = write(sp_fd, buf, writecnt);
  198. #endif
  199. if (tmp == -1) {
  200. msg_perr("Serial port write error!\n");
  201. return 1;
  202. }
  203. if (!tmp)
  204. msg_pdbg("Empty write\n");
  205. writecnt -= tmp;
  206. buf += tmp;
  207. }
  208. return 0;
  209. }
  210. int serialport_read(unsigned char *buf, unsigned int readcnt)
  211. {
  212. #ifdef _WIN32
  213. DWORD tmp = 0;
  214. #else
  215. ssize_t tmp = 0;
  216. #endif
  217. while (readcnt > 0) {
  218. #ifdef _WIN32
  219. ReadFile(sp_fd, buf, readcnt, &tmp, NULL);
  220. #else
  221. tmp = read(sp_fd, buf, readcnt);
  222. #endif
  223. if (tmp == -1) {
  224. msg_perr("Serial port read error!\n");
  225. return 1;
  226. }
  227. if (!tmp)
  228. msg_pdbg("Empty read\n");
  229. readcnt -= tmp;
  230. buf += tmp;
  231. }
  232. return 0;
  233. }