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> 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 74fa8f6facSMatthias Ringwald #if !LWIP_HTTPD_CUSTOM_FILES 75fa8f6facSMatthias Ringwald #error This needs LWIP_HTTPD_CUSTOM_FILES 76fa8f6facSMatthias Ringwald #endif 77fa8f6facSMatthias Ringwald #if !LWIP_HTTPD_DYNAMIC_HEADERS 78fa8f6facSMatthias Ringwald #error This needs LWIP_HTTPD_DYNAMIC_HEADERS 79fa8f6facSMatthias Ringwald #endif 80fa8f6facSMatthias 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 169*c10be05fSMatthias Ringwald // Major: Networking Device, Minor: Networ Access Point 170*c10be05fSMatthias Ringwald gap_set_class_of_device(0x20300); 171*c10be05fSMatthias Ringwald 17297dc5e69SMatthias Ringwald // register for HCI events 17397dc5e69SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 17497dc5e69SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 17597dc5e69SMatthias Ringwald 17697dc5e69SMatthias Ringwald // Initialize L2CAP 17797dc5e69SMatthias Ringwald l2cap_init(); 17897dc5e69SMatthias Ringwald 17997dc5e69SMatthias Ringwald // Initialize BNEP 18097dc5e69SMatthias Ringwald bnep_init(); 18197dc5e69SMatthias Ringwald 18297dc5e69SMatthias Ringwald // Init SDP 18397dc5e69SMatthias Ringwald sdp_init(); 18497dc5e69SMatthias Ringwald memset(pan_sdp_record, 0, sizeof(pan_sdp_record)); 18597dc5e69SMatthias Ringwald uint16_t network_packet_types[] = { NETWORK_TYPE_IPv4, NETWORK_TYPE_ARP, 0}; // 0 as end of list 18697dc5e69SMatthias Ringwald 18797dc5e69SMatthias Ringwald // NAP Network Access Type: Other, 1 MB/s 18897dc5e69SMatthias 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); 18997dc5e69SMatthias Ringwald sdp_register_service(pan_sdp_record); 19097dc5e69SMatthias Ringwald printf("SDP service record size: %u\n", de_get_len((uint8_t*) pan_sdp_record)); 19197dc5e69SMatthias Ringwald 19297dc5e69SMatthias Ringwald // Init BNEP lwIP Adapter 19397dc5e69SMatthias Ringwald bnep_lwip_init(); 19497dc5e69SMatthias Ringwald 19597dc5e69SMatthias Ringwald // Setup NAP Service via BENP lwIP adapter 19697dc5e69SMatthias Ringwald bnep_lwip_register_service(BLUETOOTH_SERVICE_CLASS_NAP, 1691); 19797dc5e69SMatthias Ringwald 19897dc5e69SMatthias Ringwald // register callback - to print state 19997dc5e69SMatthias Ringwald bnep_lwip_register_packet_handler(packet_handler); 20097dc5e69SMatthias Ringwald } 20197dc5e69SMatthias Ringwald /* LISTING_END */ 20297dc5e69SMatthias Ringwald 20397dc5e69SMatthias Ringwald 20497dc5e69SMatthias Ringwald /* @section DHCP Server Configuration 20597dc5e69SMatthias Ringwald * 20697dc5e69SMatthias Ringwald * @text Listing DhcpSetup shows the DHCP Server configuration for network 192.168.7.0/8 20797dc5e69SMatthias Ringwald */ 20897dc5e69SMatthias Ringwald 20997dc5e69SMatthias Ringwald /* LISTING_START(DhcpSetup): Setup DHCP Server with 3 entries for 192.168.7.0/8. */ 21097dc5e69SMatthias Ringwald 21197dc5e69SMatthias Ringwald #define NUM_DHCP_ENTRY 3 21297dc5e69SMatthias Ringwald 21397dc5e69SMatthias Ringwald static dhcp_entry_t entries[NUM_DHCP_ENTRY] = 21497dc5e69SMatthias Ringwald { 21597dc5e69SMatthias Ringwald /* mac ip address subnet mask lease time */ 21697dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 2}, {255, 255, 255, 0}, 24 * 60 * 60 }, 21797dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 3}, {255, 255, 255, 0}, 24 * 60 * 60 }, 21897dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 4}, {255, 255, 255, 0}, 24 * 60 * 60 } 21997dc5e69SMatthias Ringwald }; 22097dc5e69SMatthias Ringwald 22197dc5e69SMatthias Ringwald static dhcp_config_t dhcp_config = 22297dc5e69SMatthias Ringwald { 22397dc5e69SMatthias Ringwald {192, 168, 7, 1}, 67, /* server address, port */ 22497dc5e69SMatthias Ringwald {0, 0, 0, 0}, /* dns server */ 22597dc5e69SMatthias Ringwald NULL, /* dns suffix */ 22697dc5e69SMatthias Ringwald NUM_DHCP_ENTRY, /* num entry */ 22797dc5e69SMatthias Ringwald entries /* entries */ 22897dc5e69SMatthias Ringwald }; 22997dc5e69SMatthias Ringwald /* LISTING_END */ 23097dc5e69SMatthias Ringwald 23197dc5e69SMatthias Ringwald 232fa8f6facSMatthias Ringwald /* @section Large File Download 233fa8f6facSMatthias Ringwald * 234fa8f6facSMatthias Ringwald * @text Listing LargeFile Shows how a configurable test file for performance tests is generated on the fly. 235fa8f6facSMatthias Ringwald * The filename is the number of bytes to generate, e.g. /1048576.txt results in a 1MB file. 236fa8f6facSMatthias Ringwald */ 237fa8f6facSMatthias Ringwald 238fa8f6facSMatthias Ringwald /* LISTING_START(LargeFile): Provide large file. */ 239fa8f6facSMatthias Ringwald 2404251aeecSMatthias Ringwald int fs_open_custom(struct fs_file *file, const char *name); 241fa8f6facSMatthias Ringwald int fs_open_custom(struct fs_file *file, const char *name){ 242fa8f6facSMatthias Ringwald if (*name != '/') return 0; 243fa8f6facSMatthias Ringwald uint32_t file_size = btstack_atoi(&name[1]); 244fa8f6facSMatthias Ringwald if (file_size > 0) { 245fa8f6facSMatthias Ringwald printf("Serving '%s' with %u bytes\n", name, file_size); 246fa8f6facSMatthias Ringwald /* initialize fs_file correctly */ 247fa8f6facSMatthias Ringwald memset(file, 0, sizeof(struct fs_file)); 248fa8f6facSMatthias Ringwald file->len = file_size; 249fa8f6facSMatthias Ringwald file->index = 0; 250fa8f6facSMatthias Ringwald file->flags = FS_FILE_FLAGS_HEADER_PERSISTENT; 251fa8f6facSMatthias Ringwald return 1; 252fa8f6facSMatthias Ringwald } 253fa8f6facSMatthias Ringwald return 0; 254fa8f6facSMatthias Ringwald } 255fa8f6facSMatthias Ringwald 256fa8f6facSMatthias Ringwald static uint16_t cgi_buffer_fill(char * cgi_buffer, uint16_t cgi_buffer_size, uint32_t start_pos){ 257fa8f6facSMatthias Ringwald // fill buffer with dots 258fa8f6facSMatthias Ringwald memset(cgi_buffer, (uint8_t) '.', cgi_buffer_size); 259fa8f6facSMatthias Ringwald uint16_t cursor = 10; 260fa8f6facSMatthias Ringwald uint16_t pos = 0; 261fa8f6facSMatthias Ringwald const uint16_t line_length = 64; 262fa8f6facSMatthias Ringwald 263fa8f6facSMatthias Ringwald while ((pos + line_length ) < cgi_buffer_size){ 264fa8f6facSMatthias Ringwald // write position 265fa8f6facSMatthias Ringwald sprintf((char *) &cgi_buffer[pos], "%08"PRIx32, start_pos + pos); 266fa8f6facSMatthias Ringwald cgi_buffer[pos + 8] = '-'; 267fa8f6facSMatthias Ringwald // cursor 268fa8f6facSMatthias Ringwald cgi_buffer[pos+cursor] = '+'; 269fa8f6facSMatthias Ringwald cursor++; 270fa8f6facSMatthias Ringwald // new line 271fa8f6facSMatthias Ringwald cgi_buffer[pos+line_length-1] = '\n'; 272fa8f6facSMatthias Ringwald pos += line_length; 273fa8f6facSMatthias Ringwald } 274fa8f6facSMatthias Ringwald 275fa8f6facSMatthias Ringwald // handle last incomplete line 276fa8f6facSMatthias Ringwald if (pos == 0){ 277fa8f6facSMatthias Ringwald const char * last_line_text = "Thank you for evaluating BTstack!"; 278fa8f6facSMatthias Ringwald uint16_t bytes_to_copy = btstack_min(strlen(last_line_text), cgi_buffer_size); 279fa8f6facSMatthias Ringwald memcpy(cgi_buffer, last_line_text, bytes_to_copy); 280fa8f6facSMatthias Ringwald pos = cgi_buffer_size; 281fa8f6facSMatthias Ringwald } 282fa8f6facSMatthias Ringwald 283fa8f6facSMatthias Ringwald return pos; 284fa8f6facSMatthias Ringwald } 285fa8f6facSMatthias Ringwald 2864251aeecSMatthias Ringwald int fs_read_custom(struct fs_file *file, char *buffer, int count); 287fa8f6facSMatthias Ringwald int fs_read_custom(struct fs_file *file, char *buffer, int count) 288fa8f6facSMatthias Ringwald { 289fa8f6facSMatthias Ringwald uint32_t remaining_data = file->len - file->index; 290fa8f6facSMatthias Ringwald if (remaining_data == 0) { 291fa8f6facSMatthias Ringwald // all bytes already read 292fa8f6facSMatthias Ringwald return FS_READ_EOF; 293fa8f6facSMatthias Ringwald } 294fa8f6facSMatthias Ringwald 295fa8f6facSMatthias Ringwald uint32_t bytes_to_fill = remaining_data; 2964251aeecSMatthias Ringwald if (bytes_to_fill > (uint32_t) count){ 297fa8f6facSMatthias Ringwald bytes_to_fill = count; 298fa8f6facSMatthias Ringwald } 299fa8f6facSMatthias Ringwald 300fa8f6facSMatthias Ringwald uint32_t bytes_written = cgi_buffer_fill(buffer, bytes_to_fill, file->index); 301fa8f6facSMatthias Ringwald file->index += bytes_written; 302fa8f6facSMatthias Ringwald 303fa8f6facSMatthias Ringwald return bytes_written; 304fa8f6facSMatthias Ringwald } 305fa8f6facSMatthias Ringwald 3064251aeecSMatthias Ringwald void fs_close_custom(struct fs_file *file); 3074251aeecSMatthias Ringwald void fs_close_custom(struct fs_file *file){ 3084251aeecSMatthias Ringwald UNUSED(file); 309fa8f6facSMatthias Ringwald } 310fa8f6facSMatthias Ringwald 311fa8f6facSMatthias Ringwald /* LISTING_END */ 312fa8f6facSMatthias Ringwald 31397dc5e69SMatthias Ringwald /* @section DHCP Server Setup 31497dc5e69SMatthias Ringwald * 31597dc5e69SMatthias Ringwald * @text Listing LwipSetup shows the setup of the lwIP network stack and starts the DHCP Server 31697dc5e69SMatthias Ringwald */ 31797dc5e69SMatthias Ringwald 31897dc5e69SMatthias Ringwald /* LISTING_START(LwipSetup): Report lwIP version, init lwIP, start DHCP Serverr */ 31997dc5e69SMatthias Ringwald 32097dc5e69SMatthias Ringwald static void network_setup(void){ 32197dc5e69SMatthias Ringwald printf("lwIP version: " LWIP_VERSION_STRING "\n"); 32297dc5e69SMatthias Ringwald 32397dc5e69SMatthias Ringwald #if BYTE_ORDER == LITTLE_ENDIAN 32497dc5e69SMatthias Ringwald // big endian detection not supported by build configuration 32597dc5e69SMatthias Ringwald if (btstack_is_big_endian()){ 32697dc5e69SMatthias Ringwald printf("lwIP configured for little endian, but running on big endian. Please set BYTE_ORDER to BIG_ENDIAN in lwiopts.h\n"); 32797dc5e69SMatthias Ringwald while (1); 32897dc5e69SMatthias Ringwald } 32997dc5e69SMatthias Ringwald #endif 33097dc5e69SMatthias Ringwald 33197dc5e69SMatthias Ringwald // init lwIP stack 3320be141aeSMatthias Ringwald #if NO_SYS 33397dc5e69SMatthias Ringwald lwip_init(); 3340be141aeSMatthias Ringwald #else 3350be141aeSMatthias Ringwald tcpip_init(NULL, NULL); 3360be141aeSMatthias Ringwald #endif 33797dc5e69SMatthias Ringwald 33897dc5e69SMatthias Ringwald // start DHCP Server 33997dc5e69SMatthias Ringwald dhserv_init(&dhcp_config); 34097dc5e69SMatthias Ringwald 34197dc5e69SMatthias Ringwald // start HTTP Server 34297dc5e69SMatthias Ringwald httpd_init(); 34397dc5e69SMatthias Ringwald } 34497dc5e69SMatthias Ringwald /* LISTING_END */ 34597dc5e69SMatthias Ringwald 34697dc5e69SMatthias Ringwald 34797dc5e69SMatthias Ringwald /* @section Main 34897dc5e69SMatthias Ringwald * 34997dc5e69SMatthias Ringwald * @text Setup the lwIP network and PAN NAP 35097dc5e69SMatthias Ringwald */ 35197dc5e69SMatthias Ringwald 35297dc5e69SMatthias Ringwald /* LISTING_START(Main): Setup lwIP network and PAN NAP */ 35397dc5e69SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 35497dc5e69SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 35597dc5e69SMatthias Ringwald 35697dc5e69SMatthias Ringwald (void)argc; 35797dc5e69SMatthias Ringwald (void)argv; 35897dc5e69SMatthias Ringwald 35997dc5e69SMatthias Ringwald // setup lwIP, HTTP, DHCP 36097dc5e69SMatthias Ringwald network_setup(); 36197dc5e69SMatthias Ringwald 36297dc5e69SMatthias Ringwald // setup Classic PAN NAP Service 36397dc5e69SMatthias Ringwald pan_bnep_setup(); 36497dc5e69SMatthias Ringwald 36597dc5e69SMatthias Ringwald // Turn on the device 36697dc5e69SMatthias Ringwald hci_power_control(HCI_POWER_ON); 36797dc5e69SMatthias Ringwald return 0; 36897dc5e69SMatthias Ringwald } 36997dc5e69SMatthias Ringwald /* LISTING_END */ 37097dc5e69SMatthias Ringwald 37197dc5e69SMatthias Ringwald /* EXAMPLE_END */ 372