197dc5e69SMatthias Ringwald /* 297dc5e69SMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 397dc5e69SMatthias Ringwald * 497dc5e69SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 597dc5e69SMatthias Ringwald * modification, are permitted provided that the following conditions 697dc5e69SMatthias Ringwald * are met: 797dc5e69SMatthias Ringwald * 897dc5e69SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 997dc5e69SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 1097dc5e69SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 1197dc5e69SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 1297dc5e69SMatthias Ringwald * documentation and/or other materials provided with the distribution. 1397dc5e69SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 1497dc5e69SMatthias Ringwald * contributors may be used to endorse or promote products derived 1597dc5e69SMatthias Ringwald * from this software without specific prior written permission. 1697dc5e69SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 1797dc5e69SMatthias Ringwald * personal benefit and not for any commercial purpose or for 1897dc5e69SMatthias Ringwald * monetary gain. 1997dc5e69SMatthias Ringwald * 2097dc5e69SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 2197dc5e69SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2297dc5e69SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2597dc5e69SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2697dc5e69SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 2797dc5e69SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2897dc5e69SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2997dc5e69SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 3097dc5e69SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3197dc5e69SMatthias Ringwald * SUCH DAMAGE. 3297dc5e69SMatthias Ringwald * 3397dc5e69SMatthias Ringwald * Please inquire about commercial licensing options at 3497dc5e69SMatthias Ringwald * [email protected] 3597dc5e69SMatthias Ringwald * 3697dc5e69SMatthias Ringwald */ 3797dc5e69SMatthias Ringwald 3897dc5e69SMatthias Ringwald #define __BTSTACK_FILE__ "pan_lwip_http_server.c" 3997dc5e69SMatthias Ringwald 4097dc5e69SMatthias Ringwald // ***************************************************************************** 41ec8ae085SMilanka Ringwald /* EXAMPLE_START(pan_lwip_http_server): PAN - lwIP HTTP and DHCP Server 4297dc5e69SMatthias Ringwald * 4397dc5e69SMatthias Ringwald * @text Bluetooth PAN is mainly used for Internet Tethering, where e.g. a mobile 4497dc5e69SMatthias Ringwald * phone provides internet connection to a laptop or a tablet. 4597dc5e69SMatthias Ringwald * 4697dc5e69SMatthias Ringwald * Instead of regular internet access, it's also possible to provide a Web app on a 4797dc5e69SMatthias Ringwald * Bluetooth device, e.g. for configuration or maintenance. For some device, 4897dc5e69SMatthias Ringwald * this can be a more effective way to provide an interface compared to dedicated 4997dc5e69SMatthias Ringwald * smartphone applications (for Android and iOS). 5097dc5e69SMatthias Ringwald * 5197dc5e69SMatthias Ringwald * Before iOS 11, accessing an HTTP server via Bluetooth PAN was not supported on 5297dc5e69SMatthias Ringwald * the iPhone, but on iPod and iPad. With iOS 11, this works as expected. 5397dc5e69SMatthias Ringwald * 5497dc5e69SMatthias Ringwald * After pairing your device, please open the URL http://192.168.7.1 in your web 5597dc5e69SMatthias Ringwald * browser. 5697dc5e69SMatthias Ringwald 5797dc5e69SMatthias Ringwald */ 5897dc5e69SMatthias Ringwald // ***************************************************************************** 5997dc5e69SMatthias Ringwald 6097dc5e69SMatthias Ringwald #include <stdio.h> 61fa8f6facSMatthias Ringwald #include <inttypes.h> 6297dc5e69SMatthias Ringwald 6397dc5e69SMatthias Ringwald #include "btstack_config.h" 6497dc5e69SMatthias Ringwald #include "bnep_lwip.h" 6597dc5e69SMatthias Ringwald #include "btstack.h" 6697dc5e69SMatthias Ringwald 6797dc5e69SMatthias Ringwald #include "lwip/init.h" 6897dc5e69SMatthias Ringwald #include "lwip/opt.h" 6997dc5e69SMatthias Ringwald #include "lwip/tcpip.h" 70fa8f6facSMatthias Ringwald #include "lwip/apps/fs.h" 7197dc5e69SMatthias Ringwald #include "lwip/apps/httpd.h" 7297dc5e69SMatthias Ringwald #include "dhserver.h" 7397dc5e69SMatthias Ringwald 74fdfba5a3SMatthias Ringwald #if defined(LWIP_HTTPD_CUSTOM_FILES) && defined(LWIP_HTTPD_DYNAMIC_HEADERS) 75fdfba5a3SMatthias Ringwald #define ENABLE_TEST_FILE_DOWNLOAD 76fdfba5a3SMatthias Ringwald #else 77fdfba5a3SMatthias Ringwald #warning "Test file download requires LWIP_HTTPD_CUSTOM_FILES and LWIP_HTTPD_DYNAMIC_HEADERS to be defined. Not supported currently." 78fa8f6facSMatthias Ringwald #endif 79fa8f6facSMatthias Ringwald 8097dc5e69SMatthias Ringwald // network types 8197dc5e69SMatthias Ringwald #define NETWORK_TYPE_IPv4 0x0800 8297dc5e69SMatthias Ringwald #define NETWORK_TYPE_ARP 0x0806 8397dc5e69SMatthias Ringwald #define NETWORK_TYPE_IPv6 0x86DD 8497dc5e69SMatthias Ringwald 8597dc5e69SMatthias Ringwald static uint8_t pan_sdp_record[220]; 8697dc5e69SMatthias Ringwald 8797dc5e69SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 8897dc5e69SMatthias Ringwald 8997dc5e69SMatthias Ringwald /* 9097dc5e69SMatthias Ringwald * @section Packet Handler 9197dc5e69SMatthias Ringwald * 9297dc5e69SMatthias Ringwald * @text All BNEP events are handled in the platform/bnep_lwip.c BNEP-LWIP Adapter. 9397dc5e69SMatthias Ringwald * Here, we only print status information and handle pairing requests. 9497dc5e69SMatthias Ringwald */ 9597dc5e69SMatthias Ringwald 9697dc5e69SMatthias Ringwald /* LISTING_START(packetHandler): Packet Handler */ 9797dc5e69SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 9897dc5e69SMatthias Ringwald /* LISTING_PAUSE */ 9997dc5e69SMatthias Ringwald UNUSED(channel); 10097dc5e69SMatthias Ringwald UNUSED(size); 10197dc5e69SMatthias Ringwald 10297dc5e69SMatthias Ringwald bd_addr_t event_addr; 10397dc5e69SMatthias Ringwald 10497dc5e69SMatthias Ringwald switch (packet_type) { 10597dc5e69SMatthias Ringwald case HCI_EVENT_PACKET: 10697dc5e69SMatthias Ringwald switch (hci_event_packet_get_type(packet)) { 10797dc5e69SMatthias Ringwald 10897dc5e69SMatthias Ringwald case HCI_EVENT_PIN_CODE_REQUEST: 10997dc5e69SMatthias Ringwald // inform about pin code request 11097dc5e69SMatthias Ringwald printf("Pin code request - using '0000'\n"); 11197dc5e69SMatthias Ringwald hci_event_pin_code_request_get_bd_addr(packet, event_addr); 11297dc5e69SMatthias Ringwald gap_pin_code_response(event_addr, "0000"); 11397dc5e69SMatthias Ringwald break; 11497dc5e69SMatthias Ringwald 11597dc5e69SMatthias Ringwald case HCI_EVENT_USER_CONFIRMATION_REQUEST: 11697dc5e69SMatthias Ringwald // inform about user confirmation request 11797dc5e69SMatthias Ringwald printf("SSP User Confirmation Auto accept\n"); 11897dc5e69SMatthias Ringwald hci_event_user_confirmation_request_get_bd_addr(packet, event_addr); 11997dc5e69SMatthias Ringwald break; 12097dc5e69SMatthias Ringwald 12197dc5e69SMatthias Ringwald /* @text BNEP_EVENT_CHANNEL_OPENED is received after a BNEP connection was established or 12297dc5e69SMatthias Ringwald * or when the connection fails. The status field returns the error code. 12397dc5e69SMatthias Ringwald */ 12497dc5e69SMatthias Ringwald case BNEP_EVENT_CHANNEL_OPENED: 12597dc5e69SMatthias Ringwald if (bnep_event_channel_opened_get_status(packet)) { 12697dc5e69SMatthias Ringwald printf("BNEP channel open failed, status %02x\n", bnep_event_channel_opened_get_status(packet)); 12797dc5e69SMatthias Ringwald } else { 12897dc5e69SMatthias Ringwald uint16_t uuid_source = bnep_event_channel_opened_get_source_uuid(packet); 12997dc5e69SMatthias Ringwald uint16_t uuid_dest = bnep_event_channel_opened_get_destination_uuid(packet); 13097dc5e69SMatthias Ringwald uint16_t mtu = bnep_event_channel_opened_get_mtu(packet); 13197dc5e69SMatthias Ringwald bnep_event_channel_opened_get_remote_address(packet, event_addr); 13297dc5e69SMatthias Ringwald printf("BNEP connection open succeeded to %s source UUID 0x%04x dest UUID: 0x%04x, max frame size %u\n", bd_addr_to_str(event_addr), uuid_source, uuid_dest, mtu); 13397dc5e69SMatthias Ringwald printf("Please open 'http://192.168.7.1' in your web browser: \n"); 13497dc5e69SMatthias Ringwald } 13597dc5e69SMatthias Ringwald break; 13697dc5e69SMatthias Ringwald 13797dc5e69SMatthias Ringwald /* @text BNEP_EVENT_CHANNEL_CLOSED is received when the connection gets closed. 13897dc5e69SMatthias Ringwald */ 13997dc5e69SMatthias Ringwald case BNEP_EVENT_CHANNEL_CLOSED: 14097dc5e69SMatthias Ringwald printf("BNEP channel closed\n"); 14197dc5e69SMatthias Ringwald break; 14297dc5e69SMatthias Ringwald 14397dc5e69SMatthias Ringwald default: 14497dc5e69SMatthias Ringwald break; 14597dc5e69SMatthias Ringwald } 14697dc5e69SMatthias Ringwald break; 14797dc5e69SMatthias Ringwald default: 14897dc5e69SMatthias Ringwald break; 14997dc5e69SMatthias Ringwald } 15097dc5e69SMatthias Ringwald } 15197dc5e69SMatthias Ringwald /* LISTING_END */ 15297dc5e69SMatthias Ringwald 15397dc5e69SMatthias Ringwald /* @section PAN BNEP Setup 15497dc5e69SMatthias Ringwald * 15597dc5e69SMatthias Ringwald * @text Listing PanBnepSetup shows the setup of the PAN setup 15697dc5e69SMatthias Ringwald */ 15797dc5e69SMatthias Ringwald 15897dc5e69SMatthias Ringwald /* LISTING_START(PanBnepSetup): Configure GAP, register PAN NAP servier, register PAN NA SDP record. */ 15997dc5e69SMatthias Ringwald static void pan_bnep_setup(void){ 16097dc5e69SMatthias Ringwald 16197dc5e69SMatthias Ringwald // Discoverable 16297dc5e69SMatthias Ringwald // Set local name with a template Bluetooth address, that will be automatically 16397dc5e69SMatthias Ringwald // replaced with a actual address once it is available, i.e. when BTstack boots 16497dc5e69SMatthias Ringwald // up and starts talking to a Bluetooth module. 16597dc5e69SMatthias Ringwald gap_set_local_name("PAN HTTP 00:00:00:00:00:00"); 16697dc5e69SMatthias Ringwald gap_discoverable_control(1); 16797dc5e69SMatthias Ringwald 168c10be05fSMatthias Ringwald // Major: Networking Device, Minor: Networ Access Point 169c10be05fSMatthias Ringwald gap_set_class_of_device(0x20300); 170c10be05fSMatthias Ringwald 17197dc5e69SMatthias Ringwald // register for HCI events 17297dc5e69SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 17397dc5e69SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 17497dc5e69SMatthias Ringwald 17597dc5e69SMatthias Ringwald // Initialize L2CAP 17697dc5e69SMatthias Ringwald l2cap_init(); 17797dc5e69SMatthias Ringwald 178*8c9bb29eSMatthias Ringwald #ifdef ENABLE_BLE 179*8c9bb29eSMatthias Ringwald // Initialize LE Security Manager. Needed for cross-transport key derivation 180*8c9bb29eSMatthias Ringwald sm_init(); 181*8c9bb29eSMatthias Ringwald #endif 182*8c9bb29eSMatthias Ringwald 18397dc5e69SMatthias Ringwald // Initialize BNEP 18497dc5e69SMatthias Ringwald bnep_init(); 18597dc5e69SMatthias Ringwald 18697dc5e69SMatthias Ringwald // Init SDP 18797dc5e69SMatthias Ringwald sdp_init(); 18897dc5e69SMatthias Ringwald memset(pan_sdp_record, 0, sizeof(pan_sdp_record)); 18997dc5e69SMatthias Ringwald uint16_t network_packet_types[] = { NETWORK_TYPE_IPv4, NETWORK_TYPE_ARP, 0}; // 0 as end of list 19097dc5e69SMatthias Ringwald 19197dc5e69SMatthias Ringwald // NAP Network Access Type: Other, 1 MB/s 19297dc5e69SMatthias Ringwald pan_create_nap_sdp_record(pan_sdp_record, sdp_create_service_record_handle(), network_packet_types, NULL, NULL, BNEP_SECURITY_NONE, PAN_NET_ACCESS_TYPE_OTHER, 1000000, NULL, NULL); 19397dc5e69SMatthias Ringwald sdp_register_service(pan_sdp_record); 19497dc5e69SMatthias Ringwald printf("SDP service record size: %u\n", de_get_len((uint8_t*) pan_sdp_record)); 19597dc5e69SMatthias Ringwald 19697dc5e69SMatthias Ringwald // Init BNEP lwIP Adapter 19797dc5e69SMatthias Ringwald bnep_lwip_init(); 19897dc5e69SMatthias Ringwald 19997dc5e69SMatthias Ringwald // Setup NAP Service via BENP lwIP adapter 20097dc5e69SMatthias Ringwald bnep_lwip_register_service(BLUETOOTH_SERVICE_CLASS_NAP, 1691); 20197dc5e69SMatthias Ringwald 20297dc5e69SMatthias Ringwald // register callback - to print state 20397dc5e69SMatthias Ringwald bnep_lwip_register_packet_handler(packet_handler); 20497dc5e69SMatthias Ringwald } 20597dc5e69SMatthias Ringwald /* LISTING_END */ 20697dc5e69SMatthias Ringwald 20797dc5e69SMatthias Ringwald 20897dc5e69SMatthias Ringwald /* @section DHCP Server Configuration 20997dc5e69SMatthias Ringwald * 21097dc5e69SMatthias Ringwald * @text Listing DhcpSetup shows the DHCP Server configuration for network 192.168.7.0/8 21197dc5e69SMatthias Ringwald */ 21297dc5e69SMatthias Ringwald 21397dc5e69SMatthias Ringwald /* LISTING_START(DhcpSetup): Setup DHCP Server with 3 entries for 192.168.7.0/8. */ 21497dc5e69SMatthias Ringwald 21597dc5e69SMatthias Ringwald #define NUM_DHCP_ENTRY 3 21697dc5e69SMatthias Ringwald 21797dc5e69SMatthias Ringwald static dhcp_entry_t entries[NUM_DHCP_ENTRY] = 21897dc5e69SMatthias Ringwald { 21997dc5e69SMatthias Ringwald /* mac ip address subnet mask lease time */ 22097dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 2}, {255, 255, 255, 0}, 24 * 60 * 60 }, 22197dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 3}, {255, 255, 255, 0}, 24 * 60 * 60 }, 22297dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 4}, {255, 255, 255, 0}, 24 * 60 * 60 } 22397dc5e69SMatthias Ringwald }; 22497dc5e69SMatthias Ringwald 22597dc5e69SMatthias Ringwald static dhcp_config_t dhcp_config = 22697dc5e69SMatthias Ringwald { 22797dc5e69SMatthias Ringwald {192, 168, 7, 1}, 67, /* server address, port */ 22897dc5e69SMatthias Ringwald {0, 0, 0, 0}, /* dns server */ 22997dc5e69SMatthias Ringwald NULL, /* dns suffix */ 23097dc5e69SMatthias Ringwald NUM_DHCP_ENTRY, /* num entry */ 23197dc5e69SMatthias Ringwald entries /* entries */ 23297dc5e69SMatthias Ringwald }; 23397dc5e69SMatthias Ringwald /* LISTING_END */ 23497dc5e69SMatthias Ringwald 235fdfba5a3SMatthias Ringwald #ifdef ENABLE_TEST_FILE_DOWNLOAD 23697dc5e69SMatthias Ringwald 237fa8f6facSMatthias Ringwald /* @section Large File Download 238fa8f6facSMatthias Ringwald * 239fa8f6facSMatthias Ringwald * @text Listing LargeFile Shows how a configurable test file for performance tests is generated on the fly. 240fa8f6facSMatthias Ringwald * The filename is the number of bytes to generate, e.g. /1048576.txt results in a 1MB file. 241fa8f6facSMatthias Ringwald */ 242fa8f6facSMatthias Ringwald 243fa8f6facSMatthias Ringwald /* LISTING_START(LargeFile): Provide large file. */ 244fa8f6facSMatthias Ringwald 2454251aeecSMatthias Ringwald int fs_open_custom(struct fs_file *file, const char *name); 246fa8f6facSMatthias Ringwald int fs_open_custom(struct fs_file *file, const char *name){ 247fa8f6facSMatthias Ringwald if (*name != '/') return 0; 248fa8f6facSMatthias Ringwald uint32_t file_size = btstack_atoi(&name[1]); 249fa8f6facSMatthias Ringwald if (file_size > 0) { 250e883851fSMatthias Ringwald printf("Serving '%s' with %"PRIu32" bytes\n", name, file_size); 251fa8f6facSMatthias Ringwald /* initialize fs_file correctly */ 252fa8f6facSMatthias Ringwald memset(file, 0, sizeof(struct fs_file)); 253fa8f6facSMatthias Ringwald file->len = file_size; 254fa8f6facSMatthias Ringwald file->index = 0; 255fa8f6facSMatthias Ringwald file->flags = FS_FILE_FLAGS_HEADER_PERSISTENT; 256fa8f6facSMatthias Ringwald return 1; 257fa8f6facSMatthias Ringwald } 258fa8f6facSMatthias Ringwald return 0; 259fa8f6facSMatthias Ringwald } 260fa8f6facSMatthias Ringwald 261fa8f6facSMatthias Ringwald static uint16_t cgi_buffer_fill(char * cgi_buffer, uint16_t cgi_buffer_size, uint32_t start_pos){ 262fa8f6facSMatthias Ringwald // fill buffer with dots 263fa8f6facSMatthias Ringwald memset(cgi_buffer, (uint8_t) '.', cgi_buffer_size); 264fa8f6facSMatthias Ringwald uint16_t cursor = 10; 265fa8f6facSMatthias Ringwald uint16_t pos = 0; 266fa8f6facSMatthias Ringwald const uint16_t line_length = 64; 267fa8f6facSMatthias Ringwald 268fa8f6facSMatthias Ringwald while ((pos + line_length ) < cgi_buffer_size){ 269fa8f6facSMatthias Ringwald // write position 270fa8f6facSMatthias Ringwald sprintf((char *) &cgi_buffer[pos], "%08"PRIx32, start_pos + pos); 271fa8f6facSMatthias Ringwald cgi_buffer[pos + 8] = '-'; 272fa8f6facSMatthias Ringwald // cursor 273fa8f6facSMatthias Ringwald cgi_buffer[pos+cursor] = '+'; 274fa8f6facSMatthias Ringwald cursor++; 275fa8f6facSMatthias Ringwald // new line 276fa8f6facSMatthias Ringwald cgi_buffer[pos+line_length-1] = '\n'; 277fa8f6facSMatthias Ringwald pos += line_length; 278fa8f6facSMatthias Ringwald } 279fa8f6facSMatthias Ringwald 280fa8f6facSMatthias Ringwald // handle last incomplete line 281fa8f6facSMatthias Ringwald if (pos == 0){ 282fa8f6facSMatthias Ringwald const char * last_line_text = "Thank you for evaluating BTstack!"; 283fa8f6facSMatthias Ringwald uint16_t bytes_to_copy = btstack_min(strlen(last_line_text), cgi_buffer_size); 284fa8f6facSMatthias Ringwald memcpy(cgi_buffer, last_line_text, bytes_to_copy); 285fa8f6facSMatthias Ringwald pos = cgi_buffer_size; 286fa8f6facSMatthias Ringwald } 287fa8f6facSMatthias Ringwald 288fa8f6facSMatthias Ringwald return pos; 289fa8f6facSMatthias Ringwald } 290fa8f6facSMatthias Ringwald 2914251aeecSMatthias Ringwald int fs_read_custom(struct fs_file *file, char *buffer, int count); 292fa8f6facSMatthias Ringwald int fs_read_custom(struct fs_file *file, char *buffer, int count) 293fa8f6facSMatthias Ringwald { 294fa8f6facSMatthias Ringwald uint32_t remaining_data = file->len - file->index; 295fa8f6facSMatthias Ringwald if (remaining_data == 0) { 296fa8f6facSMatthias Ringwald // all bytes already read 297fa8f6facSMatthias Ringwald return FS_READ_EOF; 298fa8f6facSMatthias Ringwald } 299fa8f6facSMatthias Ringwald 300fa8f6facSMatthias Ringwald uint32_t bytes_to_fill = remaining_data; 3014251aeecSMatthias Ringwald if (bytes_to_fill > (uint32_t) count){ 302fa8f6facSMatthias Ringwald bytes_to_fill = count; 303fa8f6facSMatthias Ringwald } 304fa8f6facSMatthias Ringwald 305fa8f6facSMatthias Ringwald uint32_t bytes_written = cgi_buffer_fill(buffer, bytes_to_fill, file->index); 306fa8f6facSMatthias Ringwald file->index += bytes_written; 307fa8f6facSMatthias Ringwald 308fa8f6facSMatthias Ringwald return bytes_written; 309fa8f6facSMatthias Ringwald } 310fa8f6facSMatthias Ringwald 3114251aeecSMatthias Ringwald void fs_close_custom(struct fs_file *file); 3124251aeecSMatthias Ringwald void fs_close_custom(struct fs_file *file){ 3134251aeecSMatthias Ringwald UNUSED(file); 314fa8f6facSMatthias Ringwald } 315fdfba5a3SMatthias Ringwald #endif 316fa8f6facSMatthias Ringwald /* LISTING_END */ 317fa8f6facSMatthias Ringwald 31897dc5e69SMatthias Ringwald /* @section DHCP Server Setup 31997dc5e69SMatthias Ringwald * 32097dc5e69SMatthias Ringwald * @text Listing LwipSetup shows the setup of the lwIP network stack and starts the DHCP Server 32197dc5e69SMatthias Ringwald */ 32297dc5e69SMatthias Ringwald 32397dc5e69SMatthias Ringwald /* LISTING_START(LwipSetup): Report lwIP version, init lwIP, start DHCP Serverr */ 32497dc5e69SMatthias Ringwald 32597dc5e69SMatthias Ringwald static void network_setup(void){ 32697dc5e69SMatthias Ringwald printf("lwIP version: " LWIP_VERSION_STRING "\n"); 32797dc5e69SMatthias Ringwald 32897dc5e69SMatthias Ringwald #if BYTE_ORDER == LITTLE_ENDIAN 32997dc5e69SMatthias Ringwald // big endian detection not supported by build configuration 33097dc5e69SMatthias Ringwald if (btstack_is_big_endian()){ 33197dc5e69SMatthias Ringwald printf("lwIP configured for little endian, but running on big endian. Please set BYTE_ORDER to BIG_ENDIAN in lwiopts.h\n"); 33297dc5e69SMatthias Ringwald while (1); 33397dc5e69SMatthias Ringwald } 33497dc5e69SMatthias Ringwald #endif 33597dc5e69SMatthias Ringwald 33697dc5e69SMatthias Ringwald // init lwIP stack 3370be141aeSMatthias Ringwald #if NO_SYS 33897dc5e69SMatthias Ringwald lwip_init(); 3390be141aeSMatthias Ringwald #else 3400be141aeSMatthias Ringwald tcpip_init(NULL, NULL); 3410be141aeSMatthias Ringwald #endif 34297dc5e69SMatthias Ringwald 34397dc5e69SMatthias Ringwald // start DHCP Server 34497dc5e69SMatthias Ringwald dhserv_init(&dhcp_config); 34597dc5e69SMatthias Ringwald 34697dc5e69SMatthias Ringwald // start HTTP Server 34797dc5e69SMatthias Ringwald httpd_init(); 34897dc5e69SMatthias Ringwald } 34997dc5e69SMatthias Ringwald /* LISTING_END */ 35097dc5e69SMatthias Ringwald 35197dc5e69SMatthias Ringwald 35297dc5e69SMatthias Ringwald /* @section Main 35397dc5e69SMatthias Ringwald * 35497dc5e69SMatthias Ringwald * @text Setup the lwIP network and PAN NAP 35597dc5e69SMatthias Ringwald */ 35697dc5e69SMatthias Ringwald 35797dc5e69SMatthias Ringwald /* LISTING_START(Main): Setup lwIP network and PAN NAP */ 35897dc5e69SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 35997dc5e69SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 36097dc5e69SMatthias Ringwald 36197dc5e69SMatthias Ringwald (void)argc; 36297dc5e69SMatthias Ringwald (void)argv; 36397dc5e69SMatthias Ringwald 36497dc5e69SMatthias Ringwald // setup lwIP, HTTP, DHCP 36597dc5e69SMatthias Ringwald network_setup(); 36697dc5e69SMatthias Ringwald 36797dc5e69SMatthias Ringwald // setup Classic PAN NAP Service 36897dc5e69SMatthias Ringwald pan_bnep_setup(); 36997dc5e69SMatthias Ringwald 37097dc5e69SMatthias Ringwald // Turn on the device 37197dc5e69SMatthias Ringwald hci_power_control(HCI_POWER_ON); 37297dc5e69SMatthias Ringwald return 0; 37397dc5e69SMatthias Ringwald } 37497dc5e69SMatthias Ringwald /* LISTING_END */ 37597dc5e69SMatthias Ringwald 37697dc5e69SMatthias Ringwald /* EXAMPLE_END */ 377