Mbed OS 文档翻译 之 参考(API(蓝牙(SecurityManager)))

SecurityManager

SecurityManager 处理蓝牙低功耗链路的身份验证和加密。配对和任选的粘合过程提供了这一点。SecurityManager 通过保存配对信息并在后续重新连接时重新使用来实现绑定。这节省了时间,因为不必再次执行配对。

配对过程可以产生一组在当前或后续连接期间使用的密钥。SecurityManager 处理这些,它们包括长期加密密钥(LTK),身份解析密钥(IRK)和连接签名解析密钥(CSRK)。SecurityManager 使用 LTK 加密后续连接,而无需再次配对。链路控制器使用 IRK 来识别使用随机可解析地址的对等体。该应用程序使用 CSRK 对签名数据进行签名和身份验证。

配对过程可以提供中间人保护(MITM)。SecurityManager 通过各种方式实现这一点,包括带外通信,具体取决于本地和对等设备的功能。

如果可能,SecurityManager 会永久存储密钥,以加快后续连接的安全请求。

安全请求可以基于属性要求显式地来自用户应用程序或者来自 GATT 服务器。

配对

根据您的要求和应用程序提供的功能,有几种方法可以在配对期间提供不同级别的安全性。该过程首先使用新连接的默认选项初始化 SecurityManager。您可以稍后更改每个链接或全局的某些设置。

init() 函数中的重要设置是 MITM 要求和 IO 功能。MITM 保护可以防止一个设备通过同时与两个设备配对来冒充其他设备的攻击。您可以通过独立通道在设备之间共享信息来实现此保护。两种设备的 IO 功能决定了使用的算法。有关详细信息,请参阅 BLUETOOTH SPECIFICATION 版本 5.0 | 第 3 卷,第 H 部分 - 2.3.5.1。您可以在使用 setIoCapability() 初始化后更改 IO 功能。这对所有后续配对生效。

依赖于椭圆曲线加密的安全连接提供最安全的配对。对安全连接的支持取决于支持它的两侧的栈和控制器。如果任何一方不支持它,则使用传统配对。这是较旧的配对标准。如果您需要更高的安全性,可以通过调用 allowLegacyPairing(false);来禁用旧版配对。

配对中使用的带外(OOB)数据

通过 IO 功能共享此信息意味着用户交互,这会限制由于您可以预期传输的数据量限制而导致的保护程度。另一种解决方案是使用带外(OOB)通信来传输该数据。OOB 通信可以发送更多数据并使 MITM 攻击不太可能成功。应用程序必须交换 OOB 数据并将其提供给 SecurityManager。使用 setOOBDataUsage() 表示您要使用它。通过相同的调用,您可以设置用于传输 OOB 数据的通信通道本身是否可以抵御 MITM 保护 - 这将设置使用此数据的配对实现的链路安全级别。

签名

应用程序可能需要一定程度的安全性,从而确保数据传输来自可靠来源。您可以通过加密链接来实现此目的,这也提供了额外的机密性。当设备保持连接时加密是一个不错的选择,但如果设备仅定期连接以传输数据,则由于需要加密链路而引入延迟。如果您不需要机密性,GATT 服务器可能允许写入通过未加密的链接进行,但通过每个数据包中存在的签名进行身份验证。此签名依赖于在发送任何签名数据包之前在配对期间向对等方发送签名密钥。

持久性的安全信息

SecurityManager 在活动链接上存储其操作所需的所有数据。根据设备上可用的资源,它还存储已断开连接的设备的数据,这些设备已粘合,可在重新连接时重复使用。如果应用程序初始化了文件系统并且 SecurityManager 在 init() 调用期间收到了文件路径,则 SecurityManager 还可以在重置之间提供数据持久性。您必须通过调用 preserveBondingStateOnReset() 来启用它。如果异常终止,持久性可能会失败。如果资源太有限,SecurityManager 也可能会回退到非持久性实现。

如何使用

在调用任何其他 SecurityManager 函数之前,使用您选择的设置调用 init()。

