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