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 2397dc5e69SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 2497dc5e69SMatthias Ringwald * RINGWALD 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 // ***************************************************************************** 4197dc5e69SMatthias Ringwald /* EXAMPLE_START(pan_lwip_http_server): PAN - HTTP Server using lwIP 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> 61*fa8f6facSMatthias 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" 70*fa8f6facSMatthias Ringwald #include "lwip/apps/fs.h" 7197dc5e69SMatthias Ringwald #include "lwip/apps/httpd.h" 7297dc5e69SMatthias Ringwald #include "dhserver.h" 7397dc5e69SMatthias Ringwald 74*fa8f6facSMatthias Ringwald #if !LWIP_HTTPD_CUSTOM_FILES 75*fa8f6facSMatthias Ringwald #error This needs LWIP_HTTPD_CUSTOM_FILES 76*fa8f6facSMatthias Ringwald #endif 77*fa8f6facSMatthias Ringwald #if !LWIP_HTTPD_DYNAMIC_HEADERS 78*fa8f6facSMatthias Ringwald #error This needs LWIP_HTTPD_DYNAMIC_HEADERS 79*fa8f6facSMatthias Ringwald #endif 80*fa8f6facSMatthias Ringwald 8197dc5e69SMatthias Ringwald // network types 8297dc5e69SMatthias Ringwald #define NETWORK_TYPE_IPv4 0x0800 8397dc5e69SMatthias Ringwald #define NETWORK_TYPE_ARP 0x0806 8497dc5e69SMatthias Ringwald #define NETWORK_TYPE_IPv6 0x86DD 8597dc5e69SMatthias Ringwald 8697dc5e69SMatthias Ringwald static uint8_t pan_sdp_record[220]; 8797dc5e69SMatthias Ringwald 8897dc5e69SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 8997dc5e69SMatthias Ringwald 9097dc5e69SMatthias Ringwald /* 9197dc5e69SMatthias Ringwald * @section Packet Handler 9297dc5e69SMatthias Ringwald * 9397dc5e69SMatthias Ringwald * @text All BNEP events are handled in the platform/bnep_lwip.c BNEP-LWIP Adapter. 9497dc5e69SMatthias Ringwald * Here, we only print status information and handle pairing requests. 9597dc5e69SMatthias Ringwald */ 9697dc5e69SMatthias Ringwald 9797dc5e69SMatthias Ringwald /* LISTING_START(packetHandler): Packet Handler */ 9897dc5e69SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 9997dc5e69SMatthias Ringwald /* LISTING_PAUSE */ 10097dc5e69SMatthias Ringwald UNUSED(channel); 10197dc5e69SMatthias Ringwald UNUSED(size); 10297dc5e69SMatthias Ringwald 10397dc5e69SMatthias Ringwald bd_addr_t event_addr; 10497dc5e69SMatthias Ringwald 10597dc5e69SMatthias Ringwald switch (packet_type) { 10697dc5e69SMatthias Ringwald case HCI_EVENT_PACKET: 10797dc5e69SMatthias Ringwald switch (hci_event_packet_get_type(packet)) { 10897dc5e69SMatthias Ringwald 10997dc5e69SMatthias Ringwald case HCI_EVENT_PIN_CODE_REQUEST: 11097dc5e69SMatthias Ringwald // inform about pin code request 11197dc5e69SMatthias Ringwald printf("Pin code request - using '0000'\n"); 11297dc5e69SMatthias Ringwald hci_event_pin_code_request_get_bd_addr(packet, event_addr); 11397dc5e69SMatthias Ringwald gap_pin_code_response(event_addr, "0000"); 11497dc5e69SMatthias Ringwald break; 11597dc5e69SMatthias Ringwald 11697dc5e69SMatthias Ringwald case HCI_EVENT_USER_CONFIRMATION_REQUEST: 11797dc5e69SMatthias Ringwald // inform about user confirmation request 11897dc5e69SMatthias Ringwald printf("SSP User Confirmation Auto accept\n"); 11997dc5e69SMatthias Ringwald hci_event_user_confirmation_request_get_bd_addr(packet, event_addr); 12097dc5e69SMatthias Ringwald break; 12197dc5e69SMatthias Ringwald 12297dc5e69SMatthias Ringwald /* @text BNEP_EVENT_CHANNEL_OPENED is received after a BNEP connection was established or 12397dc5e69SMatthias Ringwald * or when the connection fails. The status field returns the error code. 12497dc5e69SMatthias Ringwald */ 12597dc5e69SMatthias Ringwald case BNEP_EVENT_CHANNEL_OPENED: 12697dc5e69SMatthias Ringwald if (bnep_event_channel_opened_get_status(packet)) { 12797dc5e69SMatthias Ringwald printf("BNEP channel open failed, status %02x\n", bnep_event_channel_opened_get_status(packet)); 12897dc5e69SMatthias Ringwald } else { 12997dc5e69SMatthias Ringwald uint16_t uuid_source = bnep_event_channel_opened_get_source_uuid(packet); 13097dc5e69SMatthias Ringwald uint16_t uuid_dest = bnep_event_channel_opened_get_destination_uuid(packet); 13197dc5e69SMatthias Ringwald uint16_t mtu = bnep_event_channel_opened_get_mtu(packet); 13297dc5e69SMatthias Ringwald bnep_event_channel_opened_get_remote_address(packet, event_addr); 13397dc5e69SMatthias 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); 13497dc5e69SMatthias Ringwald printf("Please open 'http://192.168.7.1' in your web browser: \n"); 13597dc5e69SMatthias Ringwald } 13697dc5e69SMatthias Ringwald break; 13797dc5e69SMatthias Ringwald 13897dc5e69SMatthias Ringwald /* @text BNEP_EVENT_CHANNEL_CLOSED is received when the connection gets closed. 13997dc5e69SMatthias Ringwald */ 14097dc5e69SMatthias Ringwald case BNEP_EVENT_CHANNEL_CLOSED: 14197dc5e69SMatthias Ringwald printf("BNEP channel closed\n"); 14297dc5e69SMatthias Ringwald break; 14397dc5e69SMatthias Ringwald 14497dc5e69SMatthias Ringwald default: 14597dc5e69SMatthias Ringwald break; 14697dc5e69SMatthias Ringwald } 14797dc5e69SMatthias Ringwald break; 14897dc5e69SMatthias Ringwald default: 14997dc5e69SMatthias Ringwald break; 15097dc5e69SMatthias Ringwald } 15197dc5e69SMatthias Ringwald } 15297dc5e69SMatthias Ringwald /* LISTING_END */ 15397dc5e69SMatthias Ringwald 15497dc5e69SMatthias Ringwald /* @section PAN BNEP Setup 15597dc5e69SMatthias Ringwald * 15697dc5e69SMatthias Ringwald * @text Listing PanBnepSetup shows the setup of the PAN setup 15797dc5e69SMatthias Ringwald */ 15897dc5e69SMatthias Ringwald 15997dc5e69SMatthias Ringwald /* LISTING_START(PanBnepSetup): Configure GAP, register PAN NAP servier, register PAN NA SDP record. */ 16097dc5e69SMatthias Ringwald static void pan_bnep_setup(void){ 16197dc5e69SMatthias Ringwald 16297dc5e69SMatthias Ringwald // Discoverable 16397dc5e69SMatthias Ringwald // Set local name with a template Bluetooth address, that will be automatically 16497dc5e69SMatthias Ringwald // replaced with a actual address once it is available, i.e. when BTstack boots 16597dc5e69SMatthias Ringwald // up and starts talking to a Bluetooth module. 16697dc5e69SMatthias Ringwald gap_set_local_name("PAN HTTP 00:00:00:00:00:00"); 16797dc5e69SMatthias Ringwald gap_discoverable_control(1); 16897dc5e69SMatthias Ringwald 16997dc5e69SMatthias Ringwald // register for HCI events 17097dc5e69SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 17197dc5e69SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 17297dc5e69SMatthias Ringwald 17397dc5e69SMatthias Ringwald // Initialize L2CAP 17497dc5e69SMatthias Ringwald l2cap_init(); 17597dc5e69SMatthias Ringwald 17697dc5e69SMatthias Ringwald // Initialize BNEP 17797dc5e69SMatthias Ringwald bnep_init(); 17897dc5e69SMatthias Ringwald 17997dc5e69SMatthias Ringwald // Init SDP 18097dc5e69SMatthias Ringwald sdp_init(); 18197dc5e69SMatthias Ringwald memset(pan_sdp_record, 0, sizeof(pan_sdp_record)); 18297dc5e69SMatthias Ringwald uint16_t network_packet_types[] = { NETWORK_TYPE_IPv4, NETWORK_TYPE_ARP, 0}; // 0 as end of list 18397dc5e69SMatthias Ringwald 18497dc5e69SMatthias Ringwald // NAP Network Access Type: Other, 1 MB/s 18597dc5e69SMatthias 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); 18697dc5e69SMatthias Ringwald sdp_register_service(pan_sdp_record); 18797dc5e69SMatthias Ringwald printf("SDP service record size: %u\n", de_get_len((uint8_t*) pan_sdp_record)); 18897dc5e69SMatthias Ringwald 18997dc5e69SMatthias Ringwald // Init BNEP lwIP Adapter 19097dc5e69SMatthias Ringwald bnep_lwip_init(); 19197dc5e69SMatthias Ringwald 19297dc5e69SMatthias Ringwald // Setup NAP Service via BENP lwIP adapter 19397dc5e69SMatthias Ringwald bnep_lwip_register_service(BLUETOOTH_SERVICE_CLASS_NAP, 1691); 19497dc5e69SMatthias Ringwald 19597dc5e69SMatthias Ringwald // register callback - to print state 19697dc5e69SMatthias Ringwald bnep_lwip_register_packet_handler(packet_handler); 19797dc5e69SMatthias Ringwald } 19897dc5e69SMatthias Ringwald /* LISTING_END */ 19997dc5e69SMatthias Ringwald 20097dc5e69SMatthias Ringwald 20197dc5e69SMatthias Ringwald /* @section DHCP Server Configuration 20297dc5e69SMatthias Ringwald * 20397dc5e69SMatthias Ringwald * @text Listing DhcpSetup shows the DHCP Server configuration for network 192.168.7.0/8 20497dc5e69SMatthias Ringwald */ 20597dc5e69SMatthias Ringwald 20697dc5e69SMatthias Ringwald /* LISTING_START(DhcpSetup): Setup DHCP Server with 3 entries for 192.168.7.0/8. */ 20797dc5e69SMatthias Ringwald 20897dc5e69SMatthias Ringwald #define NUM_DHCP_ENTRY 3 20997dc5e69SMatthias Ringwald 21097dc5e69SMatthias Ringwald static dhcp_entry_t entries[NUM_DHCP_ENTRY] = 21197dc5e69SMatthias Ringwald { 21297dc5e69SMatthias Ringwald /* mac ip address subnet mask lease time */ 21397dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 2}, {255, 255, 255, 0}, 24 * 60 * 60 }, 21497dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 3}, {255, 255, 255, 0}, 24 * 60 * 60 }, 21597dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 4}, {255, 255, 255, 0}, 24 * 60 * 60 } 21697dc5e69SMatthias Ringwald }; 21797dc5e69SMatthias Ringwald 21897dc5e69SMatthias Ringwald static dhcp_config_t dhcp_config = 21997dc5e69SMatthias Ringwald { 22097dc5e69SMatthias Ringwald {192, 168, 7, 1}, 67, /* server address, port */ 22197dc5e69SMatthias Ringwald {0, 0, 0, 0}, /* dns server */ 22297dc5e69SMatthias Ringwald NULL, /* dns suffix */ 22397dc5e69SMatthias Ringwald NUM_DHCP_ENTRY, /* num entry */ 22497dc5e69SMatthias Ringwald entries /* entries */ 22597dc5e69SMatthias Ringwald }; 22697dc5e69SMatthias Ringwald /* LISTING_END */ 22797dc5e69SMatthias Ringwald 22897dc5e69SMatthias Ringwald 229*fa8f6facSMatthias Ringwald /* @section Large File Download 230*fa8f6facSMatthias Ringwald * 231*fa8f6facSMatthias Ringwald * @text Listing LargeFile Shows how a configurable test file for performance tests is generated on the fly. 232*fa8f6facSMatthias Ringwald * The filename is the number of bytes to generate, e.g. /1048576.txt results in a 1MB file. 233*fa8f6facSMatthias Ringwald */ 234*fa8f6facSMatthias Ringwald 235*fa8f6facSMatthias Ringwald /* LISTING_START(LargeFile): Provide large file. */ 236*fa8f6facSMatthias Ringwald 237*fa8f6facSMatthias Ringwald int fs_open_custom(struct fs_file *file, const char *name){ 238*fa8f6facSMatthias Ringwald if (*name != '/') return 0; 239*fa8f6facSMatthias Ringwald uint32_t file_size = btstack_atoi(&name[1]); 240*fa8f6facSMatthias Ringwald if (file_size > 0) { 241*fa8f6facSMatthias Ringwald printf("Serving '%s' with %u bytes\n", name, file_size); 242*fa8f6facSMatthias Ringwald /* initialize fs_file correctly */ 243*fa8f6facSMatthias Ringwald memset(file, 0, sizeof(struct fs_file)); 244*fa8f6facSMatthias Ringwald file->len = file_size; 245*fa8f6facSMatthias Ringwald file->index = 0; 246*fa8f6facSMatthias Ringwald file->flags = FS_FILE_FLAGS_HEADER_PERSISTENT; 247*fa8f6facSMatthias Ringwald return 1; 248*fa8f6facSMatthias Ringwald } 249*fa8f6facSMatthias Ringwald return 0; 250*fa8f6facSMatthias Ringwald } 251*fa8f6facSMatthias Ringwald 252*fa8f6facSMatthias Ringwald static uint16_t cgi_buffer_fill(char * cgi_buffer, uint16_t cgi_buffer_size, uint32_t start_pos){ 253*fa8f6facSMatthias Ringwald // fill buffer with dots 254*fa8f6facSMatthias Ringwald memset(cgi_buffer, (uint8_t) '.', cgi_buffer_size); 255*fa8f6facSMatthias Ringwald uint16_t cursor = 10; 256*fa8f6facSMatthias Ringwald uint16_t pos = 0; 257*fa8f6facSMatthias Ringwald const uint16_t line_length = 64; 258*fa8f6facSMatthias Ringwald 259*fa8f6facSMatthias Ringwald while ((pos + line_length ) < cgi_buffer_size){ 260*fa8f6facSMatthias Ringwald // write position 261*fa8f6facSMatthias Ringwald sprintf((char *) &cgi_buffer[pos], "%08"PRIx32, start_pos + pos); 262*fa8f6facSMatthias Ringwald cgi_buffer[pos + 8] = '-'; 263*fa8f6facSMatthias Ringwald // cursor 264*fa8f6facSMatthias Ringwald cgi_buffer[pos+cursor] = '+'; 265*fa8f6facSMatthias Ringwald cursor++; 266*fa8f6facSMatthias Ringwald // new line 267*fa8f6facSMatthias Ringwald cgi_buffer[pos+line_length-1] = '\n'; 268*fa8f6facSMatthias Ringwald pos += line_length; 269*fa8f6facSMatthias Ringwald } 270*fa8f6facSMatthias Ringwald 271*fa8f6facSMatthias Ringwald // handle last incomplete line 272*fa8f6facSMatthias Ringwald if (pos == 0){ 273*fa8f6facSMatthias Ringwald const char * last_line_text = "Thank you for evaluating BTstack!"; 274*fa8f6facSMatthias Ringwald uint16_t bytes_to_copy = btstack_min(strlen(last_line_text), cgi_buffer_size); 275*fa8f6facSMatthias Ringwald memcpy(cgi_buffer, last_line_text, bytes_to_copy); 276*fa8f6facSMatthias Ringwald pos = cgi_buffer_size; 277*fa8f6facSMatthias Ringwald } 278*fa8f6facSMatthias Ringwald 279*fa8f6facSMatthias Ringwald return pos; 280*fa8f6facSMatthias Ringwald } 281*fa8f6facSMatthias Ringwald 282*fa8f6facSMatthias Ringwald int fs_read_custom(struct fs_file *file, char *buffer, int count) 283*fa8f6facSMatthias Ringwald { 284*fa8f6facSMatthias Ringwald uint32_t remaining_data = file->len - file->index; 285*fa8f6facSMatthias Ringwald if (remaining_data == 0) { 286*fa8f6facSMatthias Ringwald // all bytes already read 287*fa8f6facSMatthias Ringwald return FS_READ_EOF; 288*fa8f6facSMatthias Ringwald } 289*fa8f6facSMatthias Ringwald 290*fa8f6facSMatthias Ringwald uint32_t bytes_to_fill = remaining_data; 291*fa8f6facSMatthias Ringwald if (bytes_to_fill > count){ 292*fa8f6facSMatthias Ringwald bytes_to_fill = count; 293*fa8f6facSMatthias Ringwald } 294*fa8f6facSMatthias Ringwald 295*fa8f6facSMatthias Ringwald uint32_t bytes_written = cgi_buffer_fill(buffer, bytes_to_fill, file->index); 296*fa8f6facSMatthias Ringwald file->index += bytes_written; 297*fa8f6facSMatthias Ringwald 298*fa8f6facSMatthias Ringwald return bytes_written; 299*fa8f6facSMatthias Ringwald } 300*fa8f6facSMatthias Ringwald 301*fa8f6facSMatthias Ringwald void 302*fa8f6facSMatthias Ringwald fs_close_custom(struct fs_file *file){ 303*fa8f6facSMatthias Ringwald } 304*fa8f6facSMatthias Ringwald 305*fa8f6facSMatthias Ringwald /* LISTING_END */ 306*fa8f6facSMatthias Ringwald 30797dc5e69SMatthias Ringwald /* @section DHCP Server Setup 30897dc5e69SMatthias Ringwald * 30997dc5e69SMatthias Ringwald * @text Listing LwipSetup shows the setup of the lwIP network stack and starts the DHCP Server 31097dc5e69SMatthias Ringwald */ 31197dc5e69SMatthias Ringwald 31297dc5e69SMatthias Ringwald /* LISTING_START(LwipSetup): Report lwIP version, init lwIP, start DHCP Serverr */ 31397dc5e69SMatthias Ringwald 31497dc5e69SMatthias Ringwald static void network_setup(void){ 31597dc5e69SMatthias Ringwald printf("lwIP version: " LWIP_VERSION_STRING "\n"); 31697dc5e69SMatthias Ringwald 31797dc5e69SMatthias Ringwald #if BYTE_ORDER == LITTLE_ENDIAN 31897dc5e69SMatthias Ringwald // big endian detection not supported by build configuration 31997dc5e69SMatthias Ringwald if (btstack_is_big_endian()){ 32097dc5e69SMatthias Ringwald printf("lwIP configured for little endian, but running on big endian. Please set BYTE_ORDER to BIG_ENDIAN in lwiopts.h\n"); 32197dc5e69SMatthias Ringwald while (1); 32297dc5e69SMatthias Ringwald } 32397dc5e69SMatthias Ringwald #endif 32497dc5e69SMatthias Ringwald 32597dc5e69SMatthias Ringwald // init lwIP stack 3260be141aeSMatthias Ringwald #if NO_SYS 32797dc5e69SMatthias Ringwald lwip_init(); 3280be141aeSMatthias Ringwald #else 3290be141aeSMatthias Ringwald tcpip_init(NULL, NULL); 3300be141aeSMatthias Ringwald #endif 33197dc5e69SMatthias Ringwald 33297dc5e69SMatthias Ringwald // start DHCP Server 33397dc5e69SMatthias Ringwald dhserv_init(&dhcp_config); 33497dc5e69SMatthias Ringwald 33597dc5e69SMatthias Ringwald // start HTTP Server 33697dc5e69SMatthias Ringwald httpd_init(); 33797dc5e69SMatthias Ringwald } 33897dc5e69SMatthias Ringwald /* LISTING_END */ 33997dc5e69SMatthias Ringwald 34097dc5e69SMatthias Ringwald 34197dc5e69SMatthias Ringwald /* @section Main 34297dc5e69SMatthias Ringwald * 34397dc5e69SMatthias Ringwald * @text Setup the lwIP network and PAN NAP 34497dc5e69SMatthias Ringwald */ 34597dc5e69SMatthias Ringwald 34697dc5e69SMatthias Ringwald /* LISTING_START(Main): Setup lwIP network and PAN NAP */ 34797dc5e69SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 34897dc5e69SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 34997dc5e69SMatthias Ringwald 35097dc5e69SMatthias Ringwald (void)argc; 35197dc5e69SMatthias Ringwald (void)argv; 35297dc5e69SMatthias Ringwald 35397dc5e69SMatthias Ringwald // setup lwIP, HTTP, DHCP 35497dc5e69SMatthias Ringwald network_setup(); 35597dc5e69SMatthias Ringwald 35697dc5e69SMatthias Ringwald // setup Classic PAN NAP Service 35797dc5e69SMatthias Ringwald pan_bnep_setup(); 35897dc5e69SMatthias Ringwald 35997dc5e69SMatthias Ringwald // Turn on the device 36097dc5e69SMatthias Ringwald hci_power_control(HCI_POWER_ON); 36197dc5e69SMatthias Ringwald return 0; 36297dc5e69SMatthias Ringwald } 36397dc5e69SMatthias Ringwald /* LISTING_END */ 36497dc5e69SMatthias Ringwald 36597dc5e69SMatthias Ringwald /* EXAMPLE_END */ 366