SecurityManager 通过事件与您的应用程序通信。这些触发器必须通过调用 setSecurityManagerEventHandler() 函数来调用 EventHandler 中的调用。

最重要的过程是配对。您可以通过调用 requestPairing() 手动触发此操作。配对也可能是因为需要加密的应用程序通过调用 setLinkEncryption() 或通过 requestAuthentication() 需要 MITM 保护的应用程序。

您可以使用 setLinkSecurity() 隐式调用所有这些,以设置链接所需的安全性。SecurityManager 会触发实现设置安全级别所需的过程。您只能升级安全级别。要求 SecurityManager 的安全级别低于现有安全级别,但不会失败,但会导致通过当前级别的 linkEncryptionResult() 通知应用程序的事件(保持不变)。

选择的配对算法取决于 IO 功能和 OOB 使用设置。它们会生成适当的事件,EventHandler 必须处理这些事件。如果您的事件处理程序不支持所有调用,则不得设置 IO 功能或以触发它们的方式设置 OOB 使用,否则配对失败(通常通过超时)。

最简单的示例是没有 IO 功能的设备配对,也没有可用的 OOB 数据。这不提供任何 MITM 保护。配对(隐式触发或显式调用)导致在对等方调用 pairingRequest() 上生成事件。事件处理程序必须做出决定(在应用程序本身或基于用户交互)是否接受配对并调用 acceptPairing() 或 cancelPairing()。在 EventHandler 中调用 pairingResult() 的事件在两个对等体上传递结果。

SecurityManager 类参考

SecurityManager 类参考

数据结构
class   EventHandler
公共类型
enum   Keypress_t {
  KEYPRESS_STARTED, KEYPRESS_ENTERED, KEYPRESS_ERASED, KEYPRESS_CLEARED,
  KEYPRESS_COMPLETED
}
enum   SecurityMode_t {
  SECURITY_MODE_NO_ACCESS, SECURITY_MODE_ENCRYPTION_OPEN_LINK, SECURITY_MODE_ENCRYPTION_NO_MITM, SECURITY_MODE_ENCRYPTION_WITH_MITM,
  SECURITY_MODE_SIGNED_NO_MITM, SECURITY_MODE_SIGNED_WITH_MITM
}
enum   LinkSecurityStatus_t { NOT_ENCRYPTED, ENCRYPTION_IN_PROGRESS, ENCRYPTED }
  Defines possible security status or states. More...
