Okundu Omeni
/
wifi-https-ble-sm-uart-atcmd-5-13-1
this is using the mbed os version 5-13-1
source/BleManager.cpp
- Committer:
- ocomeni
- Date:
- 2019-03-14
- Revision:
- 75:08eff6258e1b
- Parent:
- 74:f26e846adfe9
- Child:
- 76:6afda865fbf8
File content as of revision 75:08eff6258e1b:
/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <events/mbed_events.h> #include <mbed.h> #include "ble/BLE.h" #include "SecurityManager.h" #include "BleManager.h" #if MBED_CONF_APP_FILESYSTEM_SUPPORT #include "LittleFileSystem.h" #include "HeapBlockDevice.h" #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT static const uint8_t DEVICE_NAME[] = "SM_device"; /** This example demonstrates all the basic setup required * for pairing and setting up link security both as a central and peripheral * * The example is implemented as two classes, one for the peripheral and one * for central inheriting from a common base. They are run in sequence and * require a peer device to connect to. During the peripheral device demonstration * a peer device is required to connect. In the central device demonstration * this peer device will be scanned for and connected to - therefore it should * be advertising with the same address as when it connected. * * During the test output is written on the serial connection to monitor its * progress. */ //static const uint8_t DEVICE_NAME[] = "SM_device"; /* for demonstration purposes we will store the peer device address * of the device that connects to us in the first demonstration * so we can use its address to reconnect to it later */ //static BLEProtocol::AddressBytes_t peer_address; /** Base class for both peripheral and central. The same class that provides * the logic for the application also implements the SecurityManagerEventHandler * which is the interface used by the Security Manager to communicate events * back to the applications. You can provide overrides for a selection of events * your application is interested in. */ SMDevice::SMDevice(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) : _led1(LED1, 0), _ble(ble), _event_queue(event_queue), _peer_address(peer_address), _handle(0), _is_connecting(false) { } SMDevice::~SMDevice() { if (_ble.hasInitialized()) { _ble.shutdown(); } } /** Start BLE interface initialisation */ void SMDevice::run() { ble_error_t error; /* to show we're running we'll blink every 500ms */ _event_queue.call_every(500, this, &SMDevice::blink); if (_ble.hasInitialized()) { printf("Ble instance already initialised.\r\n"); return; } /* this will inform us off all events so we can schedule their handling * using our event queue */ _ble.onEventsToProcess( makeFunctionPointer(this, &SMDevice::schedule_ble_events) ); /* handle timeouts, for example when connection attempts fail */ _ble.gap().onTimeout( makeFunctionPointer(this, &SMDevice::on_timeout) ); error = _ble.init(this, &SMDevice::on_init_complete); if (error) { printf("Error returned by BLE::init.\r\n"); return; } /* this will not return until shutdown */ _event_queue.dispatch_forever(); } /* event handler functions */ /** Respond to a pairing request. This will be called by the stack * when a pairing request arrives and expects the application to * call acceptPairingRequest or cancelPairingRequest */ void SMDevice::pairingRequest( ble::connection_handle_t connectionHandle ) { printf("Pairing requested - authorising\r\n"); _ble.securityManager().acceptPairingRequest(connectionHandle); } /** Inform the application of a successful pairing. Terminate the demonstration. */ void SMDevice::pairingResult( ble::connection_handle_t connectionHandle, SecurityManager::SecurityCompletionStatus_t result ) { if (result == SecurityManager::SEC_STATUS_SUCCESS) { printf("Pairing successful\r\n"); } else { printf("Pairing failed\r\n"); } } /** Inform the application of change in encryption status. This will be * communicated through the serial port */ void SMDevice::linkEncryptionResult( ble::connection_handle_t connectionHandle, ble::link_encryption_t result ) { if (result == ble::link_encryption_t::ENCRYPTED) { printf("Link ENCRYPTED\r\n"); } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { printf("Link ENCRYPTED_WITH_MITM\r\n"); } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) { printf("Link NOT_ENCRYPTED\r\n"); } /* disconnect in 2 s */ _event_queue.call_in( 2000, &_ble.gap(), &Gap::disconnect, _handle, Gap::REMOTE_USER_TERMINATED_CONNECTION ); } /** Override to start chosen activity when initialisation completes */ //void SMDevice::start() = 0; /** This is called when BLE interface is initialised and starts the demonstration */ void SMDevice::on_init_complete(BLE::InitializationCompleteCallbackContext *event) { ble_error_t error; if (event->error) { printf("Error during the initialisation\r\n"); return; } /* This path will be used to store bonding information but will fallback * to storing in memory if file access fails (for example due to lack of a filesystem) */ const char* db_path = "/fs/bt_sec_db"; /* If the security manager is required this needs to be called before any * calls to the Security manager happen. */ error = _ble.securityManager().init( true, false, SecurityManager::IO_CAPS_NONE, NULL, false, db_path ); if (error) { printf("Error during init %d\r\n", error); return; } error = _ble.securityManager().preserveBondingStateOnReset(true); if (error) { printf("Error during preserveBondingStateOnReset %d\r\n", error); } #if MBED_CONF_APP_FILESYSTEM_SUPPORT /* Enable privacy so we can find the keys */ error = _ble.gap().enablePrivacy(true); if (error) { printf("Error enabling privacy\r\n"); } Gap::PeripheralPrivacyConfiguration_t configuration_p = { /* use_non_resolvable_random_address */ false, Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS }; _ble.gap().setPeripheralPrivacyConfiguration(&configuration_p); Gap::CentralPrivacyConfiguration_t configuration_c = { /* use_non_resolvable_random_address */ false, Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD }; _ble.gap().setCentralPrivacyConfiguration(&configuration_c); /* this demo switches between being master and slave */ _ble.securityManager().setHintFutureRoleReversal(true); #endif /* Tell the security manager to use methods in this class to inform us * of any events. Class needs to implement SecurityManagerEventHandler. */ _ble.securityManager().setSecurityManagerEventHandler(this); /* print device address */ Gap::AddressType_t addr_type; Gap::Address_t addr; _ble.gap().getAddress(&addr_type, addr); printf("Device address: %02x:%02x:%02x:%02x:%02x:%02x\r\n", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); /* when scanning we want to connect to a peer device so we need to * attach callbacks that are used by Gap to notify us of events */ _ble.gap().onConnection(this, &SMDevice::on_connect); _ble.gap().onDisconnection(this, &SMDevice::on_disconnect); /* start test in 500 ms */ _event_queue.call_in(500, this, &SMDevice::start); } /** This is called by Gap to notify the application we connected */ //void SMDevice::on_connect(const Gap::ConnectionCallbackParams_t *connection_event); /** This is called by Gap to notify the application we disconnected, * in our case it ends the demonstration. */ void SMDevice::on_disconnect(const Gap::DisconnectionCallbackParams_t *event) { printf("Disconnected\r\n"); _event_queue.break_dispatch(); } /** End demonstration unexpectedly. Called if timeout is reached during advertising, * scanning or connection initiation */ void SMDevice::on_timeout(const Gap::TimeoutSource_t source) { printf("Unexpected timeout - aborting\r\n"); _event_queue.break_dispatch(); } /** Schedule processing of events from the BLE in the event queue. */ void SMDevice::schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) { _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents)); }; /** Blink LED to show we're running */ void SMDevice::blink(void) { _led1 = !_led1; } /** A peripheral device will advertise, accept the connection and request * a change in link security. */ SMDevicePeripheral::SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) : SMDevice(ble, event_queue, peer_address) { } void SMDevicePeripheral::start() { /* Set up and start advertising */ ble_error_t error; GapAdvertisingData advertising_data; /* add advertising flags */ advertising_data.addFlags(GapAdvertisingData::LE_GENERAL_DISCOVERABLE | GapAdvertisingData::BREDR_NOT_SUPPORTED); /* add device name */ advertising_data.addData( GapAdvertisingData::COMPLETE_LOCAL_NAME, DEVICE_NAME, sizeof(DEVICE_NAME) ); error = _ble.gap().setAdvertisingPayload(advertising_data); if (error) { printf("Error during Gap::setAdvertisingPayload\r\n"); return; } /* advertise to everyone */ _ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); /* how many milliseconds between advertisements, lower interval * increases the chances of being seen at the cost of more power */ _ble.gap().setAdvertisingInterval(20); _ble.gap().setAdvertisingTimeout(0); error = _ble.gap().startAdvertising(); if (error) { printf("Error during Gap::startAdvertising.\r\n"); return; } printf("Please connect to device\r\n"); /** This tells the stack to generate a pairingRequest event * which will require this application to respond before pairing * can proceed. Setting it to false will automatically accept * pairing. */ _ble.securityManager().setPairingRequestAuthorisation(true); } /** This is called by Gap to notify the application we connected, * in our case it immediately requests a change in link security */ void SMDevicePeripheral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event) { ble_error_t error; /* remember the device that connects to us now so we can connect to it * during the next demonstration */ memcpy(_peer_address, connection_event->peerAddr, sizeof(_peer_address)); printf("Connected to: %02x:%02x:%02x:%02x:%02x:%02x\r\n", _peer_address[5], _peer_address[4], _peer_address[3], _peer_address[2], _peer_address[1], _peer_address[0]); /* store the handle for future Security Manager requests */ _handle = connection_event->handle; /* Request a change in link security. This will be done * indirectly by asking the master of the connection to * change it. Depending on circumstances different actions * may be taken by the master which will trigger events * which the applications should deal with. */ error = _ble.securityManager().setLinkSecurity( _handle, SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM ); if (error) { printf("Error during SM::setLinkSecurity %d\r\n", error); return; } } /** A central device will scan, connect to a peer and request pairing. */ SMDeviceCentral::SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) : SMDevice(ble, event_queue, peer_address) { }; void SMDeviceCentral::start() { /* start scanning and attach a callback that will handle advertisements * and scan requests responses */ ble_error_t error = _ble.gap().startScan(this, &SMDeviceCentral::on_scan); printf("Please advertise\r\n"); printf("Scanning for: %02x:%02x:%02x:%02x:%02x:%02x\r\n", _peer_address[5], _peer_address[4], _peer_address[3], _peer_address[2], _peer_address[1], _peer_address[0]); if (error) { printf("Error during Gap::startScan %d\r\n", error); return; } } /** Look at scan payload to find a peer device and connect to it */ void SMDeviceCentral::on_scan(const Gap::AdvertisementCallbackParams_t *params) { /* don't bother with analysing scan result if we're already connecting */ if (_is_connecting) { return; } /* connect to the same device that connected to us */ if (memcmp(params->peerAddr, _peer_address, sizeof(_peer_address)) == 0) { ble_error_t error = _ble.gap().connect( params->peerAddr, params->peerAddrType, NULL, NULL ); if (error) { printf("Error during Gap::connect %d\r\n", error); return; } printf("Connecting... "); /* we may have already scan events waiting * to be processed so we need to remember * that we are already connecting and ignore them */ _is_connecting = true; return; } } /** This is called by Gap to notify the application we connected, * in our case it immediately request pairing */ void SMDeviceCentral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event) { ble_error_t error; /* store the handle for future Security Manager requests */ _handle = connection_event->handle; /* in this example the local device is the master so we request pairing */ error = _ble.securityManager().requestPairing(_handle); printf("Connected\r\n"); if (error) { printf("Error during SM::requestPairing %d\r\n", error); return; } /* upon pairing success the application will disconnect */ } #if MBED_CONF_APP_FILESYSTEM_SUPPORT bool create_filesystem() { static LittleFileSystem fs("fs"); /* replace this with any physical block device your board supports (like an SD card) */ static HeapBlockDevice bd(4096, 256); int err = bd.init(); if (err) { return false; } err = bd.erase(0, bd.size()); if (err) { return false; } err = fs.mount(&bd); if (err) { /* Reformat if we can't mount the filesystem */ printf("No filesystem found, formatting...\r\n"); err = fs.reformat(&bd); if (err) { return false; } } return true; } #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT #ifdef BLE_SECURITY_MAIN int main() { BLE& ble = BLE::Instance(); events::EventQueue queue; #if MBED_CONF_APP_FILESYSTEM_SUPPORT /* if filesystem creation fails or there is no filesystem the security manager * will fallback to storing the security database in memory */ if (!create_filesystem()) { printf("Filesystem creation failed, will use memory storage\r\n"); } #endif while(1) { { printf("\r\n PERIPHERAL \r\n\r\n"); SMDevicePeripheral peripheral(ble, queue, peer_address); peripheral.run(); } { printf("\r\n CENTRAL \r\n\r\n"); SMDeviceCentral central(ble, queue, peer_address); central.run(); } } return 0; } #endif #ifdef OLD_BLE_SECURITY /* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#ifdef BLE_SECURITY_ENABLED #include <events/mbed_events.h> #include <mbed.h> #include "ble/BLE.h" #include "ble/Gap.h" #include "Types.h" #include "ble/services/UARTService.h" //#include "ble/gap/Types.h" #include "SecurityManager.h" #include "pretty_printer.h" #if MBED_CONF_APP_FILESYSTEM_SUPPORT #include "LittleFileSystem.h" #include "HeapBlockDevice.h" #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT /** This example demonstrates all the basic setup required * for pairing and setting up link security both as a central and peripheral * * The example is implemented as two classes, one for the peripheral and one * for central inheriting from a common base. They are run in sequence and * require a peer device to connect to. During the peripheral device demonstration * a peer device is required to connect. In the central device demonstration * this peer device will be scanned for and connected to - therefore it should * be advertising with the same address as when it connected. * * During the test output is written on the serial connection to monitor its * progress. */ static const char DEVICE_NAME[] = "SM_device"; /* we have to specify the disconnect call because of ambiguous overloads */ //typedef ble_error_t (Gap::*disconnect_call_t)(ble::connection_handle_t, ble::local_disconnection_reason_t); //const static disconnect_call_t disconnect_call = &Gap::disconnect; //typedef ble_error_t (Gap::*disconnect_call_t)(ble::connection_handle_t, ble::local_disconnection_reason_t); //const static (Gap::*disconnect_call_t) disconnect_call = &Gap::disconnect; /* for demonstration purposes we will store the peer device address * of the device that connects to us in the first demonstration * so we can use its address to reconnect to it later */ static BLEProtocol::AddressBytes_t peer_address; /** Base class for both peripheral and central. The same class that provides * the logic for the application also implements the SecurityManagerEventHandler * which is the interface used by the Security Manager to communicate events * back to the applications. You can provide overrides for a selection of events * your application is interested in. */ class SMDevice : private mbed::NonCopyable<SMDevice>, public SecurityManager::EventHandler, public Gap::EventHandler { public: SMDevice(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) : _led1(LED1, 0), _ble(ble), _event_queue(event_queue), _peer_address(peer_address), _handle(0), _is_connecting(false) { }; virtual ~SMDevice() { if (_ble.hasInitialized()) { _ble.shutdown(); } }; /** Start BLE interface initialisation */ void run() { ble_error_t error; /* to show we're running we'll blink every 500ms */ _event_queue.call_every(500, this, &SMDevice::blink); if (_ble.hasInitialized()) { printf("Ble instance already initialised.\r\n"); return; } /* this will inform us off all events so we can schedule their handling * using our event queue */ _ble.onEventsToProcess( makeFunctionPointer(this, &SMDevice::schedule_ble_events) ); /* handle gap events */ _ble.gap().setEventHandler(this); error = _ble.init(this, &SMDevice::on_init_complete); if (error) { printf("Error returned by BLE::init.\r\n"); return; } /* this will not return until shutdown */ _event_queue.dispatch_forever(); }; private: /** Override to start chosen activity when initialisation completes */ virtual void start() = 0; /** This is called when BLE interface is initialised and starts the demonstration */ void on_init_complete(BLE::InitializationCompleteCallbackContext *event) { ble_error_t error; if (event->error) { printf("Error during the initialisation\r\n"); return; } /* This path will be used to store bonding information but will fallback * to storing in memory if file access fails (for example due to lack of a filesystem) */ const char* db_path = "/fs/bt_sec_db"; /* If the security manager is required this needs to be called before any * calls to the Security manager happen. */ error = _ble.securityManager().init( true, false, SecurityManager::IO_CAPS_NONE, NULL, false, db_path ); if (error) { printf("Error during init %d\r\n", error); return; } error = _ble.securityManager().preserveBondingStateOnReset(true); if (error) { printf("Error during preserveBondingStateOnReset %d\r\n", error); } #if MBED_CONF_APP_FILESYSTEM_SUPPORT /* Enable privacy so we can find the keys */ error = _ble.gap().enablePrivacy(true); if (error) { printf("Error enabling privacy\r\n"); } Gap::PeripheralPrivacyConfiguration_t configuration_p = { /* use_non_resolvable_random_address */ false, Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS }; _ble.gap().setPeripheralPrivacyConfiguration(&configuration_p); Gap::CentralPrivacyConfiguration_t configuration_c = { /* use_non_resolvable_random_address */ false, Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD }; _ble.gap().setCentralPrivacyConfiguration(&configuration_c); /* this demo switches between being master and slave */ _ble.securityManager().setHintFutureRoleReversal(true); #endif /* Tell the security manager to use methods in this class to inform us * of any events. Class needs to implement SecurityManagerEventHandler. */ _ble.securityManager().setSecurityManagerEventHandler(this); /* gap events also handled by this class */ _ble.gap().setEventHandler(this); /* print device address */ Gap::AddressType_t addr_type; Gap::Address_t addr; _ble.gap().getAddress(&addr_type, addr); print_address(addr); /* start test in 500 ms */ _event_queue.call_in(500, this, &SMDevice::start); }; /** Schedule processing of events from the BLE in the event queue. */ void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) { _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents)); }; /** Blink LED to show we're running */ void blink(void) { _led1 = !_led1; }; private: /* Event handler */ /** Respond to a pairing request. This will be called by the stack * when a pairing request arrives and expects the application to * call acceptPairingRequest or cancelPairingRequest */ virtual void pairingRequest( ble::connection_handle_t connectionHandle ) { printf("Pairing requested - authorising\r\n"); _ble.securityManager().acceptPairingRequest(connectionHandle); } /** Inform the application of a successful pairing. Terminate the demonstration. */ virtual void pairingResult( ble::connection_handle_t connectionHandle, SecurityManager::SecurityCompletionStatus_t result ) { if (result == SecurityManager::SEC_STATUS_SUCCESS) { printf("Pairing successful\r\n"); } else { printf("Pairing failed\r\n"); } } /** Inform the application of change in encryption status. This will be * communicated through the serial port */ virtual void linkEncryptionResult( ble::connection_handle_t connectionHandle, ble::link_encryption_t result ) { if (result == ble::link_encryption_t::ENCRYPTED) { printf("Link ENCRYPTED\r\n"); } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { printf("Link ENCRYPTED_WITH_MITM\r\n"); } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) { printf("Link NOT_ENCRYPTED\r\n"); } /* disconnect in 2 s */ _event_queue.call_in( 2000, &_ble.gap(), &Gap::disconnect, //disconnect_call, _handle, (Gap::DisconnectionReason_t)0x13 //Gap::DisconnectionReason_t::REMOTE_USER_TERMINATED_CONNECTION) //ble::local_disconnection_reason_t(ble::local_disconnection_reason_t::USER_TERMINATION) ); } /** This is called by Gap to notify the application we disconnected, * in our case it ends the demonstration. */ //virtual void onDisconnectionComplete(const Gap::DisconnectionCompleteEvent &) virtual void onDisconnectionComplete(const Gap::DisconnectionCallbackParams_t *params) { printf("Disconnected\r\n"); _event_queue.break_dispatch(); }; //virtual void onAdvertisingEnd(const ble::AdvertisingEndEvent &) //void onAdvertisingEnd(const ble::AdvertisingEndEvent &) //{ // printf("Advertising timed out - aborting\r\n"); // _event_queue.break_dispatch(); //} //virtual void onScanTimeout(const ble::ScanTimeoutEvent &) //{ // printf("Scan timed out - aborting\r\n"); // _event_queue.break_dispatch(); //} private: DigitalOut _led1; protected: BLE &_ble; events::EventQueue &_event_queue; BLEProtocol::AddressBytes_t &_peer_address; ble::connection_handle_t _handle; bool _is_connecting; }; /** A peripheral device will advertise, accept the connection and request * a change in link security. */ class SMDevicePeripheral : public SMDevice { public: SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) : SMDevice(ble, event_queue, peer_address) { } virtual void start() { /* Set up and start advertising */ #ifdef NEW_BLE5_API //uint8_t adv_buffer[Gap::LEGACY_ADVERTISING_MAX_SIZE]; uint8_t adv_buffer[32]; /* use the helper to build the payload */ ble::Gap::AdvertisingDataBuilder adv_data_builder( adv_buffer, 32 ); adv_data_builder.setFlags(); adv_data_builder.setName(DEVICE_NAME); /* Set payload for the set */ ble_error_t error = _ble.gap().setAdvertisingPayload( ble::LEGACY_ADVERTISING_HANDLE, adv_data_builder.getAdvertisingData() ); if (error) { print_error(error, "Gap::setAdvertisingPayload() failed"); _event_queue.break_dispatch(); return; } ble::gap::AdvertisingParameters adv_parameters( ble::advertising_type_t::CONNECTABLE_UNDIRECTED ); error = _ble.gap().setAdvertisingParameters( ble::LEGACY_ADVERTISING_HANDLE, adv_parameters ); if (error) { print_error(error, "Gap::setAdvertisingParameters() failed"); return; } error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE); if (error) { print_error(error, "Gap::startAdvertising() failed"); return; } #else /* setup advertising */ _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); //_ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); /* set up the services that can be discovered */ _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); _ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); _ble.gap().setAdvertisingInterval(1000); /* 1000ms. */ _ble.gap().setAdvertisingTimeout(300); /* 16 * 1000ms. */ _ble.gap().startAdvertising(); #endif printf("Please connect to device\r\n"); /** This tells the stack to generate a pairingRequest event * which will require this application to respond before pairing * can proceed. Setting it to false will automatically accept * pairing. */ _ble.securityManager().setPairingRequestAuthorisation(true); }; /** This is called by Gap to notify the application we connected, * in our case it immediately requests a change in link security */ //virtual void onConnectionComplete(const ble::ConnectionCompleteEvent_t &event) virtual void onConnectionComplete(const Gap::ConnectionCallbackParams_t &event) { ble_error_t error; /* remember the device that connects to us now so we can connect to it * during the next demonstration */ memcpy(_peer_address, event.peerAddr, 6); printf("Connected to peer: "); print_address(event.peerAddr); _handle = event.handle; /* Request a change in link security. This will be done * indirectly by asking the master of the connection to * change it. Depending on circumstances different actions * may be taken by the master which will trigger events * which the applications should deal with. */ error = _ble.securityManager().setLinkSecurity( _handle, SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM ); if (error) { printf("Error during SM::setLinkSecurity %d\r\n", error); return; } }; }; /** A central device will scan, connect to a peer and request pairing. */ class SMDeviceCentral : public SMDevice { public: SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) : SMDevice(ble, event_queue, peer_address) { } virtual void start() { ble::ScanParameters params; ble_error_t error = _ble.gap().setScanParameters(params); if (error) { print_error(error, "Error in Gap::startScan %d\r\n"); return; } /* start scanning, results will be handled by onAdvertisingReport */ error = _ble.gap().startScan(); if (error) { print_error(error, "Error in Gap::startScan %d\r\n"); return; } printf("Please advertise\r\n"); printf("Scanning for: "); print_address(_peer_address); } private: /* Gap::EventHandler */ /** Look at scan payload to find a peer device and connect to it */ virtual void onAdvertisingReport(const Gap::AdvertisementCallbackParams_t &event) { /* don't bother with analysing scan result if we're already connecting */ if (_is_connecting) { return; } /* parse the advertising payload, looking for a discoverable device */ if (memcmp(event.peerAddr, _peer_address, sizeof(_peer_address)) == 0) { ble_error_t error = _ble.gap().stopScan(); if (error) { print_error(error, "Error caused by Gap::stopScan"); return; } ble::ConnectionParameters connection_params( ble::phy_t::LE_1M, ble::scan_interval_t(50), ble::scan_window_t(50), ble::conn_interval_t(50), ble::conn_interval_t(100), ble::slave_latency_t(0), ble::supervision_timeout_t(100) ); connection_params.setOwnAddressType(ble::own_address_type_t::RANDOM); error = _ble.gap().connect( event.getPeerAddressType(), event.getPeerAddress(), connection_params ); if (error) { print_error(error, "Error caused by Gap::connect"); return; } /* we may have already scan events waiting * to be processed so we need to remember * that we are already connecting and ignore them */ _is_connecting = true; return; } } /** This is called by Gap to notify the application we connected, * in our case it immediately request pairing */ virtual void onConnectionComplete(const Gap::ConnectionCallbackParams_t &event) { if (event.getStatus() == BLE_ERROR_NONE) { /* store the handle for future Security Manager requests */ _handle = event.getConnectionHandle(); printf("Connected\r\n"); /* in this example the local device is the master so we request pairing */ ble_error_t error = _ble.securityManager().requestPairing(_handle); if (error) { printf("Error during SM::requestPairing %d\r\n", error); return; } /* upon pairing success the application will disconnect */ } /* failed to connect - restart scan */ ble_error_t error = _ble.gap().startScan(); if (error) { print_error(error, "Error in Gap::startScan %d\r\n"); return; } }; }; #if MBED_CONF_APP_FILESYSTEM_SUPPORT bool create_filesystem() { static LittleFileSystem fs("fs"); /* replace this with any physical block device your board supports (like an SD card) */ static HeapBlockDevice bd(4096, 256); int err = bd.init(); if (err) { return false; } err = bd.erase(0, bd.size()); if (err) { return false; } err = fs.mount(&bd); if (err) { /* Reformat if we can't mount the filesystem */ printf("No filesystem found, formatting...\r\n"); err = fs.reformat(&bd); if (err) { return false; } } return true; } #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT #ifdef BLE_MAIN int main() { BLE& ble = BLE::Instance(); events::EventQueue queue; #if MBED_CONF_APP_FILESYSTEM_SUPPORT /* if filesystem creation fails or there is no filesystem the security manager * will fallback to storing the security database in memory */ if (!create_filesystem()) { printf("Filesystem creation failed, will use memory storage\r\n"); } #endif while(1) { { printf("\r\n PERIPHERAL \r\n\r\n"); SMDevicePeripheral peripheral(ble, queue, peer_address); peripheral.run(); } { printf("\r\n CENTRAL \r\n\r\n"); SMDeviceCentral central(ble, queue, peer_address); central.run(); } } return 0; } #endif #endif