void ethos_send_frame(ethos_t *dev, const uint8_t *data, size_t len, unsigned frame_type) { uint8_t frame_delim = ETHOS_FRAME_DELIMITER; if (!irq_is_in()) { mutex_lock(&dev->out_mutex); } else { /* Send frame delimiter. This cancels the current frame, * but enables in-ISR writes. */ uart_write(dev->uart, &frame_delim, 1); } /* send frame delimiter */ uart_write(dev->uart, &frame_delim, 1); /* set frame type */ if (frame_type) { uint8_t out[2] = { ETHOS_ESC_CHAR, (frame_type ^ 0x20) }; uart_write(dev->uart, out, 2); } /* send frame content */ while(len--) { _write_escaped(dev->uart, *(uint8_t*)data++); } /* end of frame */ uart_write(dev->uart, &frame_delim, 1); if (!irq_is_in()) { mutex_unlock(&dev->out_mutex); } }
static int _send(netdev_t *netdev, const iolist_t *iolist) { ethos_t * dev = (ethos_t *) netdev; (void)dev; /* count total packet length */ size_t pktlen = iolist_count_total(iolist); /* lock line in order to prevent multiple writes */ mutex_lock(&dev->out_mutex); /* send start-frame-delimiter */ uint8_t frame_delim = ETHOS_FRAME_DELIMITER; uart_write(dev->uart, &frame_delim, 1); /* send iolist */ for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) { size_t n = iol->iol_len; uint8_t *ptr = iol->iol_base; while(n--) { _write_escaped(dev->uart, *ptr++); } } uart_write(dev->uart, &frame_delim, 1); mutex_unlock(&dev->out_mutex); return pktlen; }
static int _send(netdev2_t *netdev, const struct iovec *vector, int count) { ethos_t * dev = (ethos_t *) netdev; (void)dev; /* count total packet length */ size_t pktlen = iovec_count_total(vector, count); /* lock line in order to prevent multiple writes */ mutex_lock(&dev->out_mutex); /* send start-frame-delimiter */ uint8_t frame_delim = ETHOS_FRAME_DELIMITER; uart_write(dev->uart, &frame_delim, 1); /* send iovec */ while(count--) { size_t n = vector->iov_len; uint8_t *ptr = vector->iov_base; while(n--) { _write_escaped(dev->uart, *ptr++); } vector++; } uart_write(dev->uart, &frame_delim, 1); mutex_unlock(&dev->out_mutex); return pktlen; }
int main(int argc, char *argv[]) { char inbuf[MTU]; serial_t serial = {0}; if (argc < 3) { usage(); return 1; } char ifname[IFNAMSIZ]; strncpy(ifname, argv[1], IFNAMSIZ); int tap_fd = tun_alloc(ifname, IFF_TAP | IFF_NO_PI); if (tap_fd < 0) { return 1; } int serial_fd = open(argv[2], O_RDWR | O_NOCTTY | O_SYNC); if (serial_fd < 0) { fprintf(stderr, "Error opening serial device %s\n", argv[2]); return 1; } set_serial_attribs(serial_fd, B115200, 0); set_blocking(serial_fd, 1); fd_set readfds; int max_fd = (serial_fd > tap_fd) ? serial_fd : tap_fd; fprintf(stderr, "----> ethos: sending hello.\n"); _send_hello(serial_fd, &serial, LINE_FRAME_TYPE_HELLO); fprintf(stderr, "----> ethos: activating serial pass through.\n"); _send_hello(serial_fd, &serial, LINE_FRAME_TYPE_HELLO); while(1) { int activity; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); FD_SET(tap_fd, &readfds); FD_SET(serial_fd, &readfds); activity = select( max_fd + 1 , &readfds , NULL , NULL , NULL); if ((activity < 0) && (errno != EINTR)) { perror("select error"); } if (FD_ISSET(serial_fd, &readfds)) { ssize_t n = read(serial_fd, inbuf, sizeof(inbuf)); if (n > 0) { char *ptr = inbuf; while (n--) { size_t res = _serial_handle_byte(&serial, *ptr++); if (res) { switch (serial.frametype) { case LINE_FRAME_TYPE_DATA: write(tap_fd, serial.frame, serial.framebytes); break; case LINE_FRAME_TYPE_TEXT: write(STDOUT_FILENO, serial.frame, serial.framebytes); break; case LINE_FRAME_TYPE_HELLO: case LINE_FRAME_TYPE_HELLO_REPLY: if (serial.framebytes == 6) { memcpy(serial.remote_l2_addr, serial.frame, 6); if (serial.frametype == LINE_FRAME_TYPE_HELLO) { fprintf(stderr, "----> ethos: hello received\n"); _send_hello(serial_fd, &serial, LINE_FRAME_TYPE_HELLO_REPLY); } else { fprintf(stderr, "----> ethos: hello reply received\n"); } _clear_neighbor_cache(ifname); } break; } memset(&serial, '\0', sizeof(serial)); } } } else { fprintf(stderr, "lost serial connection.\n"); exit(1); } } if (FD_ISSET(tap_fd, &readfds)) { ssize_t res = read(tap_fd, inbuf, sizeof(inbuf)); if (res <= 0) { fprintf(stderr, "error reading from tap device. res=%zi\n", res); continue; } char delim = LINE_FRAME_DELIMITER; write(serial_fd, &delim, 1); _write_escaped(serial_fd, inbuf, res); write(serial_fd, &delim, 1); } if (FD_ISSET(STDIN_FILENO, &readfds)) { ssize_t res = read(STDIN_FILENO, inbuf, sizeof(inbuf)); if (res <= 0) { fprintf(stderr, "error reading from stdio. res=%zi\n", res); continue; } if (res) { char delim = LINE_FRAME_DELIMITER; char head[] = { LINE_FRAME_DELIMITER, LINE_ESC_CHAR, (LINE_FRAME_TYPE_TEXT ^ 0x20) }; write(serial_fd, head, sizeof(head)); _write_escaped(serial_fd, inbuf, res); write(serial_fd, &delim, 1); } } } return 0; }