xref: /btstack/platform/lwip/bnep_lwip.c (revision 97dc5e692c7d94a280158af58036a0efee5b0e56)
1*97dc5e69SMatthias Ringwald /*
2*97dc5e69SMatthias Ringwald  * Copyright (C) 2017 BlueKitchen GmbH
3*97dc5e69SMatthias Ringwald  *
4*97dc5e69SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*97dc5e69SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*97dc5e69SMatthias Ringwald  * are met:
7*97dc5e69SMatthias Ringwald  *
8*97dc5e69SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*97dc5e69SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*97dc5e69SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*97dc5e69SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*97dc5e69SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*97dc5e69SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*97dc5e69SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*97dc5e69SMatthias Ringwald  *    from this software without specific prior written permission.
16*97dc5e69SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*97dc5e69SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*97dc5e69SMatthias Ringwald  *    monetary gain.
19*97dc5e69SMatthias Ringwald  *
20*97dc5e69SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*97dc5e69SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*97dc5e69SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*97dc5e69SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*97dc5e69SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*97dc5e69SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*97dc5e69SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*97dc5e69SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*97dc5e69SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*97dc5e69SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*97dc5e69SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*97dc5e69SMatthias Ringwald  * SUCH DAMAGE.
32*97dc5e69SMatthias Ringwald  *
33*97dc5e69SMatthias Ringwald  * Please inquire about commercial licensing options at
34*97dc5e69SMatthias Ringwald  * [email protected]
35*97dc5e69SMatthias Ringwald  *
36*97dc5e69SMatthias Ringwald  */
37*97dc5e69SMatthias Ringwald 
38*97dc5e69SMatthias Ringwald #define BTSTACK_FILE__ "bnep_lwip_lwip.c"
39*97dc5e69SMatthias Ringwald 
40*97dc5e69SMatthias Ringwald /*
41*97dc5e69SMatthias Ringwald  * bnep_lwip_lwip_.c
42*97dc5e69SMatthias Ringwald  */
43*97dc5e69SMatthias Ringwald 
44*97dc5e69SMatthias Ringwald #include "lwip/netif.h"
45*97dc5e69SMatthias Ringwald #include "lwip/sys.h"
46*97dc5e69SMatthias Ringwald #include "lwip/arch.h"
47*97dc5e69SMatthias Ringwald #include "lwip/api.h"
48*97dc5e69SMatthias Ringwald #include "lwip/netifapi.h"
49*97dc5e69SMatthias Ringwald #include "lwip/tcpip.h"
50*97dc5e69SMatthias Ringwald #include "lwip/ip.h"
51*97dc5e69SMatthias Ringwald #include "lwip/dhcp.h"
52*97dc5e69SMatthias Ringwald #include "lwip/sockets.h"
53*97dc5e69SMatthias Ringwald #include "netif/etharp.h"
54*97dc5e69SMatthias Ringwald #include "lwip/prot/dhcp.h"
55*97dc5e69SMatthias Ringwald 
56*97dc5e69SMatthias Ringwald #include "bnep_lwip.h"
57*97dc5e69SMatthias Ringwald 
58*97dc5e69SMatthias Ringwald #include "btstack_config.h"
59*97dc5e69SMatthias Ringwald #include "btstack_debug.h"
60*97dc5e69SMatthias Ringwald #include "btstack_util.h"
61*97dc5e69SMatthias Ringwald #include "btstack_event.h"
62*97dc5e69SMatthias Ringwald #include "classic/bnep.h"
63*97dc5e69SMatthias Ringwald 
64*97dc5e69SMatthias Ringwald #if NO_SYS
65*97dc5e69SMatthias Ringwald #include "btstack_ring_buffer.h"
66*97dc5e69SMatthias Ringwald #include "btstack_run_loop.h"
67*97dc5e69SMatthias Ringwald #include "lwip/timeouts.h"
68*97dc5e69SMatthias Ringwald #else
69*97dc5e69SMatthias Ringwald #include "btstack_run_loop_freertos.h"
70*97dc5e69SMatthias Ringwald #endif
71*97dc5e69SMatthias Ringwald 
72*97dc5e69SMatthias Ringwald /* Short name used for netif in lwIP */
73*97dc5e69SMatthias Ringwald #define IFNAME0 'b'
74*97dc5e69SMatthias Ringwald #define IFNAME1 't'
75*97dc5e69SMatthias Ringwald 
76*97dc5e69SMatthias Ringwald #define LWIP_TIMER_INTERVAL_MS 25
77*97dc5e69SMatthias Ringwald 
78*97dc5e69SMatthias Ringwald static void bnep_lwip_outgoing_process(void * arg);
79*97dc5e69SMatthias Ringwald 
80*97dc5e69SMatthias Ringwald // lwip data
81*97dc5e69SMatthias Ringwald static struct netif btstack_netif;
82*97dc5e69SMatthias Ringwald 
83*97dc5e69SMatthias Ringwald // outgoing queue
84*97dc5e69SMatthias Ringwald #if NO_SYS
85*97dc5e69SMatthias Ringwald static uint8_t bnep_lwip_outgoing_queue_storage[ (TCP_SND_QUEUELEN+1) * sizeof(struct pbuf *)];
86*97dc5e69SMatthias Ringwald static btstack_ring_buffer_t bnep_lwip_outgoing_queue;
87*97dc5e69SMatthias Ringwald #else
88*97dc5e69SMatthias Ringwald static QueueHandle_t bnep_lwip_outgoing_queue;
89*97dc5e69SMatthias Ringwald #endif
90*97dc5e69SMatthias Ringwald 
91*97dc5e69SMatthias Ringwald 
92*97dc5e69SMatthias Ringwald // bnep data
93*97dc5e69SMatthias Ringwald static uint16_t  bnep_cid;
94*97dc5e69SMatthias Ringwald static btstack_timer_source_t   bnep_lwip_timer;
95*97dc5e69SMatthias Ringwald static btstack_packet_handler_t client_handler;
96*97dc5e69SMatthias Ringwald 
97*97dc5e69SMatthias Ringwald // next packet only modified from btstack context
98*97dc5e69SMatthias Ringwald static struct pbuf * bnep_lwip_outgoing_next_packet;
99*97dc5e69SMatthias Ringwald 
100*97dc5e69SMatthias Ringwald // temp buffer to unchain buffer
101*97dc5e69SMatthias Ringwald static uint8_t btstack_network_outgoing_buffer[HCI_ACL_PAYLOAD_SIZE];
102*97dc5e69SMatthias Ringwald 
103*97dc5e69SMatthias Ringwald /// lwIP functions
104*97dc5e69SMatthias Ringwald 
105*97dc5e69SMatthias Ringwald /**
106*97dc5e69SMatthias Ringwald  * This function should do the actual transmission of the packet. The packet is
107*97dc5e69SMatthias Ringwald  * contained in the pbuf that is passed to the function. This pbuf
108*97dc5e69SMatthias Ringwald  * might be chained.
109*97dc5e69SMatthias Ringwald  *
110*97dc5e69SMatthias Ringwald  * @param netif the lwip network interface structure
111*97dc5e69SMatthias Ringwald  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
112*97dc5e69SMatthias Ringwald  * @return ERR_OK if the packet could be sent
113*97dc5e69SMatthias Ringwald  *         an err_t value if the packet couldn't be sent
114*97dc5e69SMatthias Ringwald  *
115*97dc5e69SMatthias Ringwald  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
116*97dc5e69SMatthias Ringwald  *       strange results. You might consider waiting for space in the DMA queue
117*97dc5e69SMatthias Ringwald  *       to become availale since the stack doesn't retry to send a packet
118*97dc5e69SMatthias Ringwald  *       dropped because of memory failure (except for the TCP timers).
119*97dc5e69SMatthias Ringwald  */
120*97dc5e69SMatthias Ringwald static err_t low_level_output( struct netif *netif, struct pbuf *p ){
121*97dc5e69SMatthias Ringwald     UNUSED(netif);
122*97dc5e69SMatthias Ringwald 
123*97dc5e69SMatthias Ringwald     log_info("low_level_output: queue %p, len %u, total len %u", p, p->len, p->tot_len);
124*97dc5e69SMatthias Ringwald 
125*97dc5e69SMatthias Ringwald 
126*97dc5e69SMatthias Ringwald     // bnep up?
127*97dc5e69SMatthias Ringwald     if (bnep_cid == 0) return ERR_OK;
128*97dc5e69SMatthias Ringwald 
129*97dc5e69SMatthias Ringwald     // inc refcount
130*97dc5e69SMatthias Ringwald     pbuf_ref( p );
131*97dc5e69SMatthias Ringwald 
132*97dc5e69SMatthias Ringwald #if NO_SYS
133*97dc5e69SMatthias Ringwald     // queue up
134*97dc5e69SMatthias Ringwald     void * pointer = (void * ) p;
135*97dc5e69SMatthias Ringwald     btstack_ring_buffer_write(&bnep_lwip_outgoing_queue, (uint8_t *) &pointer, sizeof(struct pbuf *));
136*97dc5e69SMatthias Ringwald 
137*97dc5e69SMatthias Ringwald     // trigger (might be new packet)
138*97dc5e69SMatthias Ringwald     bnep_lwip_outgoing_process(NULL);
139*97dc5e69SMatthias Ringwald 
140*97dc5e69SMatthias Ringwald #else
141*97dc5e69SMatthias Ringwald     // queue up
142*97dc5e69SMatthias Ringwald     xQueueSendToBack(bnep_lwip_outgoing_queue, &p, portMAX_DELAY);
143*97dc5e69SMatthias Ringwald 
144*97dc5e69SMatthias Ringwald     // trigger (might be new packet)
145*97dc5e69SMatthias Ringwald     btstack_run_loop_freertos_execute_code_on_main_thread(&bnep_lwip_outgoing_process, NULL);
146*97dc5e69SMatthias Ringwald #endif
147*97dc5e69SMatthias Ringwald 
148*97dc5e69SMatthias Ringwald     return (err_t) ERR_OK;
149*97dc5e69SMatthias Ringwald }
150*97dc5e69SMatthias Ringwald 
151*97dc5e69SMatthias Ringwald /**
152*97dc5e69SMatthias Ringwald  * Should be called at the beginning of the program to set up the
153*97dc5e69SMatthias Ringwald  * network interface. It calls the function low_level_init() to do the
154*97dc5e69SMatthias Ringwald  * actual setup of the hardware.
155*97dc5e69SMatthias Ringwald  *
156*97dc5e69SMatthias Ringwald  * This function should be passed as a parameter to netif_add().
157*97dc5e69SMatthias Ringwald  *
158*97dc5e69SMatthias Ringwald  * @param netif the lwip network interface structure for this ethernetif
159*97dc5e69SMatthias Ringwald  * @return ERR_OK if the loopif is initialized
160*97dc5e69SMatthias Ringwald  *         ERR_MEM if private data couldn't be allocated
161*97dc5e69SMatthias Ringwald  *         any other err_t on error
162*97dc5e69SMatthias Ringwald  */
163*97dc5e69SMatthias Ringwald 
164*97dc5e69SMatthias Ringwald static err_t bnep_lwip_netif_init(struct netif *netif){
165*97dc5e69SMatthias Ringwald 
166*97dc5e69SMatthias Ringwald     // interface short name
167*97dc5e69SMatthias Ringwald     netif->name[0] = IFNAME0;
168*97dc5e69SMatthias Ringwald     netif->name[1] = IFNAME1;
169*97dc5e69SMatthias Ringwald 
170*97dc5e69SMatthias Ringwald     // mtu
171*97dc5e69SMatthias Ringwald     netif->mtu = 1600;
172*97dc5e69SMatthias Ringwald 
173*97dc5e69SMatthias Ringwald     /* device capabilities */
174*97dc5e69SMatthias Ringwald     netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
175*97dc5e69SMatthias Ringwald 
176*97dc5e69SMatthias Ringwald     /* We directly use etharp_output() here to save a function call.
177*97dc5e69SMatthias Ringwald      * You can instead declare your own function an call etharp_output()
178*97dc5e69SMatthias Ringwald      * from it if you have to do some checks before sending (e.g. if link
179*97dc5e69SMatthias Ringwald      * is available...)
180*97dc5e69SMatthias Ringwald      */
181*97dc5e69SMatthias Ringwald     netif->output = etharp_output;
182*97dc5e69SMatthias Ringwald #if LWIP_IPV6
183*97dc5e69SMatthias Ringwald     netif->output_ip6 = ethip6_output;
184*97dc5e69SMatthias Ringwald #endif
185*97dc5e69SMatthias Ringwald     netif->linkoutput = low_level_output;
186*97dc5e69SMatthias Ringwald 
187*97dc5e69SMatthias Ringwald     return ERR_OK;
188*97dc5e69SMatthias Ringwald }
189*97dc5e69SMatthias Ringwald 
190*97dc5e69SMatthias Ringwald static int bnep_lwip_netif_up(bd_addr_t network_address){
191*97dc5e69SMatthias Ringwald     log_info("bnep_lwip_netif_up start addr %s", bd_addr_to_str(network_address));
192*97dc5e69SMatthias Ringwald 
193*97dc5e69SMatthias Ringwald     // set mac address
194*97dc5e69SMatthias Ringwald     btstack_netif.hwaddr_len = 6;
195*97dc5e69SMatthias Ringwald     memcpy(btstack_netif.hwaddr, network_address, 6);
196*97dc5e69SMatthias Ringwald 
197*97dc5e69SMatthias Ringwald     // link is up
198*97dc5e69SMatthias Ringwald     btstack_netif.flags |= NETIF_FLAG_LINK_UP;
199*97dc5e69SMatthias Ringwald 
200*97dc5e69SMatthias Ringwald     // if up
201*97dc5e69SMatthias Ringwald     netif_set_up(&btstack_netif);
202*97dc5e69SMatthias Ringwald 
203*97dc5e69SMatthias Ringwald     return 0;
204*97dc5e69SMatthias Ringwald }
205*97dc5e69SMatthias Ringwald 
206*97dc5e69SMatthias Ringwald /**
207*97dc5e69SMatthias Ringwald  * @brief Bring up network interfacd
208*97dc5e69SMatthias Ringwald  * @param network_address
209*97dc5e69SMatthias Ringwald  * @return 0 if ok
210*97dc5e69SMatthias Ringwald  */
211*97dc5e69SMatthias Ringwald static int bnep_lwip_netif_down(void){
212*97dc5e69SMatthias Ringwald     log_info("bnep_lwip_netif_down");
213*97dc5e69SMatthias Ringwald 
214*97dc5e69SMatthias Ringwald     // link is down
215*97dc5e69SMatthias Ringwald     btstack_netif.flags &= ~NETIF_FLAG_LINK_UP;
216*97dc5e69SMatthias Ringwald 
217*97dc5e69SMatthias Ringwald     netif_set_down(&btstack_netif);
218*97dc5e69SMatthias Ringwald     return 0;
219*97dc5e69SMatthias Ringwald }
220*97dc5e69SMatthias Ringwald 
221*97dc5e69SMatthias Ringwald /**
222*97dc5e69SMatthias Ringwald  * @brief Forward packet to TCP/IP stack
223*97dc5e69SMatthias Ringwald  * @param packet
224*97dc5e69SMatthias Ringwald  * @param size
225*97dc5e69SMatthias Ringwald  */
226*97dc5e69SMatthias Ringwald static void bnep_lwip_netif_process_packet(const uint8_t * packet, uint16_t size){
227*97dc5e69SMatthias Ringwald 
228*97dc5e69SMatthias Ringwald     /* We allocate a pbuf chain of pbufs from the pool. */
229*97dc5e69SMatthias Ringwald     struct pbuf * p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL);
230*97dc5e69SMatthias Ringwald     log_debug("bnep_lwip_netif_process_packet, pbuf_alloc = %p", p);
231*97dc5e69SMatthias Ringwald 
232*97dc5e69SMatthias Ringwald     if (!p) return;
233*97dc5e69SMatthias Ringwald 
234*97dc5e69SMatthias Ringwald     /* store packet in pbuf chain */
235*97dc5e69SMatthias Ringwald     struct pbuf * q = p;
236*97dc5e69SMatthias Ringwald     while (q != NULL && size){
237*97dc5e69SMatthias Ringwald         memcpy(q->payload, packet, q->len);
238*97dc5e69SMatthias Ringwald         packet += q->len;
239*97dc5e69SMatthias Ringwald         size   -= q->len;
240*97dc5e69SMatthias Ringwald         q = q->next;
241*97dc5e69SMatthias Ringwald     }
242*97dc5e69SMatthias Ringwald 
243*97dc5e69SMatthias Ringwald     if (size != 0){
244*97dc5e69SMatthias Ringwald         log_error("failed to copy data into pbuf");
245*97dc5e69SMatthias Ringwald         pbuf_free(p);
246*97dc5e69SMatthias Ringwald         return;
247*97dc5e69SMatthias Ringwald     }
248*97dc5e69SMatthias Ringwald 
249*97dc5e69SMatthias Ringwald     /* pass all packets to ethernet_input, which decides what packets it supports */
250*97dc5e69SMatthias Ringwald     if (btstack_netif.input(p, &btstack_netif) != ERR_OK){
251*97dc5e69SMatthias Ringwald         log_error("bnep_lwip_netif_process_packet: IP input error\n");
252*97dc5e69SMatthias Ringwald         pbuf_free(p);
253*97dc5e69SMatthias Ringwald         p = NULL;
254*97dc5e69SMatthias Ringwald     }
255*97dc5e69SMatthias Ringwald }
256*97dc5e69SMatthias Ringwald 
257*97dc5e69SMatthias Ringwald 
258*97dc5e69SMatthias Ringwald 
259*97dc5e69SMatthias Ringwald // BNEP Functions & Handler
260*97dc5e69SMatthias Ringwald 
261*97dc5e69SMatthias Ringwald static void bnep_lwip_outgoing_process(void * arg){
262*97dc5e69SMatthias Ringwald     UNUSED(arg);
263*97dc5e69SMatthias Ringwald 
264*97dc5e69SMatthias Ringwald     // previous packet not sent yet
265*97dc5e69SMatthias Ringwald     if (bnep_lwip_outgoing_next_packet) return;
266*97dc5e69SMatthias Ringwald 
267*97dc5e69SMatthias Ringwald     // get new pbuf to send
268*97dc5e69SMatthias Ringwald #if NO_SYS
269*97dc5e69SMatthias Ringwald     uint32_t bytes_read = 0;
270*97dc5e69SMatthias Ringwald     void * pointer = NULL;
271*97dc5e69SMatthias Ringwald     btstack_ring_buffer_read(&bnep_lwip_outgoing_queue, (uint8_t *) &pointer, sizeof(struct pbuf *), &bytes_read);
272*97dc5e69SMatthias Ringwald     (void) bytes_read;
273*97dc5e69SMatthias Ringwald     bnep_lwip_outgoing_next_packet = pointer;
274*97dc5e69SMatthias Ringwald #else
275*97dc5e69SMatthias Ringwald     xQueueReceive(bnep_lwip_outgoing_queue, &bnep_lwip_outgoing_next_packet, portMAX_DELAY);
276*97dc5e69SMatthias Ringwald #endif
277*97dc5e69SMatthias Ringwald 
278*97dc5e69SMatthias Ringwald     log_info("bnep_lwip_outgoing_process send %p", bnep_lwip_outgoing_next_packet);
279*97dc5e69SMatthias Ringwald 
280*97dc5e69SMatthias Ringwald     // request can send now
281*97dc5e69SMatthias Ringwald     bnep_request_can_send_now_event(bnep_cid);
282*97dc5e69SMatthias Ringwald }
283*97dc5e69SMatthias Ringwald 
284*97dc5e69SMatthias Ringwald static void bnep_lwip_timeout_handler(btstack_timer_source_t * ts){
285*97dc5e69SMatthias Ringwald 
286*97dc5e69SMatthias Ringwald     // process lwIP timers
287*97dc5e69SMatthias Ringwald     sys_check_timeouts();
288*97dc5e69SMatthias Ringwald 
289*97dc5e69SMatthias Ringwald     // check if link is still up
290*97dc5e69SMatthias Ringwald     if ((btstack_netif.flags & NETIF_FLAG_LINK_UP) == 0) return;
291*97dc5e69SMatthias Ringwald 
292*97dc5e69SMatthias Ringwald     // restart timer
293*97dc5e69SMatthias Ringwald     btstack_run_loop_set_timer(ts, LWIP_TIMER_INTERVAL_MS);
294*97dc5e69SMatthias Ringwald     btstack_run_loop_add_timer(ts);
295*97dc5e69SMatthias Ringwald }
296*97dc5e69SMatthias Ringwald 
297*97dc5e69SMatthias Ringwald static void bnep_lwip_send_packet(void){
298*97dc5e69SMatthias Ringwald     if (bnep_lwip_outgoing_next_packet == NULL){
299*97dc5e69SMatthias Ringwald         log_error("CAN SEND NOW, but now packet queued");
300*97dc5e69SMatthias Ringwald     }
301*97dc5e69SMatthias Ringwald 
302*97dc5e69SMatthias Ringwald     // flatten into our buffer
303*97dc5e69SMatthias Ringwald     uint32_t len = btstack_min(sizeof(btstack_network_outgoing_buffer), bnep_lwip_outgoing_next_packet->tot_len);
304*97dc5e69SMatthias Ringwald     pbuf_copy_partial(bnep_lwip_outgoing_next_packet, btstack_network_outgoing_buffer, len, 0);
305*97dc5e69SMatthias Ringwald     bnep_send(bnep_cid, (uint8_t*) btstack_network_outgoing_buffer, len);
306*97dc5e69SMatthias Ringwald }
307*97dc5e69SMatthias Ringwald 
308*97dc5e69SMatthias Ringwald static void bnep_lwip_outgoing_packet_processed(void){
309*97dc5e69SMatthias Ringwald #if NO_SYS
310*97dc5e69SMatthias Ringwald     // release buffer / decrease refcount
311*97dc5e69SMatthias Ringwald     pbuf_free(bnep_lwip_outgoing_next_packet);
312*97dc5e69SMatthias Ringwald  #else
313*97dc5e69SMatthias Ringwald     // release buffer / decrease refcount
314*97dc5e69SMatthias Ringwald     pbuf_free_callback(bnep_lwip_outgoing_next_packet);
315*97dc5e69SMatthias Ringwald #endif
316*97dc5e69SMatthias Ringwald     // mark as done
317*97dc5e69SMatthias Ringwald     bnep_lwip_outgoing_next_packet = NULL;
318*97dc5e69SMatthias Ringwald }
319*97dc5e69SMatthias Ringwald 
320*97dc5e69SMatthias Ringwald static int bnep_lwip_outgoing_packets_empty(void){
321*97dc5e69SMatthias Ringwald #if NO_SYS
322*97dc5e69SMatthias Ringwald     return btstack_ring_buffer_empty(&bnep_lwip_outgoing_queue);
323*97dc5e69SMatthias Ringwald  #else
324*97dc5e69SMatthias Ringwald     return uxQueueMessagesWaiting(bnep_lwip_outgoing_queue) == 0;
325*97dc5e69SMatthias Ringwald #endif
326*97dc5e69SMatthias Ringwald }
327*97dc5e69SMatthias Ringwald 
328*97dc5e69SMatthias Ringwald static void bnep_lwip_trigger_outgoing_process(void){
329*97dc5e69SMatthias Ringwald #if NO_SYS
330*97dc5e69SMatthias Ringwald     bnep_lwip_outgoing_process(NULL);
331*97dc5e69SMatthias Ringwald #else
332*97dc5e69SMatthias Ringwald     btstack_run_loop_freertos_execute_code_on_main_thread(&bnep_lwip_outgoing_process, NULL);
333*97dc5e69SMatthias Ringwald #endif
334*97dc5e69SMatthias Ringwald }
335*97dc5e69SMatthias Ringwald 
336*97dc5e69SMatthias Ringwald static void bnep_lwip_packet_sent(void){
337*97dc5e69SMatthias Ringwald     log_debug("bnep_lwip_packet_sent: %p", bnep_lwip_outgoing_next_packet);
338*97dc5e69SMatthias Ringwald 
339*97dc5e69SMatthias Ringwald     // release current packet
340*97dc5e69SMatthias Ringwald     bnep_lwip_outgoing_packet_processed();
341*97dc5e69SMatthias Ringwald 
342*97dc5e69SMatthias Ringwald     // more ?
343*97dc5e69SMatthias Ringwald     if (bnep_lwip_outgoing_packets_empty()) return;
344*97dc5e69SMatthias Ringwald     bnep_lwip_trigger_outgoing_process();
345*97dc5e69SMatthias Ringwald }
346*97dc5e69SMatthias Ringwald 
347*97dc5e69SMatthias Ringwald static void bnep_lwip_discard_packets(void){
348*97dc5e69SMatthias Ringwald     // discard current packet
349*97dc5e69SMatthias Ringwald     if (bnep_lwip_outgoing_next_packet){
350*97dc5e69SMatthias Ringwald         bnep_lwip_outgoing_packet_processed();
351*97dc5e69SMatthias Ringwald     }
352*97dc5e69SMatthias Ringwald 
353*97dc5e69SMatthias Ringwald     // reset queue
354*97dc5e69SMatthias Ringwald #if NO_SYS
355*97dc5e69SMatthias Ringwald     btstack_ring_buffer_init(&bnep_lwip_outgoing_queue, bnep_lwip_outgoing_queue_storage, sizeof(bnep_lwip_outgoing_queue_storage));
356*97dc5e69SMatthias Ringwald #else
357*97dc5e69SMatthias Ringwald     xQueueReset(bnep_lwip_outgoing_queue);
358*97dc5e69SMatthias Ringwald #endif
359*97dc5e69SMatthias Ringwald }
360*97dc5e69SMatthias Ringwald 
361*97dc5e69SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
362*97dc5e69SMatthias Ringwald {
363*97dc5e69SMatthias Ringwald /* LISTING_PAUSE */
364*97dc5e69SMatthias Ringwald     UNUSED(channel);
365*97dc5e69SMatthias Ringwald 
366*97dc5e69SMatthias Ringwald     bd_addr_t local_addr;
367*97dc5e69SMatthias Ringwald 
368*97dc5e69SMatthias Ringwald     switch (packet_type) {
369*97dc5e69SMatthias Ringwald         case HCI_EVENT_PACKET:
370*97dc5e69SMatthias Ringwald             switch (hci_event_packet_get_type(packet)) {
371*97dc5e69SMatthias Ringwald 
372*97dc5e69SMatthias Ringwald                 /* @text BNEP_EVENT_CHANNEL_OPENED is received after a BNEP connection was established or
373*97dc5e69SMatthias Ringwald                  * or when the connection fails. The status field returns the error code.
374*97dc5e69SMatthias Ringwald                  *
375*97dc5e69SMatthias Ringwald                  * The TAP network interface is then configured. A data source is set up and registered with the
376*97dc5e69SMatthias Ringwald                  * run loop to receive Ethernet packets from the TAP interface.
377*97dc5e69SMatthias Ringwald                  *
378*97dc5e69SMatthias Ringwald                  * The event contains both the source and destination UUIDs, as well as the MTU for this connection and
379*97dc5e69SMatthias Ringwald                  * the BNEP Channel ID, which is used for sending Ethernet packets over BNEP.
380*97dc5e69SMatthias Ringwald                  */
381*97dc5e69SMatthias Ringwald                 case BNEP_EVENT_CHANNEL_OPENED:
382*97dc5e69SMatthias Ringwald                     if (bnep_event_channel_opened_get_status(packet) != 0) break;
383*97dc5e69SMatthias Ringwald 
384*97dc5e69SMatthias Ringwald                     bnep_cid = bnep_event_channel_opened_get_bnep_cid(packet);
385*97dc5e69SMatthias Ringwald 
386*97dc5e69SMatthias Ringwald                     /* Setup network interface */
387*97dc5e69SMatthias Ringwald                     gap_local_bd_addr(local_addr);
388*97dc5e69SMatthias Ringwald                     bnep_lwip_netif_up(local_addr);
389*97dc5e69SMatthias Ringwald 
390*97dc5e69SMatthias Ringwald #if NO_SYS
391*97dc5e69SMatthias Ringwald                     // start timer
392*97dc5e69SMatthias Ringwald                     btstack_run_loop_set_timer_handler(&bnep_lwip_timer, bnep_lwip_timeout_handler);
393*97dc5e69SMatthias Ringwald                     btstack_run_loop_set_timer(&bnep_lwip_timer, LWIP_TIMER_INTERVAL_MS);
394*97dc5e69SMatthias Ringwald                     btstack_run_loop_add_timer(&bnep_lwip_timer);
395*97dc5e69SMatthias Ringwald #endif
396*97dc5e69SMatthias Ringwald                     break;
397*97dc5e69SMatthias Ringwald 
398*97dc5e69SMatthias Ringwald                 /* @text BNEP_EVENT_CHANNEL_CLOSED is received when the connection gets closed.
399*97dc5e69SMatthias Ringwald                  */
400*97dc5e69SMatthias Ringwald                 case BNEP_EVENT_CHANNEL_CLOSED:
401*97dc5e69SMatthias Ringwald                     bnep_cid = 0;
402*97dc5e69SMatthias Ringwald                     bnep_lwip_discard_packets();
403*97dc5e69SMatthias Ringwald 
404*97dc5e69SMatthias Ringwald                     // Mark Link as Down
405*97dc5e69SMatthias Ringwald                     bnep_lwip_netif_down();
406*97dc5e69SMatthias Ringwald                     break;
407*97dc5e69SMatthias Ringwald 
408*97dc5e69SMatthias Ringwald                 /* @text BNEP_EVENT_CAN_SEND_NOW indicates that a new packet can be send. This triggers the send of a
409*97dc5e69SMatthias Ringwald                  * stored network packet. The tap datas source can be enabled again
410*97dc5e69SMatthias Ringwald                  */
411*97dc5e69SMatthias Ringwald                 case BNEP_EVENT_CAN_SEND_NOW:
412*97dc5e69SMatthias Ringwald                     bnep_lwip_send_packet();
413*97dc5e69SMatthias Ringwald                     bnep_lwip_packet_sent();
414*97dc5e69SMatthias Ringwald                     break;
415*97dc5e69SMatthias Ringwald 
416*97dc5e69SMatthias Ringwald                 default:
417*97dc5e69SMatthias Ringwald                     break;
418*97dc5e69SMatthias Ringwald             }
419*97dc5e69SMatthias Ringwald             break;
420*97dc5e69SMatthias Ringwald 
421*97dc5e69SMatthias Ringwald         /* @text Ethernet packets from the remote device are received in the packet handler with type BNEP_DATA_PACKET.
422*97dc5e69SMatthias Ringwald          * It is forwarded to the TAP interface.
423*97dc5e69SMatthias Ringwald          */
424*97dc5e69SMatthias Ringwald         case BNEP_DATA_PACKET:
425*97dc5e69SMatthias Ringwald             if (bnep_cid == 0) break;
426*97dc5e69SMatthias Ringwald             // Write out the ethernet frame to the network interface
427*97dc5e69SMatthias Ringwald             bnep_lwip_netif_process_packet(packet, size);
428*97dc5e69SMatthias Ringwald             break;
429*97dc5e69SMatthias Ringwald 
430*97dc5e69SMatthias Ringwald         default:
431*97dc5e69SMatthias Ringwald             break;
432*97dc5e69SMatthias Ringwald     }
433*97dc5e69SMatthias Ringwald 
434*97dc5e69SMatthias Ringwald     // forward to app
435*97dc5e69SMatthias Ringwald     if (!client_handler) return;
436*97dc5e69SMatthias Ringwald     (*client_handler)(packet_type, channel, packet, size);
437*97dc5e69SMatthias Ringwald }
438*97dc5e69SMatthias Ringwald 
439*97dc5e69SMatthias Ringwald /// API
440*97dc5e69SMatthias Ringwald 
441*97dc5e69SMatthias Ringwald /**
442*97dc5e69SMatthias Ringwald  * @brief Initialize network interface
443*97dc5e69SMatthias Ringwald  * @param send_packet_callback
444*97dc5e69SMatthias Ringwald  */
445*97dc5e69SMatthias Ringwald void bnep_lwip_init(void){
446*97dc5e69SMatthias Ringwald 
447*97dc5e69SMatthias Ringwald     // set up outgoing queue
448*97dc5e69SMatthias Ringwald #if NO_SYS
449*97dc5e69SMatthias Ringwald     btstack_ring_buffer_init(&bnep_lwip_outgoing_queue, bnep_lwip_outgoing_queue_storage, sizeof(bnep_lwip_outgoing_queue_storage));
450*97dc5e69SMatthias Ringwald #else
451*97dc5e69SMatthias Ringwald     bnep_lwip_outgoing_queue = xQueueCreate(TCP_SND_QUEUELEN, sizeof(struct pbuf *));
452*97dc5e69SMatthias Ringwald     if (bnep_lwip_outgoing_queue == NULL){
453*97dc5e69SMatthias Ringwald         log_error("cannot allocate outgoing queue");
454*97dc5e69SMatthias Ringwald         return;
455*97dc5e69SMatthias Ringwald     }
456*97dc5e69SMatthias Ringwald #endif
457*97dc5e69SMatthias Ringwald 
458*97dc5e69SMatthias Ringwald     ip4_addr_t fsl_netif0_ipaddr, fsl_netif0_netmask, fsl_netif0_gw;
459*97dc5e69SMatthias Ringwald 
460*97dc5e69SMatthias Ringwald #if 0
461*97dc5e69SMatthias Ringwald     // when using DHCP Client, no address
462*97dc5e69SMatthias Ringwald     IP4_ADDR(&fsl_netif0_ipaddr, 0U, 0U, 0U, 0U);
463*97dc5e69SMatthias Ringwald     IP4_ADDR(&fsl_netif0_netmask, 0U, 0U, 0U, 0U);
464*97dc5e69SMatthias Ringwald #else
465*97dc5e69SMatthias Ringwald     // when playing DHCP Server, set address
466*97dc5e69SMatthias Ringwald     IP4_ADDR(&fsl_netif0_ipaddr, 192U, 168U, 7U, 1U);
467*97dc5e69SMatthias Ringwald     IP4_ADDR(&fsl_netif0_netmask, 255U, 255U, 255U, 0U);
468*97dc5e69SMatthias Ringwald #endif
469*97dc5e69SMatthias Ringwald     IP4_ADDR(&fsl_netif0_gw, 0U, 0U, 0U, 0U);
470*97dc5e69SMatthias Ringwald 
471*97dc5e69SMatthias Ringwald     // input function differs for sys vs nosys
472*97dc5e69SMatthias Ringwald     netif_input_fn input_function;
473*97dc5e69SMatthias Ringwald #if NO_SYS
474*97dc5e69SMatthias Ringwald     input_function = ethernet_input;
475*97dc5e69SMatthias Ringwald #else
476*97dc5e69SMatthias Ringwald     input_function = tcpip_input;
477*97dc5e69SMatthias Ringwald #endif
478*97dc5e69SMatthias Ringwald 
479*97dc5e69SMatthias Ringwald     netif_add(&btstack_netif, &fsl_netif0_ipaddr, &fsl_netif0_netmask, &fsl_netif0_gw, NULL, bnep_lwip_netif_init, input_function);
480*97dc5e69SMatthias Ringwald     netif_set_default(&btstack_netif);
481*97dc5e69SMatthias Ringwald }
482*97dc5e69SMatthias Ringwald 
483*97dc5e69SMatthias Ringwald /**
484*97dc5e69SMatthias Ringwald  * @brief Register packet handler for BNEP events
485*97dc5e69SMatthias Ringwald  */
486*97dc5e69SMatthias Ringwald void bnep_lwip_register_packet_handler(btstack_packet_handler_t handler){
487*97dc5e69SMatthias Ringwald     client_handler = handler;
488*97dc5e69SMatthias Ringwald }
489*97dc5e69SMatthias Ringwald 
490*97dc5e69SMatthias Ringwald /**
491*97dc5e69SMatthias Ringwald  * @brief Register BNEP service
492*97dc5e69SMatthias Ringwald  * @brief Same as benp_register_service, but bnep lwip adapter handles all events
493*97dc5e69SMatthias Ringwald  * @param service_uuid
494*97dc5e69SMatthias Ringwald  * @Param max_frame_size
495*97dc5e69SMatthias Ringwald  */
496*97dc5e69SMatthias Ringwald uint8_t bnep_lwip_register_service(uint16_t service_uuid, uint16_t max_frame_size){
497*97dc5e69SMatthias Ringwald     return bnep_register_service(packet_handler, service_uuid, max_frame_size);
498*97dc5e69SMatthias Ringwald }
499