4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
8 simavr is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 simavr is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with simavr. If not, see <http://www.gnu.org/licenses/>.
32 DEFINE_FIFO(uint8_t,uart_udp_fifo);
35 * called when a byte is send via the uart on the AVR
37 static void uart_udp_in_hook(struct avr_irq_t * irq, uint32_t value, void * param)
39 uart_udp_t * p = (uart_udp_t*)param;
40 // printf("uart_udp_in_hook %02x\n", value);
41 uart_udp_fifo_write(&p->in, value);
45 * Called when the uart has room in it's input buffer. This is called repeateadly
46 * if necessary, while the xoff is called only when the uart fifo is FULL
48 static void uart_udp_xon_hook(struct avr_irq_t * irq, uint32_t value, void * param)
50 uart_udp_t * p = (uart_udp_t*)param;
52 // printf("uart_udp_xon_hook\n");
54 // try to empty our fifo, the uart_udp_xoff_hook() will be called when
56 while (p->xon && !uart_udp_fifo_isempty(&p->out)) {
57 uint8_t byte = uart_udp_fifo_read(&p->out);
58 // printf("uart_udp_xon_hook send %02x\n", byte);
59 avr_raise_irq(p->irq + IRQ_UART_UDP_BYTE_OUT, byte);
64 * Called when the uart ran out of room in it's input buffer
66 static void uart_udp_xoff_hook(struct avr_irq_t * irq, uint32_t value, void * param)
68 uart_udp_t * p = (uart_udp_t*)param;
70 // printf("uart_udp_xoff_hook\n");
74 static void * uart_udp_thread(void * param)
76 uart_udp_t * p = (uart_udp_t*)param;
79 fd_set read_set, write_set;
84 FD_SET(p->s, &read_set);
85 if (!uart_udp_fifo_isempty(&p->in))
86 FD_SET(p->s, &write_set);
88 struct timeval timo = { 0, 500 }; // short, but not too short interval
89 int ret = select(max, &read_set, &write_set, NULL, &timo);
94 if (FD_ISSET(p->s, &read_set)) {
97 socklen_t len = sizeof(p->peer);
98 ssize_t r = recvfrom(p->s, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&p->peer, &len);
100 // hdump("udp recv", buffer, r);
102 // write them in fifo
103 uint8_t * src = buffer;
104 while (r-- && !uart_udp_fifo_isfull(&p->out))
105 uart_udp_fifo_write(&p->out, *src++);
107 printf("UDP dropped %zu bytes\n", r);
109 if (FD_ISSET(p->s, &write_set)) {
111 // write them in fifo
112 uint8_t * dst = buffer;
113 while (!uart_udp_fifo_isempty(&p->in) && dst < (buffer+sizeof(buffer)))
114 *dst++ = uart_udp_fifo_read(&p->in);
115 socklen_t len = dst - buffer;
116 /*size_t r = */sendto(p->s, buffer, len, 0, (struct sockaddr*)&p->peer, sizeof(p->peer));
117 // hdump("udp send", buffer, r);
123 static const char * irq_names[IRQ_UART_UDP_COUNT] = {
124 [IRQ_UART_UDP_BYTE_IN] = "8<uart_udp.in",
125 [IRQ_UART_UDP_BYTE_OUT] = "8>uart_udp.out",
128 void uart_udp_init(struct avr_t * avr, uart_udp_t * p)
131 p->irq = avr_alloc_irq(&avr->irq_pool, 0, IRQ_UART_UDP_COUNT, irq_names);
132 avr_irq_register_notify(p->irq + IRQ_UART_UDP_BYTE_IN, uart_udp_in_hook, p);
134 if ((p->s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
135 fprintf(stderr, "%s: Can't create socket: %s", __FUNCTION__, strerror(errno));
139 struct sockaddr_in address = { 0 };
140 address.sin_family = AF_INET;
141 address.sin_port = htons (4321);
143 if (bind(p->s, (struct sockaddr *) &address, sizeof(address))) {
144 fprintf(stderr, "%s: Can not bind socket: %s", __FUNCTION__, strerror(errno));
148 printf("uart_udp_init bridge on port %d\n", 4321);
150 pthread_create(&p->thread, NULL, uart_udp_thread, p);
154 void uart_udp_connect(uart_udp_t * p, char uart)
156 // disable the stdio dump, as we are sending binary there
158 avr_ioctl(p->avr, AVR_IOCTL_UART_GET_FLAGS(uart), &f);
159 f &= ~AVR_UART_FLAG_STDIO;
160 avr_ioctl(p->avr, AVR_IOCTL_UART_SET_FLAGS(uart), &f);
162 avr_irq_t * src = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUTPUT);
163 avr_irq_t * dst = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_INPUT);
164 avr_irq_t * xon = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUT_XON);
165 avr_irq_t * xoff = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUT_XOFF);
167 avr_connect_irq(src, p->irq + IRQ_UART_UDP_BYTE_IN);
168 avr_connect_irq(p->irq + IRQ_UART_UDP_BYTE_OUT, dst);
171 avr_irq_register_notify(xon, uart_udp_xon_hook, p);
173 avr_irq_register_notify(xoff, uart_udp_xoff_hook, p);