| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- /*
- * Copyright (C) 2014 BlueKitchen GmbH
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * 4. Any redistribution, use, or modification is done solely for
- * personal benefit and not for any commercial purpose or for
- * monetary gain.
- *
- * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
- * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Please inquire about commercial licensing options at
- * contact@bluekitchen-gmbh.com
- *
- */
- #define BTSTACK_FILE__ "sm_pairing_central.c"
-
- // *****************************************************************************
- /* EXAMPLE_START(sm_pairing_central): LE Peripheral - Test pairing combinations
- *
- * @text Depending on the Authentication requiremens and IO Capabilities,
- * the pairing process uses different short and long term key generation method.
- * This example helps explore the different options incl. LE Secure Connections.
- * It scans for advertisements and connects to the first device that lists a
- * random service.
- */
- // *****************************************************************************
- #include <stdint.h>
- #include <inttypes.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "btstack.h"
- // sm_pairing_central.gatt contains the declaration of the provided GATT Services + Characteristics
- // sm_pairing_central.h contains the binary representation of sm_pairing_central.gatt
- // it is generated by the build system by calling: $BTSTACK_ROOT/tool/compile_gatt.py sm_pairing_central.gatt sm_pairing_central.h
- // it needs to be regenerated when the GATT Database declared in sm_pairing_central.gatt file is modified
- #include "sm_pairing_central.h"
- // We're looking for a remote device that lists this service in the advertisement
- // LightBlue assigns 0x1111 as the UUID for a Blank service.
- #define REMOTE_SERVICE 0x1111
- // Fixed passkey - used with sm_pairing_peripheral. Passkey is random in general
- #define FIXED_PASSKEY 123456
- static btstack_packet_callback_registration_t hci_event_callback_registration;
- static btstack_packet_callback_registration_t sm_event_callback_registration;
- /* @section GAP LE setup for receiving advertisements
- *
- * @text GAP LE advertisements are received as custom HCI events of the
- * GAP_EVENT_ADVERTISING_REPORT type. To receive them, you'll need to register
- * the HCI packet handler, as shown in Listing GAPLEAdvSetup.
- */
- /* LISTING_START(GAPLEAdvSetup): Setting up GAP LE client for receiving advertisements */
- static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
- static void sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
- static void sm_pairing_central_setup(void){
- l2cap_init();
- // setup le device db
- le_device_db_init();
- // setup SM: Display only
- sm_init();
- // setup ATT server
- att_server_init(profile_data, NULL, NULL);
- /**
- * Choose ONE of the following configurations
- * Bonding is disabled to allow for repeated testing. It can be enabled by or'ing
- * SM_AUTHREQ_BONDING to the authentication requirements like this:
- * sm_set_authentication_requirements( X | SM_AUTHREQ_BONDING)
- */
- // register handler
- hci_event_callback_registration.callback = &hci_packet_handler;
- hci_add_event_handler(&hci_event_callback_registration);
- sm_event_callback_registration.callback = &sm_packet_handler;
- sm_add_event_handler(&sm_event_callback_registration);
- // LE Legacy Pairing, Just Works
- // sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
- // sm_set_authentication_requirements(0);
- // LE Legacy Pairing, Passkey entry initiator enter, responder (us) displays
- // sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
- // sm_set_authentication_requirements(SM_AUTHREQ_MITM_PROTECTION);
- // sm_use_fixed_passkey_in_display_role(FIXED_PASSKEY);
- #ifdef ENABLE_LE_SECURE_CONNECTIONS
- // enable LE Secure Connections Only mode - disables Legacy pairing
- // sm_set_secure_connections_only_mode(true);
- // LE Secure Connections, Just Works
- // sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
- // sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION);
- // LE Secure Connections, Numeric Comparison
- sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
- sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION);
- // LE Secure Pairing, Passkey entry initiator (us) enters, responder displays
- // sm_set_io_capabilities(IO_CAPABILITY_KEYBOARD_ONLY);
- // sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION);
- // sm_use_fixed_passkey_in_display_role(FIXED_PASSKEY);
- // LE Secure Pairing, Passkey entry initiator (us) displays, responder enters
- // sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
- // sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION);
- #endif
- }
- /* LISTING_END */
- /* @section HCI packet handler
- *
- * @text The HCI packet handler has to start the scanning,
- * and to handle received advertisements. Advertisements are received
- * as HCI event packets of the GAP_EVENT_ADVERTISING_REPORT type,
- * see Listing HCIPacketHandler.
- */
- /* LISTING_START(HCIPacketHandler): Scanning and receiving advertisements */
- static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
- UNUSED(channel);
- UNUSED(size);
- if (packet_type != HCI_EVENT_PACKET) return;
- hci_con_handle_t con_handle;
- switch (hci_event_packet_get_type(packet)) {
- case BTSTACK_EVENT_STATE:
- // BTstack activated, get started
- if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
- printf("Start scaning!\n");
- gap_set_scan_parameters(1,0x0030, 0x0030);
- gap_start_scan();
- }
- break;
- case GAP_EVENT_ADVERTISING_REPORT:{
- bd_addr_t address;
- gap_event_advertising_report_get_address(packet, address);
- uint8_t address_type = gap_event_advertising_report_get_address_type(packet);
- uint8_t length = gap_event_advertising_report_get_data_length(packet);
- const uint8_t * data = gap_event_advertising_report_get_data(packet);
- // printf("Advertisement event: addr-type %u, addr %s, data[%u] ",
- // address_type, bd_addr_to_str(address), length);
- // printf_hexdump(data, length);
- if (!ad_data_contains_uuid16(length, (uint8_t *) data, REMOTE_SERVICE)) break;
- printf("Found remote with UUID %04x, connecting...\n", REMOTE_SERVICE);
- gap_stop_scan();
- gap_connect(address,address_type);
- break;
- }
- case HCI_EVENT_LE_META:
- // wait for connection complete
- if (hci_event_le_meta_get_subevent_code(packet) != HCI_SUBEVENT_LE_CONNECTION_COMPLETE) break;
- con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
- printf("Connection complete\n");
- // start pairing
- sm_request_pairing(con_handle);
- break;
- case HCI_EVENT_ENCRYPTION_CHANGE:
- con_handle = hci_event_encryption_change_get_connection_handle(packet);
- printf("Connection encrypted: %u\n", hci_event_encryption_change_get_encryption_enabled(packet));
- break;
- default:
- break;
- }
- }
- /* @section HCI packet handler
- *
- * @text The SM packet handler receives Security Manager Events required for pairing.
- * It also receives events generated during Identity Resolving
- * see Listing SMPacketHandler.
- */
- /* LISTING_START(SMPacketHandler): Scanning and receiving advertisements */
- static void sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
- UNUSED(channel);
- UNUSED(size);
- if (packet_type != HCI_EVENT_PACKET) return;
- switch (hci_event_packet_get_type(packet)) {
- case SM_EVENT_JUST_WORKS_REQUEST:
- printf("Just works requested\n");
- sm_just_works_confirm(sm_event_just_works_request_get_handle(packet));
- break;
- case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
- printf("Confirming numeric comparison: %"PRIu32"\n", sm_event_numeric_comparison_request_get_passkey(packet));
- sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet));
- break;
- case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
- printf("Display Passkey: %"PRIu32"\n", sm_event_passkey_display_number_get_passkey(packet));
- break;
- case SM_EVENT_PASSKEY_INPUT_NUMBER:
- printf("Passkey Input requested\n");
- printf("Sending fixed passkey %"PRIu32"\n", FIXED_PASSKEY);
- sm_passkey_input(sm_event_passkey_input_number_get_handle(packet), FIXED_PASSKEY);
- break;
- case SM_EVENT_PAIRING_COMPLETE:
- switch (sm_event_pairing_complete_get_status(packet)){
- case ERROR_CODE_SUCCESS:
- printf("Pairing complete, success\n");
- break;
- case ERROR_CODE_CONNECTION_TIMEOUT:
- printf("Pairing failed, timeout\n");
- break;
- case ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION:
- printf("Pairing failed, disconnected\n");
- break;
- case ERROR_CODE_AUTHENTICATION_FAILURE:
- printf("Pairing failed, reason = %u\n", sm_event_pairing_complete_get_reason(packet));
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- }
- /* LISTING_END */
- int btstack_main(void);
- int btstack_main(void)
- {
- sm_pairing_central_setup();
- // turn on!
- hci_power_control(HCI_POWER_ON);
-
- return 0;
- }
- /* EXAMPLE_END */
|