mbed-os/connectivity/FEATURE_BLE/source/impl/include/ble/internal/PalGapImpl.h

542 lines
17 KiB
C++

/* mbed Microcontroller Library
* Copyright (c) 2006-2020 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
#ifndef IMPL_PAL_GAP_
#define IMPL_PAL_GAP_
#include "source/pal/PalGap.h"
#include "dm_api.h"
namespace ble {
/**
* Implementation of ble::PalGap for the Cordio stack.
*/
class PalGap : public interface::PalGap {
public:
PalGap() : _pal_event_handler(NULL), use_active_scanning(false) { };
~PalGap() { };
bool is_feature_supported(
ble::controller_supported_features_t feature
);
ble_error_t initialize();
ble_error_t terminate();
address_t get_device_address();
address_t get_random_address();
ble_error_t set_random_address(const address_t& address);
ble_error_t set_advertising_parameters(
uint16_t advertising_interval_min,
uint16_t advertising_interval_max,
advertising_type_t advertising_type,
own_address_type_t own_address_type,
advertising_peer_address_type_t peer_address_type,
const address_t& peer_address,
advertising_channel_map_t advertising_channel_map,
advertising_filter_policy_t advertising_filter_policy
);
ble_error_t set_advertising_data(
uint8_t advertising_data_length,
const advertising_data_t& advertising_data
);
ble_error_t set_scan_response_data(
uint8_t scan_response_data_length,
const advertising_data_t& scan_response_data
);
ble_error_t advertising_enable(bool enable);
ble_error_t set_scan_parameters(
bool active_scanning,
uint16_t scan_interval,
uint16_t scan_window,
own_address_type_t own_address_type,
scanning_filter_policy_t filter_policy
);
ble_error_t scan_enable(
bool enable,
bool filter_duplicates
);
ble_error_t create_connection(
uint16_t scan_interval,
uint16_t scan_window,
initiator_policy_t initiator_policy,
connection_peer_address_type_t peer_address_type,
const address_t& peer_address,
own_address_type_t own_address_type,
uint16_t connection_interval_min,
uint16_t connection_interval_max,
uint16_t connection_latency,
uint16_t supervision_timeout,
uint16_t minimum_connection_event_length,
uint16_t maximum_connection_event_length
);
ble_error_t cancel_connection_creation();
uint8_t read_white_list_capacity();
ble_error_t clear_whitelist();
ble_error_t add_device_to_whitelist(
whitelist_address_type_t address_type,
address_t address
);
ble_error_t remove_device_from_whitelist(
whitelist_address_type_t address_type,
address_t address
);
ble_error_t connection_parameters_update(
connection_handle_t connection,
uint16_t connection_interval_min,
uint16_t connection_interval_max,
uint16_t connection_latency,
uint16_t supervision_timeout,
uint16_t minimum_connection_event_length,
uint16_t maximum_connection_event_length
);
ble_error_t accept_connection_parameter_request(
connection_handle_t connection_handle,
uint16_t interval_min,
uint16_t interval_max,
uint16_t latency,
uint16_t supervision_timeout,
uint16_t minimum_connection_event_length,
uint16_t maximum_connection_event_length
);
ble_error_t reject_connection_parameter_request(
connection_handle_t connection_handle,
hci_error_code_t rejection_reason
);
ble_error_t disconnect(
connection_handle_t connection,
local_disconnection_reason_t disconnection_reason
);
bool is_privacy_supported();
ble_error_t set_address_resolution(
bool enable
);
ble_error_t read_phy(connection_handle_t connection);
ble_error_t set_preferred_phys(
const phy_set_t& tx_phys,
const phy_set_t& rx_phys
);
ble_error_t set_phy(
connection_handle_t connection,
const phy_set_t& tx_phys,
const phy_set_t& rx_phys,
coded_symbol_per_bit_t coded_symbol
);
// singleton of the ARM Cordio client
static PalGap& get_gap();
/**
* Callback which handle wsfMsgHdr_t and forward them to emit_gap_event.
*/
static void gap_handler(const wsfMsgHdr_t* msg);
ble_error_t set_advertising_set_random_address(
advertising_handle_t advertising_handle,
const address_t &address
);
ble_error_t set_extended_advertising_parameters(
advertising_handle_t advertising_handle,
advertising_event_properties_t event_properties,
advertising_interval_t primary_advertising_interval_min,
advertising_interval_t primary_advertising_interval_max,
advertising_channel_map_t primary_advertising_channel_map,
own_address_type_t own_address_type,
advertising_peer_address_type_t peer_address_type,
const address_t &peer_address,
advertising_filter_policy_t advertising_filter_policy,
advertising_power_t advertising_power,
phy_t primary_advertising_phy,
uint8_t secondary_advertising_max_skip,
phy_t secondary_phy,
uint8_t advertising_sid,
bool scan_request_notification
);
ble_error_t set_periodic_advertising_parameters(
advertising_handle_t advertising_handle,
periodic_advertising_interval_t periodic_advertising_min,
periodic_advertising_interval_t periodic_advertising_max,
bool advertise_power
);
ble_error_t set_extended_advertising_data(
advertising_handle_t advertising_handle,
advertising_fragment_description_t operation,
bool minimize_fragmentation,
uint8_t advertising_data_size,
const uint8_t *advertising_data
);
ble_error_t set_periodic_advertising_data(
advertising_handle_t advertising_handle,
advertising_fragment_description_t fragment_description,
uint8_t advertising_data_size,
const uint8_t *advertising_data
);
ble_error_t set_extended_scan_response_data(
advertising_handle_t advertising_handle,
advertising_fragment_description_t operation,
bool minimize_fragmentation,
uint8_t scan_response_data_size,
const uint8_t *scan_response_data
);
ble_error_t extended_advertising_enable(
bool enable,
uint8_t number_of_sets,
const advertising_handle_t *handles,
const uint16_t *durations,
const uint8_t *max_extended_advertising_events
);
ble_error_t periodic_advertising_enable(
bool enable,
advertising_handle_t advertising_handle
);
uint16_t get_maximum_advertising_data_length();
uint16_t get_maximum_connectable_advertising_data_length();
uint8_t get_maximum_hci_advertising_data_length();
uint8_t get_max_number_of_advertising_sets();
ble_error_t remove_advertising_set(
advertising_handle_t advertising_handle
);
ble_error_t clear_advertising_sets();
ble_error_t set_extended_scan_parameters(
own_address_type_t own_address_type,
scanning_filter_policy_t filter_policy,
phy_set_t scanning_phys,
const bool *active_scanning,
const uint16_t *scan_interval,
const uint16_t *scan_window
);
ble_error_t extended_scan_enable(
bool enable,
duplicates_filter_t filter_duplicates,
uint16_t duration,
uint16_t period
);
ble_error_t periodic_advertising_create_sync(
bool use_periodic_advertiser_list,
uint8_t advertising_sid,
peer_address_type_t peer_address_type,
const address_t &peer_address,
uint16_t allowed_skip,
uint16_t sync_timeout
);
ble_error_t cancel_periodic_advertising_create_sync();
ble_error_t periodic_advertising_terminate_sync(
sync_handle_t sync_handle
);
ble_error_t add_device_to_periodic_advertiser_list(
advertising_peer_address_type_t advertiser_address_type,
const address_t &advertiser_address,
uint8_t advertising_sid
);
ble_error_t remove_device_from_periodic_advertiser_list(
advertising_peer_address_type_t advertiser_address_type,
const address_t &advertiser_address,
uint8_t advertising_sid
);
ble_error_t clear_periodic_advertiser_list();
uint8_t read_periodic_advertiser_list_size();
ble_error_t extended_create_connection(
initiator_policy_t initiator_policy,
own_address_type_t own_address_type,
peer_address_type_t peer_address_type,
const address_t &peer_address,
phy_set_t initiating_phys,
const uint16_t *scan_intervals,
const uint16_t *scan_windows,
const uint16_t *connection_intervals_min,
const uint16_t *connection_intervals_max,
const uint16_t *connection_latencies,
const uint16_t *supervision_timeouts,
const uint16_t *minimum_connection_event_lengths,
const uint16_t *maximum_connection_event_lengths
);
void when_gap_event_received(mbed::Callback<void(const GapEvent &)> cb);
/**
* Sets the event handler that us called by the PAL porters to notify the stack of events
* which will in turn be passed onto the user application when appropriate.
*
* @param[in] event_handler the new event handler interface implementation. Memory
* owned by caller who is responsible for updating this pointer if interface changes.
*/
void set_event_handler(PalGapEventHandler *event_handler);
PalGapEventHandler *get_event_handler();
private:
/**
* Called this function whenever the LE subsystem
* generate a PalGap event.
*
* @param gap_event The event to emit to higher layer.
*/
void emit_gap_event(const GapEvent &gap_event)
{
if (_gap_event_cb) {
_gap_event_cb(gap_event);
}
}
/**
* T shall define a can_convert and convert function and a type
*/
template<typename T>
static bool event_handler(const wsfMsgHdr_t* msg);
/**
* Traits defining can_convert for events.
*/
template<uint8_t EventID>
struct MessageConverter {
static bool can_convert(const wsfMsgHdr_t* msg) {
if (msg->event == EventID) {
return true;
}
return false;
}
};
struct ConnectionCompleteMessageConverter : public MessageConverter<DM_CONN_OPEN_IND> {
typedef hciLeConnCmplEvt_t type;
static GapConnectionCompleteEvent convert(const hciLeConnCmplEvt_t* conn_evt) {
return GapConnectionCompleteEvent(
conn_evt->status,
// note the usage of the stack handle, not the HCI handle
conn_evt->hdr.param,
(connection_role_t::type) conn_evt->role,
(peer_address_type_t::type) conn_evt->addrType,
conn_evt->peerAddr,
conn_evt->connInterval,
conn_evt->connLatency,
conn_evt->supTimeout,
conn_evt->localRpa,
conn_evt->peerRpa
);
}
};
struct GapAdvertisingReportMessageConverter : public MessageConverter<DM_SCAN_REPORT_IND> {
typedef hciLeAdvReportEvt_t type;
struct CordioGapAdvertisingReportEvent : public GapAdvertisingReportEvent {
CordioGapAdvertisingReportEvent(const advertising_t& advertising) :
GapAdvertisingReportEvent(), advertising(advertising) {
}
virtual ~CordioGapAdvertisingReportEvent() { }
virtual uint8_t size() const {
return 1;
}
virtual advertising_t operator[](uint8_t i) const {
return advertising;
}
advertising_t advertising;
};
static CordioGapAdvertisingReportEvent convert(const hciLeAdvReportEvt_t *scan_report) {
GapAdvertisingReportEvent::advertising_t advertising = {
(received_advertising_type_t::type) scan_report->eventType,
(connection_peer_address_type_t::type) scan_report->addrType,
scan_report->addr,
make_const_Span(scan_report->pData, scan_report->len),
scan_report->rssi
};
return CordioGapAdvertisingReportEvent(advertising);
}
};
struct DisconnectionMessageConverter : public MessageConverter<DM_CONN_CLOSE_IND> {
typedef hciDisconnectCmplEvt_t type;
static GapDisconnectionCompleteEvent convert(const hciDisconnectCmplEvt_t* disc_evt) {
return GapDisconnectionCompleteEvent(
disc_evt->status,
// note the usage of the stack handle, not the HCI handle
disc_evt->hdr.param,
disc_evt->reason
);
}
};
struct ConnectionUpdateMessageConverter : public MessageConverter<DM_CONN_UPDATE_IND> {
typedef hciLeConnUpdateCmplEvt_t type;
static GapConnectionUpdateEvent convert(const hciLeConnUpdateCmplEvt_t* evt) {
return GapConnectionUpdateEvent(
evt->status,
evt->hdr.param,
evt->connInterval,
evt->connLatency,
evt->supTimeout
);
}
};
struct RemoteConnectionParameterRequestMessageConverter : public MessageConverter<DM_REM_CONN_PARAM_REQ_IND> {
typedef hciLeRemConnParamReqEvt_t type;
static GapRemoteConnectionParameterRequestEvent convert(const hciLeRemConnParamReqEvt_t* evt) {
return GapRemoteConnectionParameterRequestEvent(
evt->hdr.param,
evt->intervalMin,
evt->intervalMax,
evt->latency,
evt->timeout
);
}
};
/* Cordio requires the call to DmConnAccept to properly catch direct advertising timeout.
* This call returns a connection ID and expect the peer address and the peer address type.
* This PAL following HCI expectations, these information are not present when the higher
* level calls the function to enable advertising.
* This data structure caches these informations and use them in case of direct advertising.
* Similarly, direct advertising timeout doesn't trigger an advertising timeout instead it
* triggers a disconnection with the status 60. Information on running direct advertising
* is stored here.
*/
struct direct_adv_cb_t {
direct_adv_cb_t() :
peer_address_type(advertising_peer_address_type_t::PUBLIC),
state(free)
{}
address_t peer_address;
advertising_peer_address_type_t peer_address_type;
advertising_handle_t advertising_handle;
connection_handle_t connection_handle;
bool low_duty_cycle;
enum {
free = 0,
pending,
running
} state;
};
/* Predicate expect a const reference to a direct_adv_cb_t
* It must returns true if the criteria are met and false otherwise. */
template<typename Predicate>
direct_adv_cb_t* get_adv_cb(const Predicate& predicate);
direct_adv_cb_t* get_running_direct_adv_cb(advertising_handle_t adv_handle);
direct_adv_cb_t* get_running_conn_direct_adv_cb(connection_handle_t adv_handle);
direct_adv_cb_t* get_pending_direct_adv_cb(advertising_handle_t adv_handle);
direct_adv_cb_t* get_free_direct_adv_cb();
ble_error_t update_direct_advertising_parameters(
advertising_handle_t advertising_handle,
uint8_t advertising_type,
address_t peer_address,
advertising_peer_address_type_t peer_address_type
);
/**
* Create an ALL_PHYS parameter used in LE Set PHY Command
* and LE Set Default PHY Command.
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E - 7.8.49
*/
static uint8_t create_all_phys_value(
const phy_set_t &tx_phys,
const phy_set_t &rx_phys
)
{
/* if phy set is empty set corresponding all_phys bit to 1 */
uint8_t all_phys = 0;
if (tx_phys.value() == 0) {
all_phys |= 0x01;
}
if (rx_phys.value() == 0) {
all_phys |= 0x02;
}
return all_phys;
}
private:
PalGapEventHandler* _pal_event_handler;
address_t device_random_address;
bool use_active_scanning;
uint8_t extended_scan_type[3];
phy_set_t scanning_phys;
direct_adv_cb_t direct_adv_cb[DM_NUM_ADV_SETS];
/**
* Callback called when an event is emitted by the LE subsystem.
*/
mbed::Callback<void(const GapEvent &)> _gap_event_cb;
};
} // ble
#endif /* IMPL_PAL_GAP_ */