1 /*
2 * Copyright (C) 2019 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 BLUEKITCHEN
24 * GMBH 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__ "le_mitm.c"
39
40 // *****************************************************************************
41 /* EXAMPLE_START(le_mitm): LE Man-in-the-Middle Tool
42 *
43 * @text The example first does an LE scan and allows the user to select a Peripheral
44 * device. Then, it connects to the Peripheral and starts advertising with the same
45 * data as the Peripheral device.
46 * ATT Requests and responses are forwarded between the peripheral and the central
47 * Security requests are handled locally.
48 *
49 * @note A Bluetooth Controller that supports Central and Peripheral Role
50 * at the same time is required for this example. See chipset/README.md
51 *
52 */
53 // *****************************************************************************
54
55
56 #include <inttypes.h>
57 #include <stdint.h>
58 #include <stdio.h>
59 #include <string.h>
60
61 #include "btstack.h"
62
63 // Number of devices shown during scanning
64 #define MAX_NUM_DEVICES 36
65
66 // Max number of ATT PTUs to queue (if malloc is not used)
67 #define MAX_NUM_ATT_PDUS 20
68
69 // Max ATT MTU - can be increased if needed
70 #define MAX_ATT_MTU ATT_DEFAULT_MTU
71
72 typedef struct {
73 bd_addr_t addr;
74 bd_addr_type_t addr_type;
75 int8_t rssi;
76 uint8_t ad_len;
77 uint8_t ad_data[31];
78 uint8_t scan_len;
79 uint8_t scan_data[31];
80 } device_info_t;
81
82 typedef struct {
83 btstack_linked_item_t item;
84 hci_con_handle_t handle;
85 uint8_t len;
86 uint8_t data[MAX_ATT_MTU];
87 } att_pdu_t;
88
89 typedef enum {
90 TC_OFF,
91 TC_SCANNING,
92 TC_W4_CONNECT,
93 TC_CONNECTED,
94 } app_state_t;
95
96 static uint16_t devices_found;
97 static device_info_t devices[MAX_NUM_DEVICES];
98
99 static uint16_t remote_peripheral_index;
100 static bd_addr_t remote_peripheral_addr;
101 static bd_addr_type_t remote_peripheral_addr_type;
102 static hci_con_handle_t remote_peripheral_handle;
103
104 static hci_con_handle_t remote_central_handle;
105
106 static btstack_linked_list_t outgoing_att_pdus;
107
108 static app_state_t state = TC_OFF;
109 static btstack_packet_callback_registration_t hci_event_callback_registration;
110 static btstack_packet_callback_registration_t sm_event_callback_registration;
111
112 static const char * ad_types[] = {
113 "",
114 "Flags",
115 "Incomplete 16-bit UUIDs",
116 "Complete 16-bit UUIDs",
117 "Incomplete 32-bit UUIDs",
118 "Complete 32-bit UUIDs",
119 "Incomplete 128-bit UUIDs",
120 "Complete 128-bit UUIDs",
121 "Short Name",
122 "Complete Name",
123 "Tx Power Level",
124 "",
125 "",
126 "Class of Device",
127 "Simple Pairing Hash C",
128 "Simple Pairing Randomizer R",
129 "Device ID",
130 "Security Manager TK Value",
131 "Slave Connection Interval Range",
132 "",
133 "16-bit Solicitation UUIDs",
134 "128-bit Solicitation UUIDs",
135 "Service Data",
136 "Public Target Address",
137 "Random Target Address",
138 "Appearance",
139 "Advertising Interval"
140 };
141
142 static const char * adv_failed_warning = "\n"
143 "[!] Start advertising failed!\n"
144 "[!] Make sure your Bluetooth Controller supports Central and Peripheral Roles at the same time.\n\n";
145
146 // att pdu pool implementation
147 #ifndef HAVE_MALLOC
148 static att_pdu_t att_pdu_storage[MAX_NUM_ATT_PDUS];
149 static btstack_memory_pool_t att_pdu_pool;
btstack_memory_att_pdu_get(void)150 static att_pdu_t * btstack_memory_att_pdu_get(void){
151 void * buffer = btstack_memory_pool_get(&att_pdu_pool);
152 if (buffer){
153 memset(buffer, 0, sizeof(att_pdu_t));
154 }
155 return (att_pdu_t *) buffer;
156 }
btstack_memory_att_pdu_free(att_pdu_t * att_pdu)157 static void btstack_memory_att_pdu_free(att_pdu_t *att_pdu){
158 btstack_memory_pool_free(&att_pdu_pool, att_pdu);
159 }
160 #else
btstack_memory_att_pdu_get(void)161 static att_pdu_t * btstack_memory_att_pdu_get(void){
162 void * buffer = malloc(sizeof(att_pdu_t));
163 if (buffer){
164 memset(buffer, 0, sizeof(att_pdu_t));
165 }
166 return (att_pdu_t *) buffer;
167 }
btstack_memory_att_pdu_free(att_pdu_t * att_pdu)168 static void btstack_memory_att_pdu_free(att_pdu_t * att_pdu){
169 free(att_pdu);
170 }
171 #endif
172
mitm_start_scan(btstack_timer_source_t * ts)173 static void mitm_start_scan(btstack_timer_source_t * ts){
174 UNUSED(ts);
175 printf("[-] Start scanning\n");
176 printf("To select device, enter advertisement number:\n");
177 state = TC_SCANNING;
178 gap_set_scan_parameters(0,0x0030, 0x0030);
179 gap_start_scan();
180 }
181
mitm_connect(uint16_t index)182 static void mitm_connect(uint16_t index){
183 // stop scanning, and connect to the device
184 gap_stop_scan();
185 state = TC_W4_CONNECT;
186 remote_peripheral_index = index;
187 memcpy(remote_peripheral_addr, devices[index].addr, 6);
188 remote_peripheral_addr_type = devices[index].addr_type;
189 printf("\n");
190 printf("[-] Connecting to Peripheral %s\n", bd_addr_to_str(remote_peripheral_addr));
191 gap_auto_connection_start(remote_peripheral_addr_type, remote_peripheral_addr);
192 }
193
mitm_start_advertising(void)194 static void mitm_start_advertising(void){
195 // set adv + scan data if available
196 if (devices[remote_peripheral_index].ad_len > 0){
197 gap_advertisements_set_data(devices[remote_peripheral_index].ad_len, devices[remote_peripheral_index].ad_data);
198 printf("[-] Setup adv data (len %02u): ", devices[remote_peripheral_index].ad_len);
199 printf_hexdump(devices[remote_peripheral_index].ad_data, devices[remote_peripheral_index].ad_len);
200 }
201 if (devices[remote_peripheral_index].scan_len > 0){
202 gap_scan_response_set_data(devices[remote_peripheral_index].scan_len, devices[remote_peripheral_index].scan_data);
203 printf("[-] Setup scan data (len %02u): ", devices[remote_peripheral_index].scan_len);
204 printf_hexdump(devices[remote_peripheral_index].ad_data, devices[remote_peripheral_index].ad_len);
205 }
206 uint16_t adv_int_min = 0x0030;
207 uint16_t adv_int_max = 0x0030;
208 uint8_t adv_type = 0;
209 bd_addr_t null_addr;
210 memset(null_addr, 0, 6);
211 gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
212 gap_advertisements_enable(1);
213 }
214
mitm_print_advertisement(uint16_t index)215 static void mitm_print_advertisement(uint16_t index) {
216 // get character for index
217 char c;
218 if (index < 10) {
219 c = '0' + index;
220 } else {
221 c = 'a' + (index - 10);
222 }
223
224 printf("%c. %s (%-3d dBm)", c, bd_addr_to_str(devices[index].addr), devices[index].rssi);
225
226 ad_context_t context;
227 bd_addr_t address;
228 uint8_t uuid_128[16];
229 for (ad_iterator_init(&context, devices[index].ad_len, devices[index].ad_data); ad_iterator_has_more(
230 &context); ad_iterator_next(&context)) {
231 uint8_t data_type = ad_iterator_get_data_type(&context);
232 uint8_t size = ad_iterator_get_data_len(&context);
233 const uint8_t *data = ad_iterator_get_data(&context);
234
235 if (data_type > 0 && data_type < 0x1B) {
236 printf(" - %s: ", ad_types[data_type]);
237 }
238 uint8_t i;
239 switch (data_type) {
240 case BLUETOOTH_DATA_TYPE_FLAGS:
241 printf("0x%02x", data[0]);
242 break;
243 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
244 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
245 case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS:
246 for (i = 0; i < size; i += 2) {
247 printf("%02X ", little_endian_read_16(data, i));
248 }
249 break;
250 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
251 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
252 case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS:
253 for (i = 0; i < size; i += 4) {
254 printf("%04"PRIX32, little_endian_read_32(data, i));
255 }
256 break;
257 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
258 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
259 case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS:
260 reverse_128(data, uuid_128);
261 printf("%s", uuid128_to_str(uuid_128));
262 break;
263 case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME:
264 case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME:
265 for (i = 0; i < size; i++) {
266 printf("%c", (char) (data[i]));
267 }
268 break;
269 case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL:
270 printf("%d dBm", *(int8_t *) data);
271 break;
272 case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE:
273 printf("Connection Interval Min = %u ms, Max = %u ms", little_endian_read_16(data, 0) * 5 / 4,
274 little_endian_read_16(data, 2) * 5 / 4);
275 break;
276 case BLUETOOTH_DATA_TYPE_SERVICE_DATA:
277 printf_hexdump(data, size);
278 break;
279 case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS:
280 case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS:
281 reverse_bd_addr(data, address);
282 printf("%s", bd_addr_to_str(address));
283 break;
284 case BLUETOOTH_DATA_TYPE_APPEARANCE:
285 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
286 printf("%02X", little_endian_read_16(data, 0));
287 break;
288 case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL:
289 printf("%u ms", little_endian_read_16(data, 0) * 5 / 8);
290 break;
291 case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA:
292 printf_hexdump(data, size);
293 break;
294 case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
295 case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE:
296 case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C:
297 case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
298 case BLUETOOTH_DATA_TYPE_DEVICE_ID:
299 case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS:
300 default:
301 break;
302 }
303 }
304 printf("\n");
305 }
306
mitm_handle_adv(uint8_t * packet)307 static void mitm_handle_adv(uint8_t * packet){
308 // get addr and type
309 bd_addr_t remote_addr;
310 gap_event_advertising_report_get_address(packet, remote_addr);
311 bd_addr_type_t remote_addr_type = gap_event_advertising_report_get_address_type(packet);
312 uint8_t adv_event_type = gap_event_advertising_report_get_advertising_event_type(packet);
313 bool is_scan_response = adv_event_type == 2 || adv_event_type == 4;
314
315 // find remote in list
316 uint16_t i;
317 for (i=0;i<devices_found;i++) {
318 if (memcmp(remote_addr, devices[i].addr, 6) != 0) continue;
319 if (remote_addr_type != devices[i].addr_type) continue;
320 break;
321 }
322
323 if (i == MAX_NUM_DEVICES) return;
324
325 if (devices_found == i){
326 // skip first event with scan response data (should not happen)
327 if (is_scan_response) return;
328 memset(&devices[i], 0, sizeof(device_info_t));
329 devices[i].rssi = (int8_t) gap_event_advertising_report_get_rssi(packet);
330 devices[i].addr_type = remote_addr_type;
331 memcpy(devices[i].addr, remote_addr, 6);
332 devices[i].ad_len = gap_event_advertising_report_get_data_length(packet);
333 memcpy(devices[i].ad_data, gap_event_advertising_report_get_data(packet), devices[i].ad_len);
334 mitm_print_advertisement(i);
335 devices_found++;
336 return;
337 }
338
339 // store scan data
340 if (!is_scan_response) return;
341 devices[i].scan_len = gap_event_advertising_report_get_data_length(packet);
342 memcpy(devices[i].scan_data, gap_event_advertising_report_get_data(packet), devices[i].scan_len);
343 }
344
mitm_console_connected_menu(void)345 static void mitm_console_connected_menu(void){
346 printf("=== Connected menu ===\n");
347 printf("p - Pair Peripheral\n");
348 }
349
mitm_opposite_handle(hci_con_handle_t handle)350 static hci_con_handle_t mitm_opposite_handle(hci_con_handle_t handle){
351 if (handle == remote_peripheral_handle) {
352 return remote_central_handle;
353 } else {
354 return remote_peripheral_handle;
355 }
356 }
357
mitm_request_to_send(void)358 static void mitm_request_to_send(void){
359 // request to send again if more packets queued
360 if (btstack_linked_list_empty(&outgoing_att_pdus)) return;
361 att_pdu_t * pdu = (att_pdu_t *) btstack_linked_list_get_first_item((&outgoing_att_pdus));
362 l2cap_request_can_send_fix_channel_now_event(pdu->handle, L2CAP_CID_ATTRIBUTE_PROTOCOL);
363 }
364
mitm_name_for_handle(hci_con_handle_t handle)365 static const char * mitm_name_for_handle(hci_con_handle_t handle){
366 if (handle == remote_peripheral_handle) return "Peripheral";
367 if (handle == remote_central_handle) return "Central";
368 return "(unknown handle)'";
369 }
370
hci_event_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)371 static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
372 UNUSED(channel);
373 UNUSED(size);
374
375 if (packet_type != HCI_EVENT_PACKET) return;
376
377 uint8_t event = hci_event_packet_get_type(packet);
378 hci_con_handle_t connection_handle;
379 uint32_t passkey;
380
381 switch (event) {
382 case BTSTACK_EVENT_STATE:
383 // BTstack activated, get started
384 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING) {
385 mitm_start_scan(NULL);
386 state = TC_SCANNING;
387 } else {
388 state = TC_OFF;
389 }
390 break;
391 case GAP_EVENT_ADVERTISING_REPORT:
392 if (state != TC_SCANNING) return;
393 mitm_handle_adv(packet);
394 break;
395 case HCI_EVENT_COMMAND_COMPLETE:
396 // warn if adv enable fails
397 if (hci_event_command_complete_get_command_opcode(packet) != hci_le_set_advertise_enable.opcode) break;
398 if (hci_event_command_complete_get_return_parameters(packet)[0] == ERROR_CODE_SUCCESS) break;
399 printf("%s", adv_failed_warning);
400 break;
401 case HCI_EVENT_META_GAP:
402 // wait for connection complete
403 if (hci_event_gap_meta_get_subevent_code(packet) != GAP_SUBEVENT_LE_CONNECTION_COMPLETE) break;
404 switch (state){
405 case TC_W4_CONNECT:
406 state = TC_CONNECTED;
407 remote_peripheral_handle = gap_subevent_le_connection_complete_get_connection_handle(packet);
408 printf("[-] Peripheral connected\n");
409 mitm_start_advertising();
410 printf ("You can connect now!\n");
411 printf("\n");
412 mitm_console_connected_menu();
413 break;
414 case TC_CONNECTED:
415 remote_central_handle = gap_subevent_le_connection_complete_get_connection_handle(packet);
416 printf("[-] Central connected!\n");
417 break;
418 default:
419 break;
420 }
421 break;
422 case HCI_EVENT_DISCONNECTION_COMPLETE:
423 // unregister listener
424 connection_handle = HCI_CON_HANDLE_INVALID;
425 printf("[-] %s disconnected", mitm_name_for_handle(connection_handle));
426 if (connection_handle == remote_peripheral_handle){
427 mitm_start_scan(NULL);
428 state = TC_SCANNING;
429 }
430 break;
431 case SM_EVENT_JUST_WORKS_REQUEST:
432 connection_handle = sm_event_just_works_request_get_handle(packet);
433 printf("[-] %s request 'Just Works' pairing\n", mitm_name_for_handle(connection_handle));
434 sm_just_works_confirm(connection_handle);
435 break;
436 case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
437 passkey = sm_event_numeric_comparison_request_get_passkey(packet);
438 connection_handle = sm_event_numeric_comparison_request_get_handle(packet);
439 printf("[-] %s accepting numeric comparison: %"PRIu32"\n", mitm_name_for_handle(connection_handle), passkey);
440 sm_numeric_comparison_confirm(connection_handle);
441 break;
442 case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
443 passkey = sm_event_passkey_display_number_get_passkey(packet);
444 connection_handle = sm_event_passkey_display_number_get_handle(packet);
445 printf("[-] %s display passkey: %"PRIu32"\n", mitm_name_for_handle(connection_handle), passkey);
446 break;
447 case SM_EVENT_PAIRING_COMPLETE:
448 connection_handle = sm_event_pairing_complete_get_handle(packet);
449 switch (sm_event_pairing_complete_get_status(packet)){
450 case ERROR_CODE_SUCCESS:
451 printf("[-] %s pairing complete, success\n", mitm_name_for_handle(connection_handle));
452 break;
453 case ERROR_CODE_CONNECTION_TIMEOUT:
454 printf("[-] %s pairing failed, timeout\n", mitm_name_for_handle(connection_handle));
455 break;
456 case ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION:
457 printf("[-] %s pairing failed, disconnected\n", mitm_name_for_handle(connection_handle));
458 break;
459 case ERROR_CODE_AUTHENTICATION_FAILURE:
460 printf("[-] %s pairing failed, reason = %u\n", mitm_name_for_handle(connection_handle), sm_event_pairing_complete_get_reason(packet));
461 break;
462 default:
463 break;
464 }
465 break;
466 case SM_EVENT_REENCRYPTION_COMPLETE:
467 connection_handle = sm_event_reencryption_complete_get_handle(packet);
468 printf("[-] %s Re-encryption complete, success\n", mitm_name_for_handle(connection_handle));
469 break;
470 default:
471 break;
472 }
473 }
474
att_packet_handler(uint8_t packet_type,uint16_t handle,uint8_t * packet,uint16_t size)475 static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
476 att_pdu_t * pdu;
477 switch (packet_type){
478 case ATT_DATA_PACKET:
479 printf("[%10s] ", mitm_name_for_handle(handle));
480 printf_hexdump(packet, size);
481 pdu = btstack_memory_att_pdu_get();
482 if (!pdu) break;
483 // handle att mtu exchange directly
484 if (packet[0] == ATT_EXCHANGE_MTU_REQUEST){
485 pdu->handle = handle;
486 pdu->len = 3;
487 pdu->data[0] = ATT_EXCHANGE_MTU_RESPONSE;
488 little_endian_store_16(pdu->data, 1, MAX_ATT_MTU);
489 } else {
490 btstack_assert(size <= MAX_ATT_MTU);
491 pdu->handle = mitm_opposite_handle(handle);
492 pdu->len = (uint8_t) size;
493 memcpy(pdu->data, packet, size);
494 }
495 btstack_linked_list_add_tail(&outgoing_att_pdus, (btstack_linked_item_t *) pdu);
496 mitm_request_to_send();
497 break;
498 case HCI_EVENT_PACKET:
499 if (packet[0] == L2CAP_EVENT_CAN_SEND_NOW) {
500 // send next packet
501 pdu = (att_pdu_t *) btstack_linked_list_pop(&outgoing_att_pdus);
502 if (pdu == NULL) break;
503 l2cap_send_connectionless(pdu->handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, pdu->data, pdu->len);
504 btstack_memory_att_pdu_free(pdu);
505 // request to send again if more packets queued
506 mitm_request_to_send();
507 }
508 break;
509 default:
510 break;
511 }
512 }
513
stdin_process(char cmd)514 static void stdin_process(char cmd) {
515 unsigned int index;
516 switch(state){
517 case TC_OFF:
518 break;
519 case TC_SCANNING:
520 if ((cmd >= '0') && (cmd <= '9')){
521 index = cmd - '0';
522 } else if ((cmd >= 'a') && (cmd <= 'z')){
523 index = cmd - 'a' + 10;
524 } else {
525 break;
526 }
527 if (index >= devices_found) break;
528 mitm_connect(index);
529 break;
530 case TC_CONNECTED:
531 switch (cmd){
532 case 'p':
533 printf("[-] Start pairing / encryption with Peripheral\n");
534 sm_request_pairing(remote_peripheral_handle);
535 break;
536 default:
537 mitm_console_connected_menu();
538 break;
539 }
540 break;
541 default:
542 break;
543 }
544 }
545
546 int btstack_main(int argc, const char * argv[]);
btstack_main(int argc,const char * argv[])547 int btstack_main(int argc, const char * argv[]){
548
549 (void)argc;
550 (void)argv;
551
552 l2cap_init();
553
554 l2cap_register_fixed_channel(att_packet_handler, L2CAP_CID_ATTRIBUTE_PROTOCOL);
555
556 sm_init();
557
558 hci_event_callback_registration.callback = &hci_event_handler;
559 hci_add_event_handler(&hci_event_callback_registration);
560
561 sm_event_callback_registration.callback = &hci_event_handler;
562 sm_add_event_handler(&sm_event_callback_registration);
563
564 #ifndef HAVE_MALLOC
565 btstack_memory_pool_create(&att_pdu_pool, att_pdu_storage, MAX_NUM_ATT_PDUS, sizeof(att_pdu_t));
566 #endif
567
568 #ifdef HAVE_BTSTACK_STDIN
569 btstack_stdin_setup(stdin_process);
570 #endif
571
572 // turn on!
573 hci_power_control(HCI_POWER_ON);
574
575 return 0;
576 }
577 /* EXAMPLE_END */
578