serial.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /*
  2. * Serial back end (Unix-specific).
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <assert.h>
  7. #include <limits.h>
  8. #include <errno.h>
  9. #include <unistd.h>
  10. #include <fcntl.h>
  11. #include <termios.h>
  12. #include "putty.h"
  13. #include "tree234.h"
  14. #define SERIAL_MAX_BACKLOG 4096
  15. typedef struct Serial Serial;
  16. struct Serial {
  17. Seat *seat;
  18. LogContext *logctx;
  19. int fd;
  20. bool finished;
  21. size_t inbufsize;
  22. bufchain output_data;
  23. Backend backend;
  24. };
  25. /*
  26. * We store our serial backends in a tree sorted by fd, so that
  27. * when we get an uxsel notification we know which backend instance
  28. * is the owner of the serial port that caused it.
  29. */
  30. static int serial_compare_by_fd(void *av, void *bv)
  31. {
  32. Serial *a = (Serial *)av;
  33. Serial *b = (Serial *)bv;
  34. if (a->fd < b->fd)
  35. return -1;
  36. else if (a->fd > b->fd)
  37. return +1;
  38. return 0;
  39. }
  40. static int serial_find_by_fd(void *av, void *bv)
  41. {
  42. int a = *(int *)av;
  43. Serial *b = (Serial *)bv;
  44. if (a < b->fd)
  45. return -1;
  46. else if (a > b->fd)
  47. return +1;
  48. return 0;
  49. }
  50. static tree234 *serial_by_fd = NULL;
  51. static void serial_select_result(int fd, int event);
  52. static void serial_uxsel_setup(Serial *serial);
  53. static void serial_try_write(Serial *serial);
  54. static char *serial_configure(Serial *serial, Conf *conf)
  55. {
  56. struct termios options;
  57. int bflag, bval, speed, flow, parity;
  58. const char *str;
  59. if (serial->fd < 0)
  60. return dupstr("Unable to reconfigure already-closed "
  61. "serial connection");
  62. tcgetattr(serial->fd, &options);
  63. /*
  64. * Find the appropriate baud rate flag.
  65. */
  66. speed = conf_get_int(conf, CONF_serspeed);
  67. #define SETBAUD(x) (bflag = B ## x, bval = x)
  68. #define CHECKBAUD(x) do { if (speed >= x) SETBAUD(x); } while (0)
  69. SETBAUD(50);
  70. #ifdef B75
  71. CHECKBAUD(75);
  72. #endif
  73. #ifdef B110
  74. CHECKBAUD(110);
  75. #endif
  76. #ifdef B134
  77. CHECKBAUD(134);
  78. #endif
  79. #ifdef B150
  80. CHECKBAUD(150);
  81. #endif
  82. #ifdef B200
  83. CHECKBAUD(200);
  84. #endif
  85. #ifdef B300
  86. CHECKBAUD(300);
  87. #endif
  88. #ifdef B600
  89. CHECKBAUD(600);
  90. #endif
  91. #ifdef B1200
  92. CHECKBAUD(1200);
  93. #endif
  94. #ifdef B1800
  95. CHECKBAUD(1800);
  96. #endif
  97. #ifdef B2400
  98. CHECKBAUD(2400);
  99. #endif
  100. #ifdef B4800
  101. CHECKBAUD(4800);
  102. #endif
  103. #ifdef B9600
  104. CHECKBAUD(9600);
  105. #endif
  106. #ifdef B19200
  107. CHECKBAUD(19200);
  108. #endif
  109. #ifdef B38400
  110. CHECKBAUD(38400);
  111. #endif
  112. #ifdef B57600
  113. CHECKBAUD(57600);
  114. #endif
  115. #ifdef B76800
  116. CHECKBAUD(76800);
  117. #endif
  118. #ifdef B115200
  119. CHECKBAUD(115200);
  120. #endif
  121. #ifdef B153600
  122. CHECKBAUD(153600);
  123. #endif
  124. #ifdef B230400
  125. CHECKBAUD(230400);
  126. #endif
  127. #ifdef B307200
  128. CHECKBAUD(307200);
  129. #endif
  130. #ifdef B460800
  131. CHECKBAUD(460800);
  132. #endif
  133. #ifdef B500000
  134. CHECKBAUD(500000);
  135. #endif
  136. #ifdef B576000
  137. CHECKBAUD(576000);
  138. #endif
  139. #ifdef B921600
  140. CHECKBAUD(921600);
  141. #endif
  142. #ifdef B1000000
  143. CHECKBAUD(1000000);
  144. #endif
  145. #ifdef B1152000
  146. CHECKBAUD(1152000);
  147. #endif
  148. #ifdef B1500000
  149. CHECKBAUD(1500000);
  150. #endif
  151. #ifdef B2000000
  152. CHECKBAUD(2000000);
  153. #endif
  154. #ifdef B2500000
  155. CHECKBAUD(2500000);
  156. #endif
  157. #ifdef B3000000
  158. CHECKBAUD(3000000);
  159. #endif
  160. #ifdef B3500000
  161. CHECKBAUD(3500000);
  162. #endif
  163. #ifdef B4000000
  164. CHECKBAUD(4000000);
  165. #endif
  166. #undef CHECKBAUD
  167. #undef SETBAUD
  168. cfsetispeed(&options, bflag);
  169. cfsetospeed(&options, bflag);
  170. logeventf(serial->logctx, "Configuring baud rate %d", bval);
  171. options.c_cflag &= ~CSIZE;
  172. switch (conf_get_int(conf, CONF_serdatabits)) {
  173. case 5: options.c_cflag |= CS5; break;
  174. case 6: options.c_cflag |= CS6; break;
  175. case 7: options.c_cflag |= CS7; break;
  176. case 8: options.c_cflag |= CS8; break;
  177. default: return dupstr("Invalid number of data bits "
  178. "(need 5, 6, 7 or 8)");
  179. }
  180. logeventf(serial->logctx, "Configuring %d data bits",
  181. conf_get_int(conf, CONF_serdatabits));
  182. if (conf_get_int(conf, CONF_serstopbits) >= 4) {
  183. options.c_cflag |= CSTOPB;
  184. } else {
  185. options.c_cflag &= ~CSTOPB;
  186. }
  187. logeventf(serial->logctx, "Configuring %s",
  188. (options.c_cflag & CSTOPB ? "2 stop bits" : "1 stop bit"));
  189. options.c_iflag &= ~(IXON|IXOFF);
  190. #ifdef CRTSCTS
  191. options.c_cflag &= ~CRTSCTS;
  192. #endif
  193. #ifdef CNEW_RTSCTS
  194. options.c_cflag &= ~CNEW_RTSCTS;
  195. #endif
  196. flow = conf_get_int(conf, CONF_serflow);
  197. if (flow == SER_FLOW_XONXOFF) {
  198. options.c_iflag |= IXON | IXOFF;
  199. str = "XON/XOFF";
  200. } else if (flow == SER_FLOW_RTSCTS) {
  201. #ifdef CRTSCTS
  202. options.c_cflag |= CRTSCTS;
  203. #endif
  204. #ifdef CNEW_RTSCTS
  205. options.c_cflag |= CNEW_RTSCTS;
  206. #endif
  207. str = "RTS/CTS";
  208. } else
  209. str = "no";
  210. logeventf(serial->logctx, "Configuring %s flow control", str);
  211. /* Parity */
  212. parity = conf_get_int(conf, CONF_serparity);
  213. if (parity == SER_PAR_ODD) {
  214. options.c_cflag |= PARENB;
  215. options.c_cflag |= PARODD;
  216. str = "odd";
  217. } else if (parity == SER_PAR_EVEN) {
  218. options.c_cflag |= PARENB;
  219. options.c_cflag &= ~PARODD;
  220. str = "even";
  221. } else {
  222. options.c_cflag &= ~PARENB;
  223. str = "no";
  224. }
  225. logeventf(serial->logctx, "Configuring %s parity", str);
  226. options.c_cflag |= CLOCAL | CREAD;
  227. options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  228. options.c_iflag &= ~(ISTRIP | IGNCR | INLCR | ICRNL
  229. #ifdef IUCLC
  230. | IUCLC
  231. #endif
  232. );
  233. options.c_oflag &= ~(OPOST
  234. #ifdef ONLCR
  235. | ONLCR
  236. #endif
  237. #ifdef OCRNL
  238. | OCRNL
  239. #endif
  240. #ifdef ONOCR
  241. | ONOCR
  242. #endif
  243. #ifdef ONLRET
  244. | ONLRET
  245. #endif
  246. );
  247. options.c_cc[VMIN] = 1;
  248. options.c_cc[VTIME] = 0;
  249. if (tcsetattr(serial->fd, TCSANOW, &options) < 0)
  250. return dupprintf("Configuring serial port: %s", strerror(errno));
  251. return NULL;
  252. }
  253. /*
  254. * Called to set up the serial connection.
  255. *
  256. * Returns an error message, or NULL on success.
  257. *
  258. * Also places the canonical host name into `realhost'. It must be
  259. * freed by the caller.
  260. */
  261. static char *serial_init(const BackendVtable *vt, Seat *seat,
  262. Backend **backend_handle, LogContext *logctx,
  263. Conf *conf, const char *host, int port,
  264. char **realhost, bool nodelay, bool keepalive)
  265. {
  266. Serial *serial;
  267. char *err;
  268. char *line;
  269. /* No local authentication phase in this protocol */
  270. seat_set_trust_status(seat, false);
  271. serial = snew(Serial);
  272. memset(serial, 0, sizeof(Serial));
  273. serial->backend.vt = vt;
  274. *backend_handle = &serial->backend;
  275. serial->seat = seat;
  276. serial->logctx = logctx;
  277. serial->finished = false;
  278. serial->inbufsize = 0;
  279. bufchain_init(&serial->output_data);
  280. line = conf_get_str(conf, CONF_serline);
  281. logeventf(serial->logctx, "Opening serial device %s", line);
  282. serial->fd = open(line, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
  283. if (serial->fd < 0)
  284. return dupprintf("Opening serial port '%s': %s",
  285. line, strerror(errno));
  286. cloexec(serial->fd);
  287. err = serial_configure(serial, conf);
  288. if (err)
  289. return err;
  290. *realhost = dupstr(line);
  291. if (!serial_by_fd)
  292. serial_by_fd = newtree234(serial_compare_by_fd);
  293. add234(serial_by_fd, serial);
  294. serial_uxsel_setup(serial);
  295. /*
  296. * Specials are always available.
  297. */
  298. seat_update_specials_menu(serial->seat);
  299. return NULL;
  300. }
  301. static void serial_close(Serial *serial)
  302. {
  303. if (serial->fd >= 0) {
  304. uxsel_del(serial->fd);
  305. close(serial->fd);
  306. serial->fd = -1;
  307. }
  308. }
  309. static void serial_free(Backend *be)
  310. {
  311. Serial *serial = container_of(be, Serial, backend);
  312. serial_close(serial);
  313. bufchain_clear(&serial->output_data);
  314. sfree(serial);
  315. }
  316. static void serial_reconfig(Backend *be, Conf *conf)
  317. {
  318. Serial *serial = container_of(be, Serial, backend);
  319. char *err = serial_configure(serial, conf);
  320. if (err) {
  321. /*
  322. * FIXME: apart from freeing the dynamically allocated
  323. * message, what should we do if this returns an error?
  324. */
  325. sfree(err);
  326. }
  327. }
  328. static void serial_select_result(int fd, int event)
  329. {
  330. Serial *serial;
  331. char buf[4096];
  332. int ret;
  333. bool finished = false;
  334. serial = find234(serial_by_fd, &fd, serial_find_by_fd);
  335. if (!serial)
  336. return; /* spurious event; keep going */
  337. if (event == 1) {
  338. ret = read(serial->fd, buf, sizeof(buf));
  339. if (ret == 0) {
  340. /*
  341. * Shouldn't happen on a real serial port, but I'm open
  342. * to the idea that there might be two-way devices we
  343. * can treat _like_ serial ports which can return EOF.
  344. */
  345. finished = true;
  346. } else if (ret < 0) {
  347. #ifdef EAGAIN
  348. if (errno == EAGAIN)
  349. return; /* spurious */
  350. #endif
  351. #ifdef EWOULDBLOCK
  352. if (errno == EWOULDBLOCK)
  353. return; /* spurious */
  354. #endif
  355. perror("read serial port");
  356. exit(1);
  357. } else if (ret > 0) {
  358. serial->inbufsize = seat_stdout(serial->seat, buf, ret);
  359. serial_uxsel_setup(serial); /* might acquire backlog and freeze */
  360. }
  361. } else if (event == 2) {
  362. /*
  363. * Attempt to send data down the pty.
  364. */
  365. serial_try_write(serial);
  366. }
  367. if (finished) {
  368. serial_close(serial);
  369. serial->finished = true;
  370. seat_notify_remote_exit(serial->seat);
  371. }
  372. }
  373. static void serial_uxsel_setup(Serial *serial)
  374. {
  375. int rwx = 0;
  376. if (serial->inbufsize <= SERIAL_MAX_BACKLOG)
  377. rwx |= SELECT_R;
  378. if (bufchain_size(&serial->output_data))
  379. rwx |= SELECT_W; /* might also want to write to it */
  380. uxsel_set(serial->fd, rwx, serial_select_result);
  381. }
  382. static void serial_try_write(Serial *serial)
  383. {
  384. ssize_t ret;
  385. assert(serial->fd >= 0);
  386. while (bufchain_size(&serial->output_data) > 0) {
  387. ptrlen data = bufchain_prefix(&serial->output_data);
  388. ret = write(serial->fd, data.ptr, data.len);
  389. if (ret < 0 && (errno == EWOULDBLOCK)) {
  390. /*
  391. * We've sent all we can for the moment.
  392. */
  393. break;
  394. }
  395. if (ret < 0) {
  396. perror("write serial port");
  397. exit(1);
  398. }
  399. bufchain_consume(&serial->output_data, ret);
  400. }
  401. seat_sent(serial->seat, bufchain_size(&serial->output_data));
  402. serial_uxsel_setup(serial);
  403. }
  404. /*
  405. * Called to send data down the serial connection.
  406. */
  407. static void serial_send(Backend *be, const char *buf, size_t len)
  408. {
  409. Serial *serial = container_of(be, Serial, backend);
  410. if (serial->fd < 0)
  411. return;
  412. bufchain_add(&serial->output_data, buf, len);
  413. serial_try_write(serial);
  414. }
  415. /*
  416. * Called to query the current sendability status.
  417. */
  418. static size_t serial_sendbuffer(Backend *be)
  419. {
  420. Serial *serial = container_of(be, Serial, backend);
  421. return bufchain_size(&serial->output_data);
  422. }
  423. /*
  424. * Called to set the size of the window
  425. */
  426. static void serial_size(Backend *be, int width, int height)
  427. {
  428. /* Do nothing! */
  429. return;
  430. }
  431. /*
  432. * Send serial special codes.
  433. */
  434. static void serial_special(Backend *be, SessionSpecialCode code, int arg)
  435. {
  436. Serial *serial = container_of(be, Serial, backend);
  437. if (serial->fd >= 0 && code == SS_BRK) {
  438. tcsendbreak(serial->fd, 0);
  439. logevent(serial->logctx, "Sending serial break at user request");
  440. }
  441. return;
  442. }
  443. /*
  444. * Return a list of the special codes that make sense in this
  445. * protocol.
  446. */
  447. static const SessionSpecial *serial_get_specials(Backend *be)
  448. {
  449. static const struct SessionSpecial specials[] = {
  450. {"Break", SS_BRK},
  451. {NULL, SS_EXITMENU}
  452. };
  453. return specials;
  454. }
  455. static bool serial_connected(Backend *be)
  456. {
  457. return true; /* always connected */
  458. }
  459. static bool serial_sendok(Backend *be)
  460. {
  461. return true;
  462. }
  463. static void serial_unthrottle(Backend *be, size_t backlog)
  464. {
  465. Serial *serial = container_of(be, Serial, backend);
  466. serial->inbufsize = backlog;
  467. serial_uxsel_setup(serial);
  468. }
  469. static bool serial_ldisc(Backend *be, int option)
  470. {
  471. /*
  472. * Local editing and local echo are off by default.
  473. */
  474. return false;
  475. }
  476. static void serial_provide_ldisc(Backend *be, Ldisc *ldisc)
  477. {
  478. /* This is a stub. */
  479. }
  480. static int serial_exitcode(Backend *be)
  481. {
  482. Serial *serial = container_of(be, Serial, backend);
  483. if (serial->fd >= 0)
  484. return -1; /* still connected */
  485. else
  486. /* Exit codes are a meaningless concept with serial ports */
  487. return INT_MAX;
  488. }
  489. /*
  490. * cfg_info for Serial does nothing at all.
  491. */
  492. static int serial_cfg_info(Backend *be)
  493. {
  494. return 0;
  495. }
  496. const BackendVtable serial_backend = {
  497. .init = serial_init,
  498. .free = serial_free,
  499. .reconfig = serial_reconfig,
  500. .send = serial_send,
  501. .sendbuffer = serial_sendbuffer,
  502. .size = serial_size,
  503. .special = serial_special,
  504. .get_specials = serial_get_specials,
  505. .connected = serial_connected,
  506. .exitcode = serial_exitcode,
  507. .sendok = serial_sendok,
  508. .ldisc_option_state = serial_ldisc,
  509. .provide_ldisc = serial_provide_ldisc,
  510. .unthrottle = serial_unthrottle,
  511. .cfg_info = serial_cfg_info,
  512. .id = "serial",
  513. .displayname_tc = "Serial",
  514. .displayname_lc = "serial",
  515. .protocol = PROT_SERIAL,
  516. .serial_parity_mask = ((1 << SER_PAR_NONE) |
  517. (1 << SER_PAR_ODD) |
  518. (1 << SER_PAR_EVEN)),
  519. .serial_flow_mask = ((1 << SER_FLOW_NONE) |
  520. (1 << SER_FLOW_XONXOFF) |
  521. (1 << SER_FLOW_RTSCTS)),
  522. };