+#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,
+ "<tty_bit_analyse: 0%d%d%d%d%d%d%d%d1 [%d,%d,%d,%d,%d,%d,%d,%d,%d,%d]>",
+ 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 && j > 0)
+ p->guessed_baud = i / j;
+ else
+ p->guessed_baud = 0;
+
+ }
+
+ if (p->guessed_baud == -1) {
+ log_f (c->l, "<tty_analyse: %6d errors, current rate %db is too low>",
+ p->biterrs, i);
+ } else {
+ log_f (c->l, "<tty_analyse: %6d errors, current rate %db, suggest %db>",
+ p->biterrs, i, p->guessed_baud);
+ }
+
+}
+
+TTY_Parser *
+tty_parser_new (void)
+{
+ TTY_Parser *p;
+
+ p = (TTY_Parser *) xmalloc (sizeof (TTY_Parser));
+
+ memset (p, 0, sizeof (TTY_Parser));
+
+ return p;
+}
+
+int
+tty_parse (Context * c, uint8_t * buf, int len)
+{
+ TTY_Parser *p;
+ int err = 0;
+
+ p = c->tp;
+
+ while (len--) {
+
+ if (p->in_dle) {
+ p->in_dle = 0;
+ switch (*buf) {
+ case DLE:
+ tty_bit_analyse (c, 0, *buf);
+ err += 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, "<tty reports error: \\377 \\000 \\%03o>",
+ __FILE__, __LINE__, *buf);
+
+ tty_bit_analyse (c, 1, *buf);
+
+ tty_analyse (c);
+
+ err += utf8_parse (c, *buf);
+
+ err += utf8_parse (c, SYM_CHAR_RESET);
+
+ } else if (*buf == DLE) {
+ p->in_dle = 1;
+
+ } else {
+ tty_bit_analyse (c, 0, *buf);
+
+ tty_analyse (c);
+
+ err += utf8_parse (c, *buf);
+
+ }
+ buf++;
+ }
+ return err;
+}