mirror of https://github.com/ARMmbed/mbed-os.git
BLE: Implement Advertising extension and Periodic Advertising on Cordio (WIP)
parent
8fa62ec719
commit
b9d7e63911
|
@ -153,6 +153,145 @@ public:
|
|||
*/
|
||||
static void gap_handler(const wsfMsgHdr_t* msg);
|
||||
|
||||
virtual ble_error_t set_advertising_set_random_address(
|
||||
advertising_handle_t advertising_handle,
|
||||
const address_t &address
|
||||
);
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual ble_error_t periodic_advertising_enable(
|
||||
bool enable,
|
||||
advertising_handle_t advertising_handle
|
||||
);
|
||||
|
||||
virtual uint16_t get_maximum_advertising_data_length();
|
||||
|
||||
virtual uint8_t get_max_number_of_advertising_sets();
|
||||
|
||||
virtual ble_error_t remove_advertising_set(
|
||||
advertising_handle_t advertising_handle
|
||||
);
|
||||
|
||||
virtual ble_error_t clear_advertising_sets();
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual ble_error_t extended_scan_enable(
|
||||
bool enable,
|
||||
duplicates_filter_t filter_duplicates,
|
||||
uint16_t duration,
|
||||
uint16_t period
|
||||
);
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual ble_error_t cancel_periodic_advertising_create_sync();
|
||||
|
||||
virtual ble_error_t periodic_advertising_terminate_sync(
|
||||
sync_handle_t sync_handle
|
||||
);
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
virtual ble_error_t clear_periodic_advertiser_list();
|
||||
|
||||
virtual uint8_t read_periodic_advertiser_list_size();
|
||||
|
||||
virtual 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
|
||||
);
|
||||
|
||||
private:
|
||||
/**
|
||||
* T shall define a can_convert and convert function and a type
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "CordioPalGap.h"
|
||||
#include "hci_api.h"
|
||||
#include "dm_api.h"
|
||||
|
||||
namespace ble {
|
||||
namespace pal {
|
||||
|
@ -458,6 +459,418 @@ bool Gap::event_handler(const wsfMsgHdr_t* msg) {
|
|||
return false;
|
||||
}
|
||||
|
||||
ble_error_t Gap::set_advertising_set_random_address(
|
||||
advertising_handle_t advertising_handle,
|
||||
const address_t &address
|
||||
)
|
||||
{
|
||||
DmAdvSetRandAddr(advertising_handle, address.data());
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::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
|
||||
)
|
||||
{
|
||||
DmAdvSetInterval(
|
||||
advertising_handle,
|
||||
primary_advertising_interval_min,
|
||||
primary_advertising_interval_max
|
||||
);
|
||||
|
||||
DmAdvSetAddrType(own_address_type.value());
|
||||
|
||||
DmAdvSetChannelMap(
|
||||
advertising_handle,
|
||||
primary_advertising_channel_map.value()
|
||||
);
|
||||
|
||||
DmDevSetExtFilterPolicy(
|
||||
advertising_handle,
|
||||
DM_FILT_POLICY_MODE_ADV,
|
||||
advertising_filter_policy.value()
|
||||
);
|
||||
|
||||
DmAdvScanReqNotifEnable(advertising_handle, scan_request_notification);
|
||||
|
||||
DmAdvSetPhyParam(
|
||||
advertising_handle,
|
||||
primary_advertising_phy.value(),
|
||||
secondary_advertising_max_skip,
|
||||
secondary_phy.value()
|
||||
);
|
||||
|
||||
DmAdvIncTxPwr(
|
||||
advertising_handle,
|
||||
event_properties.include_tx_power,
|
||||
advertising_power
|
||||
);
|
||||
|
||||
DmAdvUseLegacyPdu(advertising_handle, event_properties.use_legacy_pdu);
|
||||
DmAdvOmitAdvAddr(advertising_handle, event_properties.omit_advertisser_address);
|
||||
|
||||
DmAdvConfig(
|
||||
advertising_handle,
|
||||
event_properties.value(), // TODO: use the raw value here ???
|
||||
peer_address_type.value(),
|
||||
const_cast<uint8_t *>(peer_address.data())
|
||||
);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::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
|
||||
)
|
||||
{
|
||||
DmPerAdvIncTxPwr(advertising_handle, advertise_power);
|
||||
DmPerAdvSetInterval(
|
||||
advertising_handle,
|
||||
periodic_advertising_min,
|
||||
periodic_advertising_max
|
||||
);
|
||||
DmPerAdvConfig(advertising_handle);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::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
|
||||
)
|
||||
{
|
||||
uint8_t frag_pref = minimize_fragmentation ?
|
||||
HCI_ADV_DATA_FRAG_PREF_NO_FRAG :
|
||||
HCI_ADV_DATA_FRAG_PREF_FRAG;
|
||||
|
||||
DmAdvSetFragPref(advertising_handle, frag_pref);
|
||||
|
||||
DmAdvSetData(
|
||||
advertising_handle,
|
||||
operation.value(),
|
||||
DM_DATA_LOC_ADV,
|
||||
advertising_data_size,
|
||||
const_cast<uint8_t *>(advertising_data)
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::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
|
||||
)
|
||||
{
|
||||
DmPerAdvSetData(
|
||||
advertising_handle,
|
||||
fragment_description.value(),
|
||||
advertising_data_size,
|
||||
const_cast<uint8_t *>(advertising_data)
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::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
|
||||
)
|
||||
{
|
||||
uint8_t frag_pref = minimize_fragmentation ?
|
||||
HCI_ADV_DATA_FRAG_PREF_NO_FRAG :
|
||||
HCI_ADV_DATA_FRAG_PREF_FRAG;
|
||||
|
||||
DmAdvSetFragPref(advertising_handle, frag_pref);
|
||||
|
||||
DmAdvSetData(
|
||||
advertising_handle,
|
||||
operation.value(),
|
||||
DM_DATA_LOC_SCAN,
|
||||
scan_response_data_size,
|
||||
const_cast<uint8_t *>(scan_response_data)
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::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
|
||||
)
|
||||
{
|
||||
if (enable) {
|
||||
uint16_t* durations_ms = new uint16_t[number_of_sets];
|
||||
for (size_t i = 0; i < number_of_sets; ++i) {
|
||||
uint32_t r = durations[i] * 10;
|
||||
durations_ms[i] = r > 0xFFFF ? 0xFFFF : r;
|
||||
}
|
||||
|
||||
DmAdvStart(
|
||||
number_of_sets,
|
||||
const_cast<uint8_t *>(handles),
|
||||
durations_ms,
|
||||
const_cast<uint8_t *>(max_extended_advertising_events)
|
||||
);
|
||||
|
||||
delete[] durations_ms;
|
||||
} else {
|
||||
DmAdvStop(
|
||||
number_of_sets,
|
||||
const_cast<uint8_t *>(handles)
|
||||
);
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::periodic_advertising_enable(
|
||||
bool enable,
|
||||
advertising_handle_t advertising_handle
|
||||
)
|
||||
{
|
||||
if (enable) {
|
||||
DmPerAdvStart(advertising_handle);
|
||||
} else {
|
||||
DmPerAdvStop(advertising_handle);
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
uint16_t Gap::get_maximum_advertising_data_length()
|
||||
{
|
||||
return HciGetMaxAdvDataLen();
|
||||
}
|
||||
|
||||
uint8_t Gap::get_max_number_of_advertising_sets()
|
||||
{
|
||||
return HciGetNumSupAdvSets();
|
||||
}
|
||||
|
||||
ble_error_t Gap::remove_advertising_set(advertising_handle_t advertising_handle)
|
||||
{
|
||||
DmAdvRemoveAdvSet(advertising_handle);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::clear_advertising_sets()
|
||||
{
|
||||
DmAdvClearAdvSets();
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::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
|
||||
)
|
||||
{
|
||||
DmScanSetAddrType(own_address_type.value());
|
||||
|
||||
// TODO: use/store filter policy
|
||||
// TODO: use/store active scanning
|
||||
// TODO: store scanning_phys
|
||||
|
||||
DmScanSetInterval(
|
||||
scanning_phys.value(),
|
||||
const_cast<uint16_t *>(scan_interval),
|
||||
const_cast<uint16_t *>(scan_window)
|
||||
);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::extended_scan_enable(
|
||||
bool enable,
|
||||
duplicates_filter_t filter_duplicates,
|
||||
uint16_t duration,
|
||||
uint16_t period
|
||||
)
|
||||
{
|
||||
if (enable) {
|
||||
// TODO retrieve scanning phys
|
||||
phy_set_t scanning_phys;
|
||||
|
||||
// TODO: retrieve scan type
|
||||
uint8_t* scan_type /*= use_active_scanning ? DM_SCAN_TYPE_ACTIVE : DM_SCAN_TYPE_PASSIVE */;
|
||||
|
||||
uint32_t duration_ms = duration * 10;
|
||||
|
||||
DmScanModeExt();
|
||||
DmScanStart(
|
||||
scanning_phys.value(),
|
||||
DM_DISC_MODE_NONE, // TODO: What todo with this ????
|
||||
scan_type,
|
||||
filter_duplicates.value(), // TODO: cordio API incomplete ???
|
||||
duration_ms > 0xFFFF ? 0xFFFF : duration_ms,
|
||||
period
|
||||
);
|
||||
} else {
|
||||
DmScanStop();
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::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
|
||||
)
|
||||
{
|
||||
if (use_periodic_advertiser_list) {
|
||||
DmDevSetExtFilterPolicy(
|
||||
DM_ADV_HANDLE_DEFAULT,
|
||||
DM_FILT_POLICY_MODE_SYNC,
|
||||
HCI_FILT_PER_ADV_LIST
|
||||
);
|
||||
}
|
||||
|
||||
DmSyncStart(
|
||||
advertising_sid,
|
||||
peer_address_type.value(),
|
||||
peer_address.data(),
|
||||
allowed_skip,
|
||||
sync_timeout
|
||||
);
|
||||
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ble_error_t Gap::cancel_periodic_advertising_create_sync()
|
||||
{
|
||||
// FIXME: Find a way to use it!
|
||||
// Function not directly exposed by the cordio stack.
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
ble_error_t Gap::periodic_advertising_terminate_sync(sync_handle_t sync_handle)
|
||||
{
|
||||
DmSyncStop(sync_handle);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::add_device_to_periodic_advertiser_list(
|
||||
advertising_peer_address_type_t advertiser_address_type,
|
||||
const address_t &advertiser_address,
|
||||
uint8_t advertising_sid
|
||||
)
|
||||
{
|
||||
DmAddDeviceToPerAdvList(
|
||||
advertiser_address_type.value(),
|
||||
const_cast<uint8_t *>(advertiser_address.data()),
|
||||
advertising_sid
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::remove_device_from_periodic_advertiser_list(
|
||||
advertising_peer_address_type_t advertiser_address_type,
|
||||
const address_t &advertiser_address,
|
||||
uint8_t advertising_sid
|
||||
)
|
||||
{
|
||||
DmRemoveDeviceFromPerAdvList(
|
||||
advertiser_address_type.value(),
|
||||
const_cast<uint8_t *>(advertiser_address.data()),
|
||||
advertising_sid
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t Gap::clear_periodic_advertiser_list()
|
||||
{
|
||||
DmClearPerAdvList();
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
uint8_t Gap::read_periodic_advertiser_list_size()
|
||||
{
|
||||
return HciGetPerAdvListSize();
|
||||
}
|
||||
|
||||
ble_error_t Gap::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
|
||||
)
|
||||
{
|
||||
DmExtConnSetScanInterval(
|
||||
initiating_phys.value(),
|
||||
const_cast<uint16_t *>(scan_intervals),
|
||||
const_cast<uint16_t *>(scan_windows)
|
||||
);
|
||||
|
||||
DmDevSetFilterPolicy(DM_FILT_POLICY_MODE_INIT, initiator_policy.value());
|
||||
DmConnSetAddrType(own_address_type.value());
|
||||
|
||||
// At most 3 phys are in used
|
||||
hciConnSpec_t conn_specs[3];
|
||||
for (size_t i = 0, count = initiating_phys.count(); i < count; ++i) {
|
||||
conn_specs[i].connIntervalMin = connection_intervals_min[i];
|
||||
conn_specs[i].connIntervalMax = connection_intervals_max[i];
|
||||
conn_specs[i].connLatency = connection_latencies[i];
|
||||
conn_specs[i].supTimeout = supervision_timeouts[i];
|
||||
conn_specs[i].minCeLen = minimum_connection_event_lengths[i];
|
||||
conn_specs[i].maxCeLen = maximum_connection_event_lengths[i];
|
||||
}
|
||||
|
||||
DmExtConnSetConnSpec(initiating_phys.value(), conn_specs);
|
||||
|
||||
dmConnId_t connection_id = DmConnOpen(
|
||||
DM_CLIENT_ID_APP,
|
||||
initiating_phys.value(),
|
||||
peer_address_type.value(),
|
||||
const_cast<uint8_t *>(peer_address.data())
|
||||
);
|
||||
|
||||
if (connection_id == DM_CONN_ID_NONE) {
|
||||
return BLE_ERROR_INTERNAL_STACK_FAILURE;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
} // cordio
|
||||
} // vendor
|
||||
|
|
Loading…
Reference in New Issue