enum   SecurityIOCapabilities_t {
  IO_CAPS_DISPLAY_ONLY = 0x00, IO_CAPS_DISPLAY_YESNO = 0x01, IO_CAPS_KEYBOARD_ONLY = 0x02, IO_CAPS_NONE = 0x03,
  IO_CAPS_KEYBOARD_DISPLAY = 0x04
}
enum   SecurityCompletionStatus_t {
  SEC_STATUS_SUCCESS = 0x00, SEC_STATUS_TIMEOUT = 0x01, SEC_STATUS_PDU_INVALID = 0x02, SEC_STATUS_PASSKEY_ENTRY_FAILED = 0x81,
  SEC_STATUS_OOB_NOT_AVAILABLE = 0x82, SEC_STATUS_AUTH_REQ = 0x83, SEC_STATUS_CONFIRM_VALUE = 0x84, SEC_STATUS_PAIRING_NOT_SUPP = 0x85,
  SEC_STATUS_ENC_KEY_SIZE = 0x86, SEC_STATUS_SMP_CMD_UNSUPPORTED = 0x87, SEC_STATUS_UNSPECIFIED = 0x88, SEC_STATUS_REPEATED_ATTEMPTS = 0x89,
  SEC_STATUS_INVALID_PARAMS = 0x8A, SEC_STATUS_DHKEY_CHECK_FAILED = 0x8B, SEC_STATUS_COMPARISON_FAILED = 0x8C
}
typedef uint8_t  Passkey_t[PASSKEY_LEN]
typedef FunctionPointerWithContext< const SecurityManager * >  SecurityManagerShutdownCallback_t
typedef CallChainOfFunctionPointersWithContext< const SecurityManager * >  SecurityManagerShutdownCallbackChain_t
typedef void(*  HandleSpecificEvent_t) (ble::connection_handle_t connectionHandle)
typedef void(*  SecuritySetupInitiatedCallback_t) (ble::connection_handle_t, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps)
typedef void(*  SecuritySetupCompletedCallback_t) (ble::connection_handle_t, SecurityCompletionStatus_t status)
typedef void(*  LinkSecuredCallback_t) (ble::connection_handle_t connectionHandle, SecurityMode_t securityMode)
typedef void(*  PasskeyDisplayCallback_t) (ble::connection_handle_t connectionHandle, const Passkey_t passkey)
公共成员函数
virtual ble_error_t  init (bool enableBonding=true, bool requireMITM=true, SecurityIOCapabilities_t iocaps=IO_CAPS_NONE, const Passkey_t passkey=NULL, bool signing=true, const char *dbFilepath=NULL)
virtual ble_error_t  setDatabaseFilepath (const char *dbFilepath=NULL)
virtual ble_error_t  reset (void)
virtual ble_error_t  preserveBondingStateOnReset (bool enable)
virtual ble_error_t  purgeAllBondingState (void)
virtual ble_error_t  generateWhitelistFromBondTable (Gap::Whitelist_t *whitelist) const
virtual ble_error_t  requestPairing (ble::connection_handle_t connectionHandle)
virtual ble_error_t  acceptPairingRequest (ble::connection_handle_t connectionHandle)
virtual ble_error_t  cancelPairingRequest (ble::connection_handle_t connectionHandle)
virtual ble_error_t  setPairingRequestAuthorisation (bool required=true)
virtual ble_error_t  allowLegacyPairing (bool allow=true)
virtual ble_error_t  getSecureConnectionsSupport (bool *enabled)
virtual ble_error_t  setIoCapability (SecurityIOCapabilities_t iocaps)
virtual ble_error_t  setDisplayPasskey (const Passkey_t passkey)
virtual ble_error_t  setLinkSecurity (ble::connection_handle_t connectionHandle, SecurityMode_t securityMode)
virtual ble_error_t  setKeypressNotification (bool enabled=true)
virtual ble_error_t  enableSigning (ble::connection_handle_t connectionHandle, bool enabled=true)
virtual ble_error_t  setHintFutureRoleReversal (bool enable=true)
virtual ble_error_t  getLinkEncryption (ble::connection_handle_t connectionHandle, ble::link_encryption_t *encryption)
virtual ble_error_t  setLinkEncryption (ble::connection_handle_t connectionHandle, ble::link_encryption_t encryption)
virtual ble_error_t  setEncryptionKeyRequirements (uint8_t minimumByteSize, uint8_t maximumByteSize)
virtual ble_error_t  requestAuthentication (ble::connection_handle_t connectionHandle)
virtual ble_error_t  generateOOB (const ble::address_t *address)
virtual ble_error_t  setOOBDataUsage (ble::connection_handle_t connectionHandle, bool useOOB, bool OOBProvidesMITM=true)
virtual ble_error_t  confirmationEntered (ble::connection_handle_t connectionHandle, bool confirmation)
virtual ble_error_t  passkeyEntered (ble::connection_handle_t connectionHandle, Passkey_t passkey)
virtual ble_error_t  sendKeypressNotification (ble::connection_handle_t connectionHandle, Keypress_t keypress)
virtual ble_error_t  legacyPairingOobReceived (const ble::address_t *address, const ble::oob_tk_t *tk)
virtual ble_error_t  oobReceived (const ble::address_t *address, const ble::oob_lesc_value_t *random, const ble::oob_confirm_t *confirm)
virtual ble_error_t  getSigningKey (ble::connection_handle_t connectionHandle, bool authenticated)
void  onShutdown (const SecurityManagerShutdownCallback_t &callback)
template<typename T >
void  onShutdown (T *objPtr, void(T::*memberPtr)(const SecurityManager *))
SecurityManagerShutdownCallbackChain_t onShutdown ()
virtual void  setSecurityManagerEventHandler (EventHandler *handler)
virtual ble_error_t  getAddressesFromBondTable (Gap::Whitelist_t &addresses) const
ble_error_t  getLinkSecurity (ble::connection_handle_t connectionHandle, LinkSecurityStatus_t *securityStatus)
virtual void  onSecuritySetupInitiated (SecuritySetupInitiatedCallback_t callback)
virtual void  onSecuritySetupCompleted (SecuritySetupCompletedCallback_t callback)
virtual void  onLinkSecured (LinkSecuredCallback_t callback)
virtual void  onSecurityContextStored (HandleSpecificEvent_t callback)
virtual void  onPasskeyDisplay (PasskeyDisplayCallback_t callback)
void  processSecuritySetupInitiatedEvent (ble::connection_handle_t connectionHandle, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps)
void  processSecuritySetupCompletedEvent (ble::connection_handle_t connectionHandle, SecurityCompletionStatus_t status)
void  processLinkSecuredEvent (ble::connection_handle_t connectionHandle, SecurityMode_t securityMode)
void  processSecurityContextStoredEvent (ble::connection_handle_t connectionHandle)
void  processPasskeyDisplayEvent (ble::connection_handle_t connectionHandle, const Passkey_t passkey)
静态公共属性
static const unsigned  PASSKEY_LEN = 6
受保护的属性
EventHandler eventHandler
LegacyEventHandler  defaultEventHandler

