xref: /btstack/example/pan_lwip_http_server.c (revision 1fbe4564be530ba975f4cd70443a76f0afda5276)
1 /*
2  * Copyright (C) 2014 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 MATTHIAS
24  * RINGWALD 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__ "pan_lwip_http_server.c"
39 
40 // *****************************************************************************
41 /* EXAMPLE_START(pan_lwip_http_server): PAN - HTTP Server using lwIP
42  *
43  * @text Bluetooth PAN is mainly used for Internet Tethering, where e.g. a mobile
44  * phone provides internet connection to a laptop or a tablet.
45  *
46  * Instead of regular internet access, it's also possible to provide a Web app on a
47  * Bluetooth device, e.g. for configuration or maintenance. For some device,
48  * this can be a more effective way to provide an interface compared to dedicated
49  * smartphone applications (for Android and iOS).
50  *
51  * Before iOS 11, accessing an HTTP server via Bluetooth PAN was not supported on
52  * the iPhone, but on iPod and iPad. With iOS 11, this works as expected.
53  *
54  * After pairing your device, please open the URL http://192.168.7.1 in your web
55  * browser.
56 
57  */
58  // *****************************************************************************
59 
60 #include <stdio.h>
61 
62 #include "btstack_config.h"
63 #include "bnep_lwip.h"
64 #include "btstack.h"
65 
66 #include "lwip/init.h"
67 #include "lwip/opt.h"
68 #include "lwip/tcpip.h"
69 #include "lwip/apps/httpd.h"
70 #include "dhserver.h"
71 
72 // network types
73 #define NETWORK_TYPE_IPv4       0x0800
74 #define NETWORK_TYPE_ARP        0x0806
75 #define NETWORK_TYPE_IPv6       0x86DD
76 
77 static uint8_t pan_sdp_record[220];
78 
79 static btstack_packet_callback_registration_t hci_event_callback_registration;
80 
81 /*
82  * @section Packet Handler
83  *
84  * @text All BNEP events are handled in the platform/bnep_lwip.c BNEP-LWIP Adapter.
85  *       Here, we only print status information and handle pairing requests.
86  */
87 
88 /* LISTING_START(packetHandler): Packet Handler */
89 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
90     /* LISTING_PAUSE */
91     UNUSED(channel);
92     UNUSED(size);
93 
94     bd_addr_t event_addr;
95 
96     switch (packet_type) {
97         case HCI_EVENT_PACKET:
98             switch (hci_event_packet_get_type(packet)) {
99 
100                 case HCI_EVENT_PIN_CODE_REQUEST:
101                     // inform about pin code request
102                     printf("Pin code request - using '0000'\n");
103                     hci_event_pin_code_request_get_bd_addr(packet, event_addr);
104                     gap_pin_code_response(event_addr, "0000");
105                     break;
106 
107                 case HCI_EVENT_USER_CONFIRMATION_REQUEST:
108                     // inform about user confirmation request
109                     printf("SSP User Confirmation Auto accept\n");
110                     hci_event_user_confirmation_request_get_bd_addr(packet, event_addr);
111                     break;
112 
113                 /* @text BNEP_EVENT_CHANNEL_OPENED is received after a BNEP connection was established or
114                  * or when the connection fails. The status field returns the error code.
115                  */
116                 case BNEP_EVENT_CHANNEL_OPENED:
117                     if (bnep_event_channel_opened_get_status(packet)) {
118                         printf("BNEP channel open failed, status %02x\n", bnep_event_channel_opened_get_status(packet));
119                     } else {
120                         uint16_t uuid_source = bnep_event_channel_opened_get_source_uuid(packet);
121                         uint16_t uuid_dest   = bnep_event_channel_opened_get_destination_uuid(packet);
122                         uint16_t mtu         = bnep_event_channel_opened_get_mtu(packet);
123                         bnep_event_channel_opened_get_remote_address(packet, event_addr);
124                         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                         printf("Please open 'http://192.168.7.1' in your web browser: \n");
126                     }
127                     break;
128 
129                 /* @text BNEP_EVENT_CHANNEL_CLOSED is received when the connection gets closed.
130                  */
131                 case BNEP_EVENT_CHANNEL_CLOSED:
132                     printf("BNEP channel closed\n");
133                     break;
134 
135                 default:
136                     break;
137             }
138             break;
139         default:
140             break;
141     }
142 }
143 /* LISTING_END */
144 
145 /* @section PAN BNEP Setup
146  *
147  * @text Listing PanBnepSetup shows the setup of the PAN setup
148  */
149 
150 /* LISTING_START(PanBnepSetup): Configure GAP, register PAN NAP servier, register PAN NA SDP record. */
151 static void pan_bnep_setup(void){
152 
153     // Discoverable
154     // Set local name with a template Bluetooth address, that will be automatically
155     // replaced with a actual address once it is available, i.e. when BTstack boots
156     // up and starts talking to a Bluetooth module.
157     gap_set_local_name("PAN HTTP 00:00:00:00:00:00");
158     gap_discoverable_control(1);
159 
160     // register for HCI events
161     hci_event_callback_registration.callback = &packet_handler;
162     hci_add_event_handler(&hci_event_callback_registration);
163 
164     // Initialize L2CAP
165     l2cap_init();
166 
167     // Initialize BNEP
168     bnep_init();
169 
170     // Init SDP
171     sdp_init();
172     memset(pan_sdp_record, 0, sizeof(pan_sdp_record));
173     uint16_t network_packet_types[] = { NETWORK_TYPE_IPv4, NETWORK_TYPE_ARP, 0};    // 0 as end of list
174 
175     // NAP Network Access Type: Other, 1 MB/s
176     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     sdp_register_service(pan_sdp_record);
178     printf("SDP service record size: %u\n", de_get_len((uint8_t*) pan_sdp_record));
179 
180     // Init BNEP lwIP Adapter
181     bnep_lwip_init();
182 
183     // Setup NAP Service via BENP lwIP adapter
184     bnep_lwip_register_service(BLUETOOTH_SERVICE_CLASS_NAP, 1691);
185 
186     // register callback - to print state
187     bnep_lwip_register_packet_handler(packet_handler);
188 }
189 /* LISTING_END */
190 
191 
192 /* @section DHCP Server Configuration
193  *
194  * @text Listing DhcpSetup shows the DHCP Server configuration for network 192.168.7.0/8
195  */
196 
197 /* LISTING_START(DhcpSetup): Setup DHCP Server with 3 entries for 192.168.7.0/8. */
198 
199 #define NUM_DHCP_ENTRY 3
200 
201 static dhcp_entry_t entries[NUM_DHCP_ENTRY] =
202 {
203     /* mac    ip address        subnet mask        lease time */
204     { {0}, {192, 168, 7, 2}, {255, 255, 255, 0}, 24 * 60 * 60 },
205     { {0}, {192, 168, 7, 3}, {255, 255, 255, 0}, 24 * 60 * 60 },
206     { {0}, {192, 168, 7, 4}, {255, 255, 255, 0}, 24 * 60 * 60 }
207 };
208 
209 static dhcp_config_t dhcp_config =
210 {
211     {192, 168, 7, 1}, 67, /* server address, port */
212     {0, 0, 0, 0},         /* dns server */
213     NULL,                /* dns suffix */
214     NUM_DHCP_ENTRY,       /* num entry */
215     entries               /* entries */
216 };
217 /* LISTING_END */
218 
219 
220 /* @section DHCP Server Setup
221  *
222  * @text Listing LwipSetup shows the setup of the lwIP network stack and starts the DHCP Server
223  */
224 
225 /* LISTING_START(LwipSetup): Report lwIP version, init lwIP, start DHCP Serverr */
226 
227 static void network_setup(void){
228     printf("lwIP version: " LWIP_VERSION_STRING "\n");
229 
230 #if BYTE_ORDER == LITTLE_ENDIAN
231     // big endian detection not supported by build configuration
232     if (btstack_is_big_endian()){
233         printf("lwIP configured for little endian, but running on big endian. Please set BYTE_ORDER to BIG_ENDIAN in lwiopts.h\n");
234         while (1);
235     }
236 #endif
237 
238     // init lwIP stack
239 #if NO_SYS
240     lwip_init();
241 #else
242     tcpip_init(NULL, NULL);
243 #endif
244 
245     // start DHCP Server
246     dhserv_init(&dhcp_config);
247 
248     // start HTTP Server
249     httpd_init();
250 }
251 /* LISTING_END */
252 
253 
254 /* @section Main
255  *
256  * @text Setup the lwIP network and PAN NAP
257  */
258 
259 /* LISTING_START(Main): Setup lwIP network and PAN NAP */
260 int btstack_main(int argc, const char * argv[]);
261 int btstack_main(int argc, const char * argv[]){
262 
263     (void)argc;
264     (void)argv;
265 
266     // setup lwIP, HTTP, DHCP
267     network_setup();
268 
269     // setup Classic PAN NAP Service
270     pan_bnep_setup();
271 
272     // Turn on the device
273     hci_power_control(HCI_POWER_ON);
274     return 0;
275 }
276 /* LISTING_END */
277 
278 /* EXAMPLE_END */
279