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