SecurityManager 示例

SecurityManager 示例演示了中央连接和外围连接,执行基本配对和设置链接安全性。

main.cpp                                                                                                                                                 导入到 Mbed IDE

/* 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"

/** 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.
 */
class SMDevice : private mbed::NonCopyable<SMDevice>,
                 public SecurityManager::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 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 */
    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");
        }

        /* disconnect in 500 ms */
        _event_queue.call_in(
            500, &_ble.gap(),
            &Gap::disconnect, _handle, Gap::REMOTE_USER_TERMINATED_CONNECTION
        );
    }

    /** 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");
        }
    }

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;
        }

        /* If the security manager is required this needs to be called before any
         * calls to the Security manager happen. */
        error = _ble.securityManager().init();

        if (error) {
            printf("Error during init %d\r\n", error);
            return;
        }

        /* 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 */
    virtual void on_connect(const Gap::ConnectionCallbackParams_t *connection_event) = 0;

    /** This is called by Gap to notify the application we disconnected,
     *  in our case it ends the demonstration. */
    void on_disconnect(const Gap::DisconnectionCallbackParams_t *event)
    {
        printf("Disconnected - demonstration ended \r\n");
        _event_queue.break_dispatch();
    };

    /** End demonstration unexpectedly. Called if timeout is reached during advertising,
     * scanning or connection initiation */
    void 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 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:
    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 */

        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;
        }

        /** 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 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));

        /* 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. */
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()
    {
        /* 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);

        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 on_scan(const Gap::AdvertisementCallbackParams_t *params)
    {
        /* 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 */
        for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
            /* The advertising payload is a collection of key/value records where
             * byte 0: length of the record excluding this byte
             * byte 1: The key, it is the type of the data
             * byte [2..N] The value. N is equal to byte0 - 1 */
            const uint8_t record_length = params->advertisingData[i];
            if (record_length == 0) {
                continue;
            }

            /* 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->addressType,
                    NULL, NULL
                );

                if (error) {
                    printf("Error during Gap::connect %d\r\n", error);
                    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;
            }

            i += record_length;
        }
    };

    /** This is called by Gap to notify the application we connected,
     *  in our case it immediately request pairing */
    virtual void 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);

        if (error) {
            printf("Error during SM::requestPairing %d\r\n", error);
            return;
        }

        /* upon pairing success the application will disconnect */
    };
};

int main()
{
    BLE& ble = BLE::Instance();
    events::EventQueue queue;

    {
        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;
}

猜你喜欢

转载自blog.csdn.net/u012325601/article/details/82081508