mbed OS5
Fork of UIPEthernet by
Diff: UIPClient.cpp
- Revision:
- 4:d774541a34da
- Parent:
- 2:049ce85163c5
- Child:
- 6:10e42359e217
diff -r 5b17e4656dd0 -r d774541a34da UIPClient.cpp --- a/UIPClient.cpp Sat Dec 20 11:10:40 2014 +0000 +++ b/UIPClient.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -3,6 +3,8 @@ Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> All rights reserved. + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -18,9 +20,10 @@ */ extern "C" { -#include "utility/uip-conf.h" -#include "utility/uip.h" -#include "utility/uip_arp.h" +#include "utility/uip-conf.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +#include "utility/millis.h" #include "string.h" } #include "UIPEthernet.h" @@ -32,7 +35,7 @@ #endif #define UIP_TCP_PHYH_LEN UIP_LLH_LEN + UIP_IPTCPH_LEN -uip_userdata_closed_t* UIPClient:: closed_conns[UIP_CONNS]; +uip_userdata_t UIPClient:: all_data[UIP_CONNS]; /** * @brief @@ -41,20 +44,7 @@ * @retval */ UIPClient::UIPClient(void) : - _uip_conn(NULL), - data(NULL) { - UIPEthernet.set_uip_callback(&UIPClient::uip_callback); -} - -/** - * @brief - * @note - * @param - * @retval - */ -UIPClient::UIPClient(struct uip_conn* conn) : - _uip_conn(conn), - data(conn ? (uip_userdata_t*)conn->appstate.user : NULL) + data(NULL) { } /** @@ -63,9 +53,8 @@ * @param * @retval */ -UIPClient::UIPClient(uip_userdata_closed_t* conn_data) : - _uip_conn(NULL), - data((uip_userdata_t*)conn_data) +UIPClient::UIPClient(uip_userdata_t* conn_data) : + data(conn_data) { } /** @@ -75,22 +64,36 @@ * @retval */ int UIPClient::connect(IPAddress ip, uint16_t port) { + stop(); + uip_ipaddr_t ipaddr; uip_ip_addr(ipaddr, ip); - _uip_conn = uip_connect(&ipaddr, htons(port)); - if(_uip_conn) { - while((_uip_conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) { + + struct uip_conn* conn = uip_connect(&ipaddr, htons(port)); + if(conn) + { +#if UIP_CONNECT_TIMEOUT > 0 + int32_t timeout = millis() + 1000 * UIP_CONNECT_TIMEOUT; +#endif + while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) { UIPEthernet.tick(); - if((_uip_conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) - { + if((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) { + data = (uip_userdata_t*)conn->appstate; #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("connected, state: "); - Serial.print(((uip_userdata_t*)_uip_conn->appstate.user)->state); - Serial.print(", first packet in: "); - Serial.println(((uip_userdata_t*)_uip_conn->appstate.user)->packets_in[0]); + Serial.print(F("connected, state: ")); + Serial.print(data->state); + Serial.print(F(", first packet in: ")); + Serial.println(data->packets_in[0]); #endif return 1; } + +#if UIP_CONNECT_TIMEOUT > 0 + if(((int32_t) (millis() - timeout)) > 0) { + conn->tcpstateflags = UIP_CLOSED; + break; + } +#endif } } @@ -111,7 +114,7 @@ DNSClient dns; IPAddress remote_addr; - dns.begin(UIPEthernet.dnsServerIP()); + dns.begin(UIPEthernetClass::_dnsServerAddress); ret = dns.getHostByName(host, remote_addr); if(ret == 1) { return connect(remote_addr, port); @@ -127,29 +130,32 @@ * @retval */ void UIPClient::stop(void) { - if(data) { + if(data && data->state) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("before stop(), with data")); + _dumpAllData(); +#endif _flushBlocks(&data->packets_in[0]); - if(data->state & UIP_CLIENT_CLOSED) { - uip_userdata_closed_t ** cc = &UIPClient::closed_conns[0]; - for(uint8_t i = 0; i < UIP_CONNS; i++) { - if(*cc == (void*)data) { - *cc = NULL; - break; - } - - cc++; - } - - free(data); + if(data->state & UIP_CLIENT_REMOTECLOSED) { + data->state = 0; } else { data->state |= UIP_CLIENT_CLOSE; } - data = NULL; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("after stop()")); + _dumpAllData(); +#endif } - _uip_conn = NULL; +#ifdef UIPETHERNET_DEBUG_CLIENT + else { + Serial.println(F("stop(), data: NULL")); + } +#endif + data = NULL; UIPEthernet.tick(); } @@ -160,7 +166,7 @@ * @retval */ uint8_t UIPClient::connected(void) { - return((_uip_conn && (_uip_conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) || available() > 0) ? 1 : 0; + return(data && (data->packets_in[0] != NOBLOCK || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0; } /** @@ -170,7 +176,7 @@ * @retval */ bool UIPClient::operator==(const UIPClient& rhs) { - return _uip_conn && rhs._uip_conn && _uip_conn == rhs._uip_conn; + return data && rhs.data && (data == rhs.data); } /** @@ -181,8 +187,7 @@ */ UIPClient::operator bool(void) { UIPEthernet.tick(); - return(data || (_uip_conn && (data = (uip_userdata_t*)_uip_conn->appstate.user))) -&& (!(data->state & UIP_CLIENT_CLOSED) || data->packets_in[0] != NOBLOCK); + return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in[0] != NOBLOCK); } /** @@ -192,7 +197,7 @@ * @retval */ size_t UIPClient::write(uint8_t c) { - return _write(_uip_conn, &c, 1); + return _write(data, &c, 1); } /** @@ -202,7 +207,7 @@ * @retval */ size_t UIPClient::write(const uint8_t* buf, size_t size) { - return _write(_uip_conn, buf, size); + return _write(data, buf, size); } /** @@ -211,21 +216,20 @@ * @param * @retval */ -size_t UIPClient::_write(struct uip_conn* conn, const uint8_t* buf, size_t size) { - uip_userdata_t* u; - int remain = size; - uint16_t written; +size_t UIPClient::_write(uip_userdata_t* u, const uint8_t* buf, size_t size) { + int remain = size; + uint16_t written; #if UIP_ATTEMPTS_ON_WRITE > 0 - uint16_t attempts = UIP_ATTEMPTS_ON_WRITE; + uint16_t attempts = UIP_ATTEMPTS_ON_WRITE; #endif repeat : UIPEthernet.tick(); - if(conn && (u = (uip_userdata_t*)conn->appstate.user) && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) { - memhandle* p = _currentBlock(&u->packets_out[0]); - if(*p == NOBLOCK) + if(u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) { + uint8_t p = _currentBlock(&u->packets_out[0]); + if(u->packets_out[p] == NOBLOCK) { newpacket: - *p = UIPEthernet.network.allocBlock(UIP_SOCKET_DATALEN); - if(*p == NOBLOCK) + u->packets_out[p] = UIPEthernet.network.allocBlock(UIP_SOCKET_DATALEN); + if(u->packets_out[p] == NOBLOCK) { #if UIP_ATTEMPTS_ON_WRITE > 0 if((--attempts) > 0) @@ -240,23 +244,29 @@ } #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("UIPClient.write: writePacket("); - Serial.print(*p); - Serial.print(") pos: "); + Serial.print(F("UIPClient.write: writePacket(")); + Serial.print(u->packets_out[p]); + Serial.print(F(") pos: ")); Serial.print(u->out_pos); - Serial.print(", buf["); + Serial.print(F(", buf[")); Serial.print(size - remain); - Serial.print("-"); + Serial.print(F("-")); Serial.print(remain); - Serial.print("]: '"); + Serial.print(F("]: '")); Serial.write((uint8_t*)buf + size - remain, remain); - Serial.println("'"); + Serial.println(F("'")); #endif - written = UIPEthernet.network.writePacket(*p, u->out_pos, (uint8_t*)buf + size - remain, remain); + written = UIPEthernet.network.writePacket + ( + u->packets_out[p], + u->out_pos, + (uint8_t*)buf + size - remain, + remain + ); remain -= written; u->out_pos += written; if(remain > 0) { - if(p == &u->packets_out[UIP_SOCKET_NUMPACKETS - 1]) + if(p == UIP_SOCKET_NUMPACKETS - 1) { #if UIP_ATTEMPTS_ON_WRITE > 0 if((--attempts) > 0) @@ -272,6 +282,9 @@ } ready: +#if UIP_CLIENT_TIMER >= 0 + u->timer = millis() + UIP_CLIENT_TIMER; +#endif return size - remain; } @@ -287,7 +300,7 @@ int UIPClient::available(void) { if(*this) return _available(data); - return -1; + return 0; } /** @@ -297,15 +310,9 @@ * @retval */ int UIPClient::_available(uip_userdata_t* u) { - memhandle* p = &u->packets_in[0]; - if(*p == NOBLOCK) - return 0; - int len = 0; - for(memhandle * end = p + UIP_SOCKET_NUMPACKETS; p < end; p++) { - if(*p == NOBLOCK) - break; - len += UIPEthernet.network.blockSize(*p); + for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { + len += UIPEthernet.network.blockSize(u->packets_in[i]); } return len; @@ -319,25 +326,33 @@ */ int UIPClient::read(uint8_t* buf, size_t size) { if(*this) { - int remain = size; - memhandle* p = &data->packets_in[0]; - if(*p == NOBLOCK) + uint16_t remain = size; + if(data->packets_in[0] == NOBLOCK) return 0; - int read; + uint16_t read; do { - read = UIPEthernet.network.readPacket(*p, 0, buf + size - remain, remain); - if(read == UIPEthernet.network.blockSize(*p)) { + read = UIPEthernet.network.readPacket(data->packets_in[0], 0, buf + size - remain, remain); + if(read == UIPEthernet.network.blockSize(data->packets_in[0])) { remain -= read; - _eatBlock(p); - if(_uip_conn && uip_stopped(_uip_conn) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) - data->state |= UIP_CLIENT_RESTART; - if(*p == NOBLOCK) + _eatBlock(&data->packets_in[0]); + if + ( + uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) + && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)) + ) data->state |= UIP_CLIENT_RESTART; + if(data->packets_in[0] == NOBLOCK) { + if(data->state & UIP_CLIENT_REMOTECLOSED) { + data->state = 0; + data = NULL; + } + return size - remain; + } } else { - UIPEthernet.network.resizeBlock(*p, read); + UIPEthernet.network.resizeBlock(data->packets_in[0], read); break; } } while(remain > 0); @@ -368,10 +383,9 @@ */ int UIPClient::peek(void) { if(*this) { - memhandle p = data->packets_in[0]; - if(p != NOBLOCK) { + if(data->packets_in[0] != NOBLOCK) { uint8_t c; - UIPEthernet.network.readPacket(p, 0, &c, 1); + UIPEthernet.network.readPacket(data->packets_in[0], 0, &c, 1); return c; } } @@ -397,67 +411,58 @@ * @param * @retval */ -void UIPClient::uip_callback(uip_tcp_appstate_t* s) { - uip_userdata_t* u = (uip_userdata_t*)s->user; +void uipclient_appcall(void) { + uint16_t send_len = 0; + uip_userdata_t* u = (uip_userdata_t*)uip_conn->appstate; if(!u && uip_connected()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.println("UIPClient uip_connected"); + Serial.println(F("UIPClient uip_connected")); + UIPClient::_dumpAllData(); #endif - // We want to store some data in our connections, so allocate some space + u = (uip_userdata_t*)UIPClient::_allocateData(); + if(u) { + uip_conn->appstate = u; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("UIPClient allocated state: ")); + Serial.println(u->state, BIN); +#endif + } - // for it. The connection_data struct is defined in a separate .h file, - // due to the way the Arduino IDE works. (typedefs come after function - // definitions.) - u = (uip_userdata_t*)malloc(sizeof(uip_userdata_t)); - if(u) { - memset(u, 0, sizeof(uip_userdata_t)); - s->user = u; - } +#ifdef UIPETHERNET_DEBUG_CLIENT + else + Serial.println(F("UIPClient allocation failed")); +#endif } if(u) { if(uip_newdata()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("UIPClient uip_newdata, uip_len:"); + Serial.print(F("UIPClient uip_newdata, uip_len:")); Serial.println(uip_len); #endif - if(uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) { - memhandle newPacket = UIPEthernet.network.allocBlock(uip_len); - if(newPacket != NOBLOCK) { - memhandle* p = _currentBlock(&u->packets_in[0]); - //if it's not the first packet - - if(*p != NOBLOCK) { - uint8_t slot = p - &u->packets_in[0]; - if(slot < UIP_SOCKET_NUMPACKETS - 1) - p++; - - //if this is the last slot stop this connection - if(slot >= UIP_SOCKET_NUMPACKETS - 2) { - uip_stop(); - - //if there's no free slot left omit loosing this packet and (again) stop this connection - if(slot == UIP_SOCKET_NUMPACKETS - 1) - goto reject_newdata; + if(uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) { + for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { + if(u->packets_in[i] == NOBLOCK) { + u->packets_in[i] = UIPEthernet.network.allocBlock(uip_len); + if(u->packets_in[i] != NOBLOCK) { + UIPEthernet.network.copyPacket + ( + u->packets_in[i], + 0, + UIPEthernetClass::in_packet, + ((uint8_t*)uip_appdata) - uip_buf, + uip_len + ); + if(i == UIP_SOCKET_NUMPACKETS - 1) + uip_stop(); + goto finish_newdata; } } - - UIPEthernet.network.copyPacket - ( - newPacket, - 0, - UIPEthernet.in_packet, - ((uint8_t*)uip_appdata) - uip_buf, - uip_len - ); - *p = newPacket; - goto finish_newdata; } -reject_newdata: - UIPEthernet.packetstate &= ~UIPETHERNET_FREEPACKET; + UIPEthernetClass::packetstate &= ~UIPETHERNET_FREEPACKET; uip_stop(); } } @@ -472,66 +477,67 @@ if(uip_closed() || uip_timedout()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.println("UIPClient uip_closed"); + Serial.println(F("UIPClient uip_closed")); + UIPClient::_dumpAllData(); #endif // drop outgoing packets not sent yet: - _flushBlocks(&u->packets_out[0]); + UIPClient::_flushBlocks(&u->packets_out[0]); if(u->packets_in[0] != NOBLOCK) { - uip_userdata_closed_t ** closed_conn_data = &UIPClient::closed_conns[0]; - for(uip_socket_ptr i = 0; i < UIP_CONNS; i++) { - if(!*closed_conn_data) { - *closed_conn_data = (uip_userdata_closed_t*)u; - (*closed_conn_data)->lport = uip_conn->lport; - break; - } - - closed_conn_data++; - } + ((uip_userdata_closed_t*)u)->lport = uip_conn->lport; + u->state |= UIP_CLIENT_REMOTECLOSED; } - - u->state |= UIP_CLIENT_CLOSED; + else + u->state = 0; // disassociate appdata. - s->user = NULL; - goto nodata; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("after UIPClient uip_closed")); + UIPClient::_dumpAllData(); +#endif + uip_conn->appstate = NULL; + goto finish; } if(uip_acked()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.println("UIPClient uip_acked"); + Serial.println(F("UIPClient uip_acked")); #endif - _eatBlock(&u->packets_out[0]); + UIPClient::_eatBlock(&u->packets_out[0]); } if(uip_poll() || uip_rexmit()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.println("UIPClient uip_poll"); + //Serial.println(F("UIPClient uip_poll")); #endif - - memhandle p = u->packets_out[0]; - if(p != NOBLOCK) { + if(u->packets_out[0] != NOBLOCK) { if(u->packets_out[1] == NOBLOCK) { - uip_len = u->out_pos; - if(uip_len > 0) { - UIPEthernet.network.resizeBlock(p, 0, uip_len); + send_len = u->out_pos; + if(send_len > 0) { + UIPEthernet.network.resizeBlock(u->packets_out[0], 0, send_len); } } else - uip_len = UIPEthernet.network.blockSize(p); - if(uip_len > 0) { - UIPEthernet.uip_hdrlen = ((uint8_t*)uip_appdata) - uip_buf; - UIPEthernet.uip_packet = UIPEthernet.network.allocBlock(UIPEthernet.uip_hdrlen + uip_len); - if(UIPEthernet.uip_packet != NOBLOCK) { - UIPEthernet.network.copyPacket(UIPEthernet.uip_packet, UIPEthernet.uip_hdrlen, p, 0, uip_len); - UIPEthernet.packetstate |= UIPETHERNET_SENDPACKET; - uip_send(uip_appdata, uip_len); + send_len = UIPEthernet.network.blockSize(u->packets_out[0]); + if(send_len > 0) { + UIPEthernetClass::uip_hdrlen = ((uint8_t*)uip_appdata) - uip_buf; + UIPEthernetClass::uip_packet = UIPEthernet.network.allocBlock(UIPEthernetClass::uip_hdrlen + send_len); + if(UIPEthernetClass::uip_packet != NOBLOCK) { + UIPEthernet.network.copyPacket + ( + UIPEthernetClass::uip_packet, + UIPEthernetClass::uip_hdrlen, + u->packets_out[0], + 0, + send_len + ); + UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET; } + } - return; - } + goto finish; } } @@ -539,25 +545,30 @@ if(u->state & UIP_CLIENT_CLOSE) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("UIPClient state UIP_CLIENT_CLOSE"); -#endif - if(u->packets_out[0] == NOBLOCK) - { -#ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("UIPClient state UIP_CLIENT_CLOSE -> free userdata"); + Serial.println(F("UIPClient state UIP_CLIENT_CLOSE")); + UIPClient::_dumpAllData(); #endif - free(u); - s->user = NULL; + if(u->packets_out[0] == NOBLOCK) { + u->state = 0; + uip_conn->appstate = NULL; uip_close(); +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("no blocks out -> free userdata")); + UIPClient::_dumpAllData(); +#endif } - else + else { uip_stop(); +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("blocks outstanding transfer -> uip_stop()")); +#endif + } } } -nodata: - UIPEthernet.uip_packet = NOBLOCK; - uip_len = 0; +finish: + uip_send(uip_appdata, send_len); + uip_len = send_len; } /** @@ -566,11 +577,32 @@ * @param * @retval */ -memhandle* UIPClient::_currentBlock(memhandle* block) { - for(memhandle * end = block + UIP_SOCKET_NUMPACKETS - 1; block < end; block++) - if(*(block + 1) == NOBLOCK) - break; - return block; +uip_userdata_t* UIPClient::_allocateData(void) { + for(uint8_t sock = 0; sock < UIP_CONNS; sock++) { + uip_userdata_t* data = &UIPClient::all_data[sock]; + if(!data->state) { + data->state = sock | UIP_CLIENT_CONNECTED; + memset(&data->packets_in[0], 0, sizeof(uip_userdata_t) - sizeof(data->state)); + return data; + } + } + + return NULL; +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint8_t UIPClient::_currentBlock(memhandle* block) { + for(uint8_t i = 1; i < UIP_SOCKET_NUMPACKETS; i++) { + if(block[i] == NOBLOCK) + return i - 1; + } + + return UIP_SOCKET_NUMPACKETS - 1; } /** @@ -583,26 +615,26 @@ { #ifdef UIPETHERNET_DEBUG_CLIENT memhandle* start = block; - Serial.print("eatblock("); + Serial.print(F("eatblock(")); Serial.print(*block); - Serial.print("): "); + Serial.print(F("): ")); for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { Serial.print(start[i]); - Serial.print(" "); + Serial.print(F(" ")); } - Serial.print("-> "); + Serial.print(F("-> ")); #endif + UIPEthernet.network.freeBlock(block[0]); + for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS - 1; i++) { + block[i] = block[i + 1]; + } - memhandle* end = block + (UIP_SOCKET_NUMPACKETS - 1); - UIPEthernet.network.freeBlock(*block); - while(block < end) - *block = *((block++) + 1); - *end = NOBLOCK; + block[UIP_SOCKET_NUMPACKETS - 1] = NOBLOCK; #ifdef UIPETHERNET_DEBUG_CLIENT for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { Serial.print(start[i]); - Serial.print(" "); + Serial.print(F(" ")); } Serial.println(); @@ -616,13 +648,48 @@ * @retval */ void UIPClient::_flushBlocks(memhandle* block) { - for(memhandle * end = block + UIP_SOCKET_NUMPACKETS; block < end; block++) { - if(*block != NOBLOCK) { - UIPEthernet.network.freeBlock(*block); - *block = NOBLOCK; - } - else - break; + for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { + UIPEthernet.network.freeBlock(block[i]); + block[i] = NOBLOCK; } } +#ifdef UIPETHERNET_DEBUG_CLIENT + +/** + * @brief + * @note + * @param + * @retval + */ +void UIPClient::_dumpAllData(void) { + for(uint8_t i = 0; i < UIP_CONNS; i++) { + Serial.print(F("UIPClient::all_data[")); + Serial.print(i); + Serial.print(F("], state:")); + Serial.println(all_data[i].state, BIN); + Serial.print(F("packets_in: ")); + for(uint8_t j = 0; j < UIP_SOCKET_NUMPACKETS; j++) { + Serial.print(all_data[i].packets_in[j]); + Serial.print(F(" ")); + } + + Serial.println(); + if(all_data[i].state & UIP_CLIENT_REMOTECLOSED) { + Serial.print(F("state remote closed, local port: ")); + Serial.println(htons(((uip_userdata_closed_t *) (&all_data[i]))->lport)); + } + else { + Serial.print(F("packets_out: ")); + for(uint8_t j = 0; j < UIP_SOCKET_NUMPACKETS; j++) { + Serial.print(all_data[i].packets_out[j]); + Serial.print(F(" ")); + } + + Serial.println(); + Serial.print(F("out_pos: ")); + Serial.println(all_data[i].out_pos); + } + } +} +#endif