1*97dc5e69SMatthias Ringwald /* 2*97dc5e69SMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3*97dc5e69SMatthias Ringwald * 4*97dc5e69SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*97dc5e69SMatthias Ringwald * modification, are permitted provided that the following conditions 6*97dc5e69SMatthias Ringwald * are met: 7*97dc5e69SMatthias Ringwald * 8*97dc5e69SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*97dc5e69SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*97dc5e69SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*97dc5e69SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*97dc5e69SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*97dc5e69SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*97dc5e69SMatthias Ringwald * contributors may be used to endorse or promote products derived 15*97dc5e69SMatthias Ringwald * from this software without specific prior written permission. 16*97dc5e69SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*97dc5e69SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*97dc5e69SMatthias Ringwald * monetary gain. 19*97dc5e69SMatthias Ringwald * 20*97dc5e69SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*97dc5e69SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*97dc5e69SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*97dc5e69SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*97dc5e69SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*97dc5e69SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*97dc5e69SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*97dc5e69SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*97dc5e69SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*97dc5e69SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*97dc5e69SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*97dc5e69SMatthias Ringwald * SUCH DAMAGE. 32*97dc5e69SMatthias Ringwald * 33*97dc5e69SMatthias Ringwald * Please inquire about commercial licensing options at 34*97dc5e69SMatthias Ringwald * [email protected] 35*97dc5e69SMatthias Ringwald * 36*97dc5e69SMatthias Ringwald */ 37*97dc5e69SMatthias Ringwald 38*97dc5e69SMatthias Ringwald #define __BTSTACK_FILE__ "pan_lwip_http_server.c" 39*97dc5e69SMatthias Ringwald 40*97dc5e69SMatthias Ringwald // ***************************************************************************** 41*97dc5e69SMatthias Ringwald /* EXAMPLE_START(pan_lwip_http_server): PAN - HTTP Server using lwIP 42*97dc5e69SMatthias Ringwald * 43*97dc5e69SMatthias Ringwald * @text Bluetooth PAN is mainly used for Internet Tethering, where e.g. a mobile 44*97dc5e69SMatthias Ringwald * phone provides internet connection to a laptop or a tablet. 45*97dc5e69SMatthias Ringwald * 46*97dc5e69SMatthias Ringwald * Instead of regular internet access, it's also possible to provide a Web app on a 47*97dc5e69SMatthias Ringwald * Bluetooth device, e.g. for configuration or maintenance. For some device, 48*97dc5e69SMatthias Ringwald * this can be a more effective way to provide an interface compared to dedicated 49*97dc5e69SMatthias Ringwald * smartphone applications (for Android and iOS). 50*97dc5e69SMatthias Ringwald * 51*97dc5e69SMatthias Ringwald * Before iOS 11, accessing an HTTP server via Bluetooth PAN was not supported on 52*97dc5e69SMatthias Ringwald * the iPhone, but on iPod and iPad. With iOS 11, this works as expected. 53*97dc5e69SMatthias Ringwald * 54*97dc5e69SMatthias Ringwald * After pairing your device, please open the URL http://192.168.7.1 in your web 55*97dc5e69SMatthias Ringwald * browser. 56*97dc5e69SMatthias Ringwald 57*97dc5e69SMatthias Ringwald */ 58*97dc5e69SMatthias Ringwald // ***************************************************************************** 59*97dc5e69SMatthias Ringwald 60*97dc5e69SMatthias Ringwald #include <stdio.h> 61*97dc5e69SMatthias Ringwald 62*97dc5e69SMatthias Ringwald #include "btstack_config.h" 63*97dc5e69SMatthias Ringwald #include "bnep_lwip.h" 64*97dc5e69SMatthias Ringwald #include "btstack.h" 65*97dc5e69SMatthias Ringwald 66*97dc5e69SMatthias Ringwald #include "lwip/init.h" 67*97dc5e69SMatthias Ringwald #include "lwip/opt.h" 68*97dc5e69SMatthias Ringwald #include "lwip/tcpip.h" 69*97dc5e69SMatthias Ringwald #include "lwip/apps/httpd.h" 70*97dc5e69SMatthias Ringwald #include "dhserver.h" 71*97dc5e69SMatthias Ringwald 72*97dc5e69SMatthias Ringwald // network types 73*97dc5e69SMatthias Ringwald #define NETWORK_TYPE_IPv4 0x0800 74*97dc5e69SMatthias Ringwald #define NETWORK_TYPE_ARP 0x0806 75*97dc5e69SMatthias Ringwald #define NETWORK_TYPE_IPv6 0x86DD 76*97dc5e69SMatthias Ringwald 77*97dc5e69SMatthias Ringwald static uint8_t pan_sdp_record[220]; 78*97dc5e69SMatthias Ringwald 79*97dc5e69SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 80*97dc5e69SMatthias Ringwald 81*97dc5e69SMatthias Ringwald /* 82*97dc5e69SMatthias Ringwald * @section Packet Handler 83*97dc5e69SMatthias Ringwald * 84*97dc5e69SMatthias Ringwald * @text All BNEP events are handled in the platform/bnep_lwip.c BNEP-LWIP Adapter. 85*97dc5e69SMatthias Ringwald * Here, we only print status information and handle pairing requests. 86*97dc5e69SMatthias Ringwald */ 87*97dc5e69SMatthias Ringwald 88*97dc5e69SMatthias Ringwald /* LISTING_START(packetHandler): Packet Handler */ 89*97dc5e69SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 90*97dc5e69SMatthias Ringwald /* LISTING_PAUSE */ 91*97dc5e69SMatthias Ringwald UNUSED(channel); 92*97dc5e69SMatthias Ringwald UNUSED(size); 93*97dc5e69SMatthias Ringwald 94*97dc5e69SMatthias Ringwald bd_addr_t event_addr; 95*97dc5e69SMatthias Ringwald 96*97dc5e69SMatthias Ringwald switch (packet_type) { 97*97dc5e69SMatthias Ringwald case HCI_EVENT_PACKET: 98*97dc5e69SMatthias Ringwald switch (hci_event_packet_get_type(packet)) { 99*97dc5e69SMatthias Ringwald 100*97dc5e69SMatthias Ringwald case HCI_EVENT_PIN_CODE_REQUEST: 101*97dc5e69SMatthias Ringwald // inform about pin code request 102*97dc5e69SMatthias Ringwald printf("Pin code request - using '0000'\n"); 103*97dc5e69SMatthias Ringwald hci_event_pin_code_request_get_bd_addr(packet, event_addr); 104*97dc5e69SMatthias Ringwald gap_pin_code_response(event_addr, "0000"); 105*97dc5e69SMatthias Ringwald break; 106*97dc5e69SMatthias Ringwald 107*97dc5e69SMatthias Ringwald case HCI_EVENT_USER_CONFIRMATION_REQUEST: 108*97dc5e69SMatthias Ringwald // inform about user confirmation request 109*97dc5e69SMatthias Ringwald printf("SSP User Confirmation Auto accept\n"); 110*97dc5e69SMatthias Ringwald hci_event_user_confirmation_request_get_bd_addr(packet, event_addr); 111*97dc5e69SMatthias Ringwald break; 112*97dc5e69SMatthias Ringwald 113*97dc5e69SMatthias Ringwald /* @text BNEP_EVENT_CHANNEL_OPENED is received after a BNEP connection was established or 114*97dc5e69SMatthias Ringwald * or when the connection fails. The status field returns the error code. 115*97dc5e69SMatthias Ringwald */ 116*97dc5e69SMatthias Ringwald case BNEP_EVENT_CHANNEL_OPENED: 117*97dc5e69SMatthias Ringwald if (bnep_event_channel_opened_get_status(packet)) { 118*97dc5e69SMatthias Ringwald printf("BNEP channel open failed, status %02x\n", bnep_event_channel_opened_get_status(packet)); 119*97dc5e69SMatthias Ringwald } else { 120*97dc5e69SMatthias Ringwald uint16_t uuid_source = bnep_event_channel_opened_get_source_uuid(packet); 121*97dc5e69SMatthias Ringwald uint16_t uuid_dest = bnep_event_channel_opened_get_destination_uuid(packet); 122*97dc5e69SMatthias Ringwald uint16_t mtu = bnep_event_channel_opened_get_mtu(packet); 123*97dc5e69SMatthias Ringwald bnep_event_channel_opened_get_remote_address(packet, event_addr); 124*97dc5e69SMatthias 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); 125*97dc5e69SMatthias Ringwald printf("Please open 'http://192.168.7.1' in your web browser: \n"); 126*97dc5e69SMatthias Ringwald } 127*97dc5e69SMatthias Ringwald break; 128*97dc5e69SMatthias Ringwald 129*97dc5e69SMatthias Ringwald /* @text BNEP_EVENT_CHANNEL_CLOSED is received when the connection gets closed. 130*97dc5e69SMatthias Ringwald */ 131*97dc5e69SMatthias Ringwald case BNEP_EVENT_CHANNEL_CLOSED: 132*97dc5e69SMatthias Ringwald printf("BNEP channel closed\n"); 133*97dc5e69SMatthias Ringwald break; 134*97dc5e69SMatthias Ringwald 135*97dc5e69SMatthias Ringwald default: 136*97dc5e69SMatthias Ringwald break; 137*97dc5e69SMatthias Ringwald } 138*97dc5e69SMatthias Ringwald break; 139*97dc5e69SMatthias Ringwald default: 140*97dc5e69SMatthias Ringwald break; 141*97dc5e69SMatthias Ringwald } 142*97dc5e69SMatthias Ringwald } 143*97dc5e69SMatthias Ringwald /* LISTING_END */ 144*97dc5e69SMatthias Ringwald 145*97dc5e69SMatthias Ringwald /* @section PAN BNEP Setup 146*97dc5e69SMatthias Ringwald * 147*97dc5e69SMatthias Ringwald * @text Listing PanBnepSetup shows the setup of the PAN setup 148*97dc5e69SMatthias Ringwald */ 149*97dc5e69SMatthias Ringwald 150*97dc5e69SMatthias Ringwald /* LISTING_START(PanBnepSetup): Configure GAP, register PAN NAP servier, register PAN NA SDP record. */ 151*97dc5e69SMatthias Ringwald static void pan_bnep_setup(void){ 152*97dc5e69SMatthias Ringwald 153*97dc5e69SMatthias Ringwald // Discoverable 154*97dc5e69SMatthias Ringwald // Set local name with a template Bluetooth address, that will be automatically 155*97dc5e69SMatthias Ringwald // replaced with a actual address once it is available, i.e. when BTstack boots 156*97dc5e69SMatthias Ringwald // up and starts talking to a Bluetooth module. 157*97dc5e69SMatthias Ringwald gap_set_local_name("PAN HTTP 00:00:00:00:00:00"); 158*97dc5e69SMatthias Ringwald gap_discoverable_control(1); 159*97dc5e69SMatthias Ringwald 160*97dc5e69SMatthias Ringwald // register for HCI events 161*97dc5e69SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 162*97dc5e69SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 163*97dc5e69SMatthias Ringwald 164*97dc5e69SMatthias Ringwald // Initialize L2CAP 165*97dc5e69SMatthias Ringwald l2cap_init(); 166*97dc5e69SMatthias Ringwald 167*97dc5e69SMatthias Ringwald // Initialize BNEP 168*97dc5e69SMatthias Ringwald bnep_init(); 169*97dc5e69SMatthias Ringwald 170*97dc5e69SMatthias Ringwald // Init SDP 171*97dc5e69SMatthias Ringwald sdp_init(); 172*97dc5e69SMatthias Ringwald memset(pan_sdp_record, 0, sizeof(pan_sdp_record)); 173*97dc5e69SMatthias Ringwald uint16_t network_packet_types[] = { NETWORK_TYPE_IPv4, NETWORK_TYPE_ARP, 0}; // 0 as end of list 174*97dc5e69SMatthias Ringwald 175*97dc5e69SMatthias Ringwald // NAP Network Access Type: Other, 1 MB/s 176*97dc5e69SMatthias 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); 177*97dc5e69SMatthias Ringwald sdp_register_service(pan_sdp_record); 178*97dc5e69SMatthias Ringwald printf("SDP service record size: %u\n", de_get_len((uint8_t*) pan_sdp_record)); 179*97dc5e69SMatthias Ringwald 180*97dc5e69SMatthias Ringwald // Init BNEP lwIP Adapter 181*97dc5e69SMatthias Ringwald bnep_lwip_init(); 182*97dc5e69SMatthias Ringwald 183*97dc5e69SMatthias Ringwald // Setup NAP Service via BENP lwIP adapter 184*97dc5e69SMatthias Ringwald bnep_lwip_register_service(BLUETOOTH_SERVICE_CLASS_NAP, 1691); 185*97dc5e69SMatthias Ringwald 186*97dc5e69SMatthias Ringwald // register callback - to print state 187*97dc5e69SMatthias Ringwald bnep_lwip_register_packet_handler(packet_handler); 188*97dc5e69SMatthias Ringwald } 189*97dc5e69SMatthias Ringwald /* LISTING_END */ 190*97dc5e69SMatthias Ringwald 191*97dc5e69SMatthias Ringwald 192*97dc5e69SMatthias Ringwald /* @section DHCP Server Configuration 193*97dc5e69SMatthias Ringwald * 194*97dc5e69SMatthias Ringwald * @text Listing DhcpSetup shows the DHCP Server configuration for network 192.168.7.0/8 195*97dc5e69SMatthias Ringwald */ 196*97dc5e69SMatthias Ringwald 197*97dc5e69SMatthias Ringwald /* LISTING_START(DhcpSetup): Setup DHCP Server with 3 entries for 192.168.7.0/8. */ 198*97dc5e69SMatthias Ringwald 199*97dc5e69SMatthias Ringwald #define NUM_DHCP_ENTRY 3 200*97dc5e69SMatthias Ringwald 201*97dc5e69SMatthias Ringwald static dhcp_entry_t entries[NUM_DHCP_ENTRY] = 202*97dc5e69SMatthias Ringwald { 203*97dc5e69SMatthias Ringwald /* mac ip address subnet mask lease time */ 204*97dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 2}, {255, 255, 255, 0}, 24 * 60 * 60 }, 205*97dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 3}, {255, 255, 255, 0}, 24 * 60 * 60 }, 206*97dc5e69SMatthias Ringwald { {0}, {192, 168, 7, 4}, {255, 255, 255, 0}, 24 * 60 * 60 } 207*97dc5e69SMatthias Ringwald }; 208*97dc5e69SMatthias Ringwald 209*97dc5e69SMatthias Ringwald static dhcp_config_t dhcp_config = 210*97dc5e69SMatthias Ringwald { 211*97dc5e69SMatthias Ringwald {192, 168, 7, 1}, 67, /* server address, port */ 212*97dc5e69SMatthias Ringwald {0, 0, 0, 0}, /* dns server */ 213*97dc5e69SMatthias Ringwald NULL, /* dns suffix */ 214*97dc5e69SMatthias Ringwald NUM_DHCP_ENTRY, /* num entry */ 215*97dc5e69SMatthias Ringwald entries /* entries */ 216*97dc5e69SMatthias Ringwald }; 217*97dc5e69SMatthias Ringwald /* LISTING_END */ 218*97dc5e69SMatthias Ringwald 219*97dc5e69SMatthias Ringwald 220*97dc5e69SMatthias Ringwald /* @section DHCP Server Setup 221*97dc5e69SMatthias Ringwald * 222*97dc5e69SMatthias Ringwald * @text Listing LwipSetup shows the setup of the lwIP network stack and starts the DHCP Server 223*97dc5e69SMatthias Ringwald */ 224*97dc5e69SMatthias Ringwald 225*97dc5e69SMatthias Ringwald /* LISTING_START(LwipSetup): Report lwIP version, init lwIP, start DHCP Serverr */ 226*97dc5e69SMatthias Ringwald 227*97dc5e69SMatthias Ringwald static void network_setup(void){ 228*97dc5e69SMatthias Ringwald printf("lwIP version: " LWIP_VERSION_STRING "\n"); 229*97dc5e69SMatthias Ringwald 230*97dc5e69SMatthias Ringwald #if BYTE_ORDER == LITTLE_ENDIAN 231*97dc5e69SMatthias Ringwald // big endian detection not supported by build configuration 232*97dc5e69SMatthias Ringwald if (btstack_is_big_endian()){ 233*97dc5e69SMatthias Ringwald printf("lwIP configured for little endian, but running on big endian. Please set BYTE_ORDER to BIG_ENDIAN in lwiopts.h\n"); 234*97dc5e69SMatthias Ringwald while (1); 235*97dc5e69SMatthias Ringwald } 236*97dc5e69SMatthias Ringwald #endif 237*97dc5e69SMatthias Ringwald 238*97dc5e69SMatthias Ringwald // init lwIP stack 239*97dc5e69SMatthias Ringwald lwip_init(); 240*97dc5e69SMatthias Ringwald 241*97dc5e69SMatthias Ringwald // start DHCP Server 242*97dc5e69SMatthias Ringwald dhserv_init(&dhcp_config); 243*97dc5e69SMatthias Ringwald 244*97dc5e69SMatthias Ringwald // start HTTP Server 245*97dc5e69SMatthias Ringwald httpd_init(); 246*97dc5e69SMatthias Ringwald } 247*97dc5e69SMatthias Ringwald /* LISTING_END */ 248*97dc5e69SMatthias Ringwald 249*97dc5e69SMatthias Ringwald 250*97dc5e69SMatthias Ringwald /* @section Main 251*97dc5e69SMatthias Ringwald * 252*97dc5e69SMatthias Ringwald * @text Setup the lwIP network and PAN NAP 253*97dc5e69SMatthias Ringwald */ 254*97dc5e69SMatthias Ringwald 255*97dc5e69SMatthias Ringwald /* LISTING_START(Main): Setup lwIP network and PAN NAP */ 256*97dc5e69SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 257*97dc5e69SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 258*97dc5e69SMatthias Ringwald 259*97dc5e69SMatthias Ringwald (void)argc; 260*97dc5e69SMatthias Ringwald (void)argv; 261*97dc5e69SMatthias Ringwald 262*97dc5e69SMatthias Ringwald // setup lwIP, HTTP, DHCP 263*97dc5e69SMatthias Ringwald network_setup(); 264*97dc5e69SMatthias Ringwald 265*97dc5e69SMatthias Ringwald // setup Classic PAN NAP Service 266*97dc5e69SMatthias Ringwald pan_bnep_setup(); 267*97dc5e69SMatthias Ringwald 268*97dc5e69SMatthias Ringwald // Turn on the device 269*97dc5e69SMatthias Ringwald hci_power_control(HCI_POWER_ON); 270*97dc5e69SMatthias Ringwald return 0; 271*97dc5e69SMatthias Ringwald } 272*97dc5e69SMatthias Ringwald /* LISTING_END */ 273*97dc5e69SMatthias Ringwald 274*97dc5e69SMatthias Ringwald /* EXAMPLE_END */ 275