Commit 8c5185f9db51a5eea9a0e0a794f95131cacd391c
authorMichel Pollet <buserror@gmail.com>
Sat, 2 Jun 2012 14:34:21 +0000 (15:34 +0100)
committerMichel Pollet <buserror@gmail.com>
Sat, 2 Jun 2012 14:34:21 +0000 (15:34 +0100)
The previous way to debug was 'stealing' the port by using an xterm on it..
the new way leaves the proper pty available to the application you want to use
but still allow you to have a 'tap' port that sees both the sides of the
communication om the other pty.

You can also type stuff obviously, and it does some cr/lf conversions.

/tmp/simavr-uart0 : will be the normal fake serial port
/tmp/simavr-uarttap0 : is the one to launch an xterm on

This allow you to really see the serial traffic as it happends with both
requests and replies.

Signed-off-by: Michel Pollet <buserror@gmail.com>
2 files changed:
examples/parts/uart_pty.c
examples/parts/uart_pty.h

index 6fc3287348690244d81032e61583b5e084601703..eb3ba7fb7d46d88ddec79cbd273a8dffa1fc057a 100644 (file)
@@ -55,7 +55,13 @@ uart_pty_in_hook(
 {
        uart_pty_t * p = (uart_pty_t*)param;
        TRACE(printf("uart_pty_in_hook %02x\n", value);)
-       uart_pty_fifo_write(&p->in, value);
+       uart_pty_fifo_write(&p->pty.in, value);
+
+       if (p->tap.s) {
+               if (p->tap.crlf && value == '\n')
+                       uart_pty_fifo_write(&p->tap.in, '\r');
+               uart_pty_fifo_write(&p->tap.in, value);
+       }
 }
 
 // try to empty our fifo, the uart_pty_xoff_hook() will be called when
@@ -64,10 +70,22 @@ static void
 uart_pty_flush_incoming(
                uart_pty_t * p)
 {
-       while (p->xon && !uart_pty_fifo_isempty(&p->out)) {
-               uint8_t byte = uart_pty_fifo_read(&p->out);
+       while (p->xon && !uart_pty_fifo_isempty(&p->pty.out)) {
+               uint8_t byte = uart_pty_fifo_read(&p->pty.out);
                TRACE(printf("uart_pty_flush_incoming send %02x\n", byte);)
                avr_raise_irq(p->irq + IRQ_UART_PTY_BYTE_OUT, byte);
+
+               if (p->tap.s) {
+                       if (p->tap.crlf && byte == '\n')
+                               uart_pty_fifo_write(&p->tap.in, '\r');
+                       uart_pty_fifo_write(&p->tap.in, byte);
+               }
+       }
+       if (p->tap.s) {
+               while (p->xon && !uart_pty_fifo_isempty(&p->tap.out)) {
+                       uint8_t byte = uart_pty_fifo_read(&p->tap.out);
+                       avr_raise_irq(p->irq + IRQ_UART_PTY_BYTE_OUT, byte);
+               }
        }
 }
 
@@ -109,44 +127,55 @@ uart_pty_thread(
 
        while (1) {
                fd_set read_set, write_set;
-               int max = p->s + 1;
+               int max = 0;
                FD_ZERO(&read_set);
                FD_ZERO(&write_set);
 
-               // read more only if buffer was flushed
-               if (p->buffer_len == p->buffer_done)
-                       FD_SET(p->s, &read_set);
-               if (!uart_pty_fifo_isempty(&p->in))
-                       FD_SET(p->s, &write_set);
+               for (int ti = 0; ti < 2; ti++) if (p->port[ti].s) {
+                       // read more only if buffer was flushed
+                       if (p->port[ti].buffer_len == p->port[ti].buffer_done) {
+                               FD_SET(p->port[ti].s, &read_set);
+                               max = p->port[ti].s > max ? p->port[ti].s : max;
+                       }
+                       if (!uart_pty_fifo_isempty(&p->port[ti].in)) {
+                               FD_SET(p->port[ti].s, &write_set);
+                               max = p->port[ti].s > max ? p->port[ti].s : max;
+                       }
+               }
 
                struct timeval timo = { 0, 500 };       // short, but not too short interval
-               int ret = select(max, &read_set, &write_set, NULL, &timo);
+               int ret = select(max+1, &read_set, &write_set, NULL, &timo);
 
                if (!ret)
                        continue;
                if (ret < 0)
                        break;
 
-               if (FD_ISSET(p->s, &read_set)) {
-                       ssize_t r = read(p->s, p->buffer, sizeof(p->buffer)-1);
-                       p->buffer_len = r;
-                       p->buffer_done = 0;
-                       TRACE(hdump("pty recv", p->buffer, r);)
-               }
-               if (p->buffer_done < p->buffer_len) {
-                       // write them in fifo
-                       while (p->buffer_done < p->buffer_len && !uart_pty_fifo_isfull(&p->out))
-                               uart_pty_fifo_write(&p->out, p->buffer[p->buffer_done++]);
-               }
-               if (FD_ISSET(p->s, &write_set)) {
-                       uint8_t buffer[512];
-                       // write them in fifo
-                       uint8_t * dst = buffer;
-                       while (!uart_pty_fifo_isempty(&p->in) && dst < (buffer+sizeof(buffer)))
-                               *dst++ = uart_pty_fifo_read(&p->in);
-                       size_t len = dst - buffer;
-                       TRACE(size_t r =) write(p->s, buffer, len);
-                       TRACE(hdump("pty send", buffer, r);)
+               for (int ti = 0; ti < 2; ti++) if (p->port[ti].s) {
+                       if (FD_ISSET(p->port[ti].s, &read_set)) {
+                               ssize_t r = read(p->port[ti].s, p->port[ti].buffer, sizeof(p->port[ti].buffer)-1);
+                               p->port[ti].buffer_len = r;
+                               p->port[ti].buffer_done = 0;
+                               TRACE(hdump("pty recv", p->port[ti].buffer, r);)
+                       }
+                       if (p->port[ti].buffer_done < p->port[ti].buffer_len) {
+                               // write them in fifo
+                               while (p->port[ti].buffer_done < p->port[ti].buffer_len &&
+                                               !uart_pty_fifo_isfull(&p->port[ti].out))
+                                       uart_pty_fifo_write(&p->port[ti].out,
+                                                       p->port[ti].buffer[p->port[ti].buffer_done++]);
+                       }
+                       if (FD_ISSET(p->port[ti].s, &write_set)) {
+                               uint8_t buffer[512];
+                               // write them in fifo
+                               uint8_t * dst = buffer;
+                               while (!uart_pty_fifo_isempty(&p->port[ti].in) &&
+                                               dst < (buffer + sizeof(buffer)))
+                                       *dst++ = uart_pty_fifo_read(&p->port[ti].in);
+                               size_t len = dst - buffer;
+                               TRACE(size_t r =) write(p->port[ti].s, buffer, len);
+                               TRACE(hdump("pty send", buffer, r);)
+                       }
                }
                uart_pty_flush_incoming(p);
        }
@@ -163,19 +192,32 @@ uart_pty_init(
                struct avr_t * avr,
                uart_pty_t * p)
 {
+       memset(p, 0, sizeof(*p));
+
        p->avr = avr;
        p->irq = avr_alloc_irq(&avr->irq_pool, 0, IRQ_UART_PTY_COUNT, irq_names);
        avr_irq_register_notify(p->irq + IRQ_UART_PTY_BYTE_IN, uart_pty_in_hook, p);
 
-       int m, s;
+       int hastap = (getenv("SIMAVR_UART_TAP") && atoi(getenv("SIMAVR_UART_TAP"))) ||
+                       (getenv("SIMAVR_UART_XTERM") && atoi(getenv("SIMAVR_UART_XTERM"))) ;
 
-       if (openpty(&m, &s, p->slavename, NULL, NULL) < 0) {
-               fprintf(stderr, "%s: Can't create pty: %s", __FUNCTION__, strerror(errno));
-               return ;
-       }
-       p->s = m;
+       for (int ti = 0; ti < 1 + hastap; ti++) {
+               int m, s;
 
-       printf("uart_pty_init bridge on port *** %s ***\n", p->slavename);
+               if (openpty(&m, &s, p->port[ti].slavename, NULL, NULL) < 0) {
+                       fprintf(stderr, "%s: Can't create pty: %s", __FUNCTION__, strerror(errno));
+                       return ;
+               }
+               struct termios tio;
+               tcgetattr(m, &tio);
+               cfmakeraw(&tio);
+               tcsetattr(m, TCSANOW, &tio);
+               p->port[ti].s = m;
+               p->port[ti].tap = ti != 0;
+               p->port[ti].crlf = ti != 0;
+               printf("uart_pty_init %s on port *** %s ***\n",
+                               ti == 0 ? "bridge" : "tap", p->port[ti].slavename);
+       }
 
        pthread_create(&p->thread, NULL, uart_pty_thread, p);
 
@@ -187,7 +229,9 @@ uart_pty_stop(
 {
        puts(__func__);
        pthread_kill(p->thread, SIGINT);
-       close(p->s);
+       for (int ti = 0; ti < 2; ti++)
+               if (p->port[ti].s)
+                       close(p->port[ti].s);
        void * ret;
        pthread_join(p->thread, &ret);
 }
@@ -216,17 +260,20 @@ uart_pty_connect(
        if (xoff)
                avr_irq_register_notify(xoff, uart_pty_xoff_hook, p);
 
-       char link[128];
-       sprintf(link, "/tmp/simavr-uart%c", uart);
-       unlink(link);
-       if (symlink(p->slavename, link) != 0) {
-               fprintf(stderr, "WARN %s: Can't create %s: %s", __func__, link, strerror(errno));
-       } else {
-               printf("%s: %s now points to %s\n", __func__, link, p->slavename);
+       for (int ti = 0; ti < 1; ti++) if (p->port[ti].s) {
+               char link[128];
+               sprintf(link, "/tmp/simavr-uart%s%c", ti == 1 ? "tap" : "", uart);
+               unlink(link);
+               if (symlink(p->port[ti].slavename, link) != 0) {
+                       fprintf(stderr, "WARN %s: Can't create %s: %s", __func__, link, strerror(errno));
+               } else {
+                       printf("%s: %s now points to %s\n", __func__, link, p->port[ti].slavename);
+               }
        }
        if (getenv("SIMAVR_UART_XTERM") && atoi(getenv("SIMAVR_UART_XTERM"))) {
                char cmd[256];
-               sprintf(cmd, "nohup xterm -e picocom -b 115200 %s >/dev/null 2>&1 &", p->slavename);
+               sprintf(cmd, "xterm -e picocom -b 115200 %s >/dev/null 2>&1 &",
+                               p->tap.slavename);
                system(cmd);
        } else
                printf("note: export SIMAVR_UART_XTERM=1 and install picocom to get a terminal\n");
index f797e58cff840cdc24f648637b627e5c50560c17..c6e0603aada6791457c567ae8e3e0676c062b4b7 100644 (file)
@@ -35,19 +35,30 @@ enum {
 
 DECLARE_FIFO(uint8_t,uart_pty_fifo, 512);
 
+typedef struct uart_pty_port_t {
+       int                     tap : 1, crlf : 1;
+       int             s;                      // socket we chat on
+       char            slavename[64];
+       uart_pty_fifo_t in;
+       uart_pty_fifo_t out;
+       uint8_t         buffer[512];
+       size_t          buffer_len, buffer_done;
+} uart_pty_port_t, *uart_pty_port_p;
+
 typedef struct uart_pty_t {
        avr_irq_t *     irq;            // irq list
        struct avr_t *avr;              // keep it around so we can pause it
 
        pthread_t       thread;
-       int             s;                      // socket we chat on
-       char            slavename[64];
        int                     xon;
-       uart_pty_fifo_t in;
-       uart_pty_fifo_t out;
 
-       uint8_t         buffer[512];
-       size_t          buffer_len, buffer_done;
+       union {
+               struct {
+                       uart_pty_port_t         pty;
+                       uart_pty_port_t         tap;
+               };
+               uart_pty_port_t port[2];
+       };
 } uart_pty_t;
 
 void