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