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