4 * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
9 static char rcsid[] = "$Id: tty.c,v 1.27 2010/07/27 14:49:35 james Exp $";
13 * Revision 1.27 2010/07/27 14:49:35 james
14 * add support for byte logging
16 * Revision 1.26 2008/03/10 11:49:33 james
17 * *** empty log message ***
19 * Revision 1.25 2008/03/07 13:16:02 james
20 * *** empty log message ***
22 * Revision 1.24 2008/03/07 12:37:04 james
23 * *** empty log message ***
25 * Revision 1.23 2008/03/06 16:49:39 james
26 * *** empty log message ***
28 * Revision 1.22 2008/03/06 16:49:05 james
29 * *** empty log message ***
31 * Revision 1.21 2008/03/03 06:04:42 james
32 * *** empty log message ***
34 * Revision 1.20 2008/03/02 10:37:56 james
35 * *** empty log message ***
37 * Revision 1.19 2008/02/28 16:57:52 james
38 * *** empty log message ***
40 * Revision 1.18 2008/02/28 16:37:16 james
41 * *** empty log message ***
43 * Revision 1.17 2008/02/28 15:37:06 james
44 * *** empty log message ***
46 * Revision 1.16 2008/02/28 12:12:25 james
47 * *** empty log message ***
49 * Revision 1.15 2008/02/28 00:10:44 james
50 * *** empty log message ***
52 * Revision 1.14 2008/02/23 13:05:58 staffcvs
53 * *** empty log message ***
55 * Revision 1.13 2008/02/23 11:48:37 james
56 * *** empty log message ***
58 * Revision 1.12 2008/02/22 23:39:27 james
59 * *** empty log message ***
61 * Revision 1.11 2008/02/20 18:31:53 james
62 * *** empty log message ***
64 * Revision 1.10 2008/02/15 23:52:12 james
65 * *** empty log message ***
67 * Revision 1.9 2008/02/15 03:32:07 james
68 * *** empty log message ***
70 * Revision 1.8 2008/02/14 10:36:18 james
71 * *** empty log message ***
73 * Revision 1.7 2008/02/14 10:34:30 james
74 * *** empty log message ***
76 * Revision 1.6 2008/02/13 16:59:34 james
77 * *** empty log message ***
79 * Revision 1.5 2008/02/13 16:57:29 james
80 * *** empty log message ***
82 * Revision 1.4 2008/02/12 22:36:46 james
83 * *** empty log message ***
85 * Revision 1.3 2008/02/09 15:47:28 james
86 * *** empty log message ***
94 speed_t_to_baud (speed_t s)
179 baud_to_speed_t (int baud)
263 tty_pre_select (TTY * t, fd_set * rfds, fd_set * wfds)
266 struct timeval now, dif;
270 gettimeofday (&now, NULL);
271 timersub (&now, &t->hangup_clock, &dif);
274 ioctl (t->rfd, TIOCMBIS, &line);
280 FD_SET (t->rfd, rfds);
284 tty_get_status (TTY * t, TTY_Status * s)
288 ioctl (t->rfd, TIOCMGET, &s->lines);
290 if (tcgetattr (t->rfd, &s->termios))
293 s->baud = speed_t_to_baud (cfgetispeed (&s->termios));
294 s->blocked = t->blocked;
300 tty_get_baud (TTY * t)
302 struct termios tios = { 0 };
304 if (tcgetattr (t->rfd, &tios))
307 return speed_t_to_baud (cfgetispeed (&tios));
312 tty_set_baud (TTY * t, int rate)
314 struct termios tios = { 0 };
316 speed_t s = baud_to_speed_t (rate);
318 if (s == (speed_t) - 1)
321 if (tcgetattr (t->rfd, &tios))
324 cfsetispeed (&tios, s);
325 cfsetospeed (&tios, s);
327 tcsetattr (t->rfd, TCSANOW, &tios);
331 tty_send_break (TTY * t)
333 tcsendbreak (t->wfd, 0);
337 tty_set_flow (TTY * t, int flow)
339 struct termios tios = { 0 };
341 if (tcgetattr (t->rfd, &tios))
345 tios.c_cflag |= CRTSCTS;
347 tios.c_cflag &= ~CRTSCTS;
349 tcsetattr (t->rfd, TCSANOW, &tios);
359 ioctl (t->rfd, TIOCMBIC, &line);
362 gettimeofday (&t->hangup_clock, NULL);
367 tty_length (TTY * t, int l)
369 t->displayed_length = l;
373 tty_winch (TTY * t, CRT_Pos size)
375 struct winsize sz = { 0 };
380 ioctl (t->wfd, TIOCSWINSZ, &sz);
390 int bit_edge_frequency[8];
395 #define bit(p,b,z,o) \
415 tty_bit_analyse (Context * c, int err, int ch)
419 TTY_Parser *p = c->tp;
424 for (d = 1; d < 0x100; d <<= 1) {
425 bit (p, ch & d, zc, oc);
433 gettimeofday (&p->lasterr, NULL);
438 "<tty_bit_analyse: 0%d%d%d%d%d%d%d%d1 [%d,%d,%d,%d,%d,%d,%d,%d,%d,%d]>",
439 ch & 0x01 ? 1 : 0, ch & 0x02 ? 1 : 0, ch & 0x04 ? 1 : 0,
440 ch & 0x08 ? 1 : 0, ch & 0x10 ? 1 : 0, ch & 0x20 ? 1 : 0,
441 ch & 0x40 ? 1 : 0, ch & 0x80 ? 1 : 0, p->bitfreq[0],
442 p->bitfreq[1], p->bitfreq[2], p->bitfreq[3], p->bitfreq[4],
443 p->bitfreq[5], p->bitfreq[6], p->bitfreq[7], p->bitfreq[8],
450 tty_parse_reset (Context * c)
452 TTY_Parser *p = c->tp;
453 memset (p->bitfreq, 0, sizeof (p->bitfreq));
459 tty_analyse (Context * c)
461 TTY_Parser *p = c->tp;
462 struct timeval now, dif;
470 gettimeofday (&now, NULL);
472 timersub (&now, &p->lasterr, &dif);
474 if (dif.tv_sec > 10) {
482 for (i = 0; i < TTY_BITFREQ_LEN; ++i) {
483 if (p->bitfreq[i] > max) {
490 i = tty_get_baud (c->t);
495 /* Closest bit edge is one bit, so the baud rate is too low */
496 p->guessed_baud = -1;
500 p->guessed_baud = i / j;
506 if (p->guessed_baud == -1) {
507 log_f (c->l, "<tty_analyse: %6d errors, current rate %db is too low>",
510 log_f (c->l, "<tty_analyse: %6d errors, current rate %db, suggest %db>",
511 p->biterrs, i, p->guessed_baud);
517 tty_parser_new (void)
521 p = (TTY_Parser *) xmalloc (sizeof (TTY_Parser));
523 memset (p, 0, sizeof (TTY_Parser));
529 tty_parse (Context * c, uint8_t * buf, int len)
542 tty_bit_analyse (c, 0, *buf);
543 err += utf8_parse (c, *buf);
549 log_f (c->l, "%s:%d DLE parsing error: \\377 \\%03o", __FILE__,
552 } else if (p->in_errmark) {
555 log_f (c->l, "<tty reports error: \\377 \\000 \\%03o>",
556 __FILE__, __LINE__, *buf);
558 tty_bit_analyse (c, 1, *buf);
562 err += utf8_parse (c, *buf);
564 err += utf8_parse (c, SYM_CHAR_RESET);
566 } else if (*buf == DLE) {
570 tty_bit_analyse (c, 0, *buf);
574 err += utf8_parse (c, *buf);