X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=sympathy.git;a=blobdiff_plain;f=src%2Ftty.c;h=df7c13fbe3b0ba7dfe2c5db03ca03100de6b1658;hp=72b31a12f161cfe615255166559466a585aaeba2;hb=3e72a1f6fc28777c26e4fb109867bd2a3c7b89b0;hpb=f6fc17f7f1c349dd4e8c88d95c21e8196090a599 diff --git a/src/tty.c b/src/tty.c index 72b31a1..df7c13f 100644 --- a/src/tty.c +++ b/src/tty.c @@ -10,6 +10,48 @@ static char rcsid[] = "$Id$"; /* * $Log$ + * Revision 1.19 2008/02/28 16:57:52 james + * *** empty log message *** + * + * Revision 1.18 2008/02/28 16:37:16 james + * *** empty log message *** + * + * Revision 1.17 2008/02/28 15:37:06 james + * *** empty log message *** + * + * Revision 1.16 2008/02/28 12:12:25 james + * *** empty log message *** + * + * Revision 1.15 2008/02/28 00:10:44 james + * *** empty log message *** + * + * Revision 1.14 2008/02/23 13:05:58 staffcvs + * *** empty log message *** + * + * Revision 1.13 2008/02/23 11:48:37 james + * *** empty log message *** + * + * Revision 1.12 2008/02/22 23:39:27 james + * *** empty log message *** + * + * Revision 1.11 2008/02/20 18:31:53 james + * *** empty log message *** + * + * Revision 1.10 2008/02/15 23:52:12 james + * *** empty log message *** + * + * Revision 1.9 2008/02/15 03:32:07 james + * *** empty log message *** + * + * Revision 1.8 2008/02/14 10:36:18 james + * *** empty log message *** + * + * Revision 1.7 2008/02/14 10:34:30 james + * *** empty log message *** + * + * Revision 1.6 2008/02/13 16:59:34 james + * *** empty log message *** + * * Revision 1.5 2008/02/13 16:57:29 james * *** empty log message *** * @@ -22,25 +64,520 @@ static char rcsid[] = "$Id$"; */ +#include "project.h" +static int +speed_t_to_baud (speed_t s) +{ + switch (s) + { +#ifdef B0 + case B0: + return 0; +#endif +#ifdef B50 + case B50: + return 50; +#endif +#ifdef B75 + case B75: + return 75; +#endif +#ifdef B110 + case B110: + return 110; +#endif +#ifdef B134 + case B134: + return 134; +#endif +#ifdef B150 + case B150: + return 150; +#endif +#ifdef B200 + case B200: + return 200; +#endif +#ifdef B300 + case B300: + return 300; +#endif +#ifdef B600 + case B600: + return 600; +#endif +#ifdef B1200 + case B1200: + return 1200; +#endif +#ifdef B1800 + case B1800: + return 1800; +#endif +#ifdef B2400 + case B2400: + return 2400; +#endif +#ifdef B4800 + case B4800: + return 4800; +#endif +#ifdef B9600 + case B9600: + return 9600; +#endif +#ifdef B19200 + case B19200: + return 19200; +#endif +#ifdef B38400 + case B38400: + return 38400; +#endif +#ifdef B57600 + case B57600: + return 57600; +#endif +#ifdef B115200 + case B115200: + return 115200; +#endif +#ifdef B230400 + case B230400: + return 230400; +#endif + } + + return -1; +} + +static speed_t +baud_to_speed_t (int baud) +{ + switch (baud) + { +#ifdef B0 + case 0: + return B0; +#endif +#ifdef B50 + case 50: + return B50; +#endif +#ifdef B75 + case 75: + return B75; +#endif +#ifdef B110 + case 110: + return B110; +#endif +#ifdef B134 + case 134: + return B134; +#endif +#ifdef B150 + case 150: + return B150; +#endif +#ifdef B200 + case 200: + return B200; +#endif +#ifdef B300 + case 300: + return B300; +#endif +#ifdef B600 + case 600: + return B600; +#endif +#ifdef B1200 + case 1200: + return B1200; +#endif +#ifdef B1800 + case 1800: + return B1800; +#endif +#ifdef B2400 + case 2400: + return B2400; +#endif +#ifdef B4800 + case 4800: + return B4800; +#endif +#ifdef B9600 + case 9600: + return B9600; +#endif +#ifdef B19200 + case 19200: + return B19200; +#endif +#ifdef B38400 + case 38400: + return B38400; +#endif +#ifdef B57600 + case 57600: + return B57600; +#endif +#ifdef B115200 + case 115200: + return B115200; +#endif +#ifdef B230400 + case 230400: + return B230400; +#endif + } + return -1; +} void tty_pre_select (TTY * t, fd_set * rfds, fd_set * wfds) { - FD_SET (t->rfd, &rfds); + int line; + struct timeval now, dif; + + if (t->hanging_up) + { + + gettimeofday (&now, NULL); + timersub (&now, &t->hangup_clock, &dif); + if (dif.tv_sec) + { + line = TIOCM_DTR; + ioctl (t->rfd, TIOCMBIS, &line); + t->hanging_up = 0; + } + } + + + FD_SET (t->rfd, rfds); } -#if 0 int -tty_post_select (Context * c, fd_set * rfds, fd_set * wfds) +tty_get_status (TTY * t, TTY_Status * s) { - if (FD_ISSET (c->t->rfd, rfds)) - { - if (vt102_dispatch (&c)) - return -1; - } + s->lines = 0; + ioctl (t->rfd, TIOCMGET, &s->lines); + + if (tcgetattr (t->rfd, &s->termios)) + return -1; + + s->baud = speed_t_to_baud (cfgetispeed (&s->termios)); + s->blocked = t->blocked; + return 0; } +int +tty_get_baud (TTY * t) +{ + struct termios tios = { 0 }; + + if (tcgetattr (t->rfd, &tios)) + return; + + return speed_t_to_baud (cfgetispeed (&tios)); +} + + +void +tty_set_baud (TTY * t, int rate) +{ + struct termios tios = { 0 }; + + speed_t s = baud_to_speed_t (rate); + + if (s == (speed_t) - 1) + return; + + if (tcgetattr (t->rfd, &tios)) + return; + + cfsetispeed (&tios, s); + cfsetospeed (&tios, s); + + tcsetattr (t->rfd, TCSANOW, &tios); +} + +void +tty_send_break (TTY * t) +{ + tcsendbreak (t->wfd, 0); +} + +void +tty_set_flow (TTY * t, int flow) +{ + struct termios tios = { 0 }; + + if (tcgetattr (t->rfd, &tios)) + return; + + if (flow) + tios.c_cflag |= CRTSCTS; + else + tios.c_cflag &= ~CRTSCTS; + + tcsetattr (t->rfd, TCSANOW, &tios); + +} + +void +tty_hangup (TTY * t) +{ + int line; + + line = TIOCM_DTR; + ioctl (t->rfd, TIOCMBIC, &line); + + t->hanging_up = 1; + gettimeofday (&t->hangup_clock, NULL); + +} + +void tty_length(TTY *t,int l) +{ +t->displayed_length=l; +} + +void +tty_winch (TTY * t, CRT_Pos size) +{ + struct winsize sz = { 0 }; + + sz.ws_col = size.x; + sz.ws_row = size.y; + + ioctl (t->wfd, TIOCSWINSZ, &sz); +} + + + +#if 0 +typedef struct +{ + int in_dle; + int in_errmark; + + int bit_edge_frequency[8]; + int errs; +} #endif + +#define DLE 0377 + +#define bit(p,b,z,o) \ + do { \ + if ((b && z)) { \ + p->bitfreq[z]++; \ + z = 0; \ + } \ + \ + if ((!b && o)) \ + { \ + p->bitfreq[z]++; \ + o = 0; \ + } \ + \ + if (b) \ + o++; \ + else \ + z++; \ + } \ + while (0) + +static void +tty_bit_analyse (Context * c, int err, int ch) +{ + int d; + int zc = 0, oc = 0; + TTY_Parser *p = c->tp; + + + bit (p, 0, zc, oc); + + for (d = 1; d < 0x100; d <<= 1) + { + bit (p, ch & d, zc, oc); + } + bit (p, 1, zc, oc); + + + + if (err) + { + p->biterrs++; + gettimeofday (&p->lasterr, NULL); + } + + if (p->biterrs) + { + log_f (c->l, + "", + ch & 0x01 ? 1 : 0, ch & 0x02 ? 1 : 0, ch & 0x04 ? 1 : 0, + ch & 0x08 ? 1 : 0, ch & 0x10 ? 1 : 0, ch & 0x20 ? 1 : 0, + ch & 0x40 ? 1 : 0, ch & 0x80 ? 1 : 0, p->bitfreq[0], + p->bitfreq[1], p->bitfreq[2], p->bitfreq[3], p->bitfreq[4], + p->bitfreq[5], p->bitfreq[6], p->bitfreq[7], p->bitfreq[8], + p->bitfreq[9]); + } + +} + +void +tty_parse_reset (Context * c) +{ + TTY_Parser *p = c->tp; + memset (p->bitfreq, 0, sizeof (p->bitfreq)); + p->biterrs = 0; + p->guessed_baud = 0; +} + +void +tty_analyse (Context * c) +{ + TTY_Parser *p = c->tp; + struct timeval now, dif; + int i, j, max; + + if (!p->biterrs) + { + p->guessed_baud = 0; + return; + } + + gettimeofday (&now, NULL); + + timersub (&now, &p->lasterr, &dif); + + if (dif.tv_sec > 10) + { + tty_parse_reset (c); + return; + } + + + max = -1; + j = 0; + for (i = 0; i < TTY_BITFREQ_LEN; ++i) + { + if (p->bitfreq[i] > max) + { + max = p->bitfreq[i]; + j = i; + } + } + + if (c->t) + i = tty_get_baud (c->t); + else + i = -1; + + if (j == 1) + { + /*Closest bit edge is one bit, so the baud rate is too low */ + p->guessed_baud = -1; + + } + else + { + if (i > 0) + p->guessed_baud = i / j; + else + p->guessed_baud = 0; + + } + + if (p->guessed_baud == -1) + { + log_f (c->l, "", + p->biterrs, i); + } + else + { + log_f (c->l, "", + p->biterrs, i, p->guessed_baud); + } + +} + +TTY_Parser * +tty_parser_new (void) +{ + TTY_Parser *p; + + p = (TTY_Parser *) malloc (sizeof (TTY_Parser)); + + memset (p, 0, sizeof (TTY_Parser)); + + return p; +} + +void +tty_parse (Context * c, uint8_t * buf, int len) +{ + TTY_Parser *p; + + p = c->tp; + + while (len--) + { + + if (p->in_dle) + { + p->in_dle = 0; + switch (*buf) + { + case DLE: + tty_bit_analyse (c, 0, *buf); + utf8_parse (c, *buf); + break; + case 0: + p->in_errmark = 1; + break; + default: + log_f (c->l, "%s:%d DLE parsing error: \\377 \\%03o", __FILE__, + __LINE__, *buf); + } + } + else if (p->in_errmark) + { + p->in_errmark = 0; + + log_f (c->l, "", + __FILE__, __LINE__, *buf); + + tty_bit_analyse (c, 1, *buf); + + tty_analyse (c); + + utf8_parse (c, *buf); + + utf8_parse (c, SYM_CHAR_RESET); + + } + else if (*buf == DLE) + { + p->in_dle = 1; + + } + else + { + tty_bit_analyse (c, 0, *buf); + + tty_analyse (c); + + utf8_parse (c, *buf); + + } + buf++; + } +}