nimble/host: Add HCI commands / events for LE Power control

This commit is contained in:
Rahul Tank
2022-04-07 15:03:46 +05:30
committed by Szymon Janc
parent 02bb32fd1f
commit 7ee72efb48
11 changed files with 412 additions and 0 deletions
+126
View File
@@ -135,6 +135,8 @@ struct hci_conn_update;
#define BLE_GAP_EVENT_PERIODIC_SYNC_LOST 22
#define BLE_GAP_EVENT_SCAN_REQ_RCVD 23
#define BLE_GAP_EVENT_PERIODIC_TRANSFER 24
#define BLE_GAP_EVENT_PATHLOSS_THRESHOLD 25
#define BLE_GAP_EVENT_TRANSMIT_POWER 26
/*** Reason codes for the subscribe GAP event. */
@@ -973,6 +975,54 @@ struct ble_gap_event {
uint8_t adv_clk_accuracy;
} periodic_transfer;
#endif
#if MYNEWT_VAL(BLE_POWER_CONTROL)
/**
* Represents a change in either local transmit power or remote transmit
* power. Valid for the following event types:
* o BLE_GAP_EVENT_PATHLOSS_THRESHOLD
*/
struct {
/** Connection handle */
uint16_t conn_handle;
/** Current Path Loss */
uint8_t current_path_loss;
/** Entered Zone */
uint8_t zone_entered;
} pathloss_threshold;
/**
* Represents crossing of path loss threshold set via LE Set Path Loss
* Reporting Parameter command. Valid for the following event types:
* o BLE_GAP_EVENT_TRANSMIT_POWER
*/
struct {
/** BLE_ERR_SUCCESS on success or error code on failure */
uint8_t status;
/** Connection Handle */
uint16_t conn_handle;
/** Reason indicating why event was sent */
uint8_t reason;
/** Advertising PHY */
uint8_t phy;
/** Transmit power Level */
uint8_t transmit_power_level;
/** Transmit Power Level Flag */
uint8_t transmit_power_level_flag;
/** Delta indicating change in transmit Power Level */
uint8_t delta;
} transmit_power;
#endif
};
};
@@ -2097,6 +2147,82 @@ int ble_gap_event_listener_register(struct ble_gap_event_listener *listener,
*/
int ble_gap_event_listener_unregister(struct ble_gap_event_listener *listener);
#if MYNEWT_VAL(BLE_POWER_CONTROL)
/**
* Enable Set Path Loss Reporting.
*
* @param conn_handle Connection handle
* @params enable 1: Enable
* 0: Disable
*
* @return 0 on success; nonzero on failure.
*/
int ble_gap_set_path_loss_reporting_enable(uint16_t conn_handle, uint8_t enable);
/**
* Enable Reporting of Transmit Power
*
* @param conn_handle Connection handle
* @params local_enable 1: Enable local transmit power reports
* 0: Disable local transmit power reports
*
* @params remote_enable 1: Enable remote transmit power reports
* 0: Disable remote transmit power reports
*
* @return 0 on success; nonzero on failure.
*/
int ble_gap_set_transmit_power_reporting_enable(uint16_t conn_handle,
uint8_t local_enable,
uint8_t remote_enable);
/**
* LE Enhanced Read Transmit Power Level
*
* @param conn_handle Connection handle
* @params phy Advertising Phy
*
* @params status 0 on success; nonzero on failure.
* @params conn_handle Connection handle
* @params phy Advertising Phy
*
* @params curr_tx_power_level Current trasnmit Power Level
*
* @params mx_tx_power_level Maximum transmit power level
*
* @return 0 on success; nonzero on failure.
*/
int ble_gap_enh_read_transmit_power_level(uint16_t conn_handle, uint8_t phy,
uint8_t *out_status, uint8_t *out_phy,
uint8_t *out_curr_tx_power_level,
uint8_t *out_max_tx_power_level);
/**
* Read Remote Transmit Power Level
*
* @param conn_handle Connection handle
* @params phy Advertising Phy
*
* @return 0 on success; nonzero on failure.
*/
int ble_gap_read_remote_transmit_power_level(uint16_t conn_handle, uint8_t phy);
/**
* Set Path Loss Reproting Param
*
* @param conn_handle Connection handle
* @params high_threshold High Threshold value for path loss
* @params high_hysteresis Hysteresis value for high threshold
* @params low_threshold Low Threshold value for path loss
* @params low_hysteresis Hysteresis value for low threshold
* @params min_time_spent Minimum time controller observes the path loss
*
* @return 0 on success; nonzero on failure.
*/
int ble_gap_set_path_loss_reporting_param(uint16_t conn_handle, uint8_t high_threshold,
uint8_t high_hysteresis, uint8_t low_threshold,
uint8_t low_hysteresis, uint16_t min_time_spent);
#endif
#ifdef __cplusplus
}
#endif
+155
View File
@@ -1641,6 +1641,42 @@ ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_
}
#endif
#if MYNEWT_VAL(BLE_POWER_CONTROL)
void
ble_gap_rx_le_pathloss_threshold(const struct ble_hci_ev_le_subev_path_loss_threshold *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof event);
event.type = BLE_GAP_EVENT_PATHLOSS_THRESHOLD;
event.pathloss_threshold.conn_handle = le16toh(ev->conn_handle);
event.pathloss_threshold.current_path_loss = ev->current_path_loss;
event.pathloss_threshold.zone_entered = ev->zone_entered;
ble_gap_event_listener_call(&event);
}
void
ble_gap_rx_transmit_power_report(const struct ble_hci_ev_le_subev_transmit_power_report *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof event);
event.type = BLE_GAP_EVENT_TRANSMIT_POWER;
event.transmit_power.status = ev->status;
event.transmit_power.conn_handle = le16toh(ev->conn_handle);
event.transmit_power.reason = ev->reason;
event.transmit_power.phy = ev->phy;
event.transmit_power.transmit_power_level = ev->transmit_power_level;
event.transmit_power.transmit_power_level_flag = ev->transmit_power_level_flag;
event.transmit_power.delta = ev->delta;
ble_gap_event_listener_call(&event);
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
static int
periodic_adv_transfer_disable(uint16_t conn_handle)
@@ -6213,3 +6249,122 @@ ble_gap_init(void)
err:
return rc;
}
int
ble_gap_enh_read_transmit_power_level(uint16_t conn_handle, uint8_t phy, uint8_t *out_status, uint8_t *out_phy ,
uint8_t *out_curr_tx_power_level, uint8_t *out_max_tx_power_level)
{
#if MYNEWT_VAL(BLE_POWER_CONTROL)
struct ble_hci_le_enh_read_transmit_power_level_cp cmd;
struct ble_hci_le_enh_read_transmit_power_level_rp rsp;
uint16_t opcode;
int rc;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ENH_READ_TRANSMIT_POWER_LEVEL);
cmd.conn_handle = htole16(conn_handle);
cmd.phy = phy;
rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc!=0) {
return rc;
}
*out_status = rsp.status;
*out_phy = rsp.phy;
*out_curr_tx_power_level = rsp.curr_tx_power_level;
*out_max_tx_power_level = rsp.max_tx_power_level;
return 0;
#else
return BLE_HS_ENOTSUP;
#endif
}
int
ble_gap_read_remote_transmit_power_level(uint16_t conn_handle,
uint8_t phy)
{
#if MYNEWT_VAL(BLE_POWER_CONTROL)
struct ble_hci_le_read_remote_transmit_power_level_cp cmd;
uint16_t opcode;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_READ_REMOTE_TRANSMIT_POWER_LEVEL);
cmd.conn_handle = htole16(conn_handle);
cmd.phy = phy;
return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
#else
return BLE_HS_ENOTSUP;
#endif
}
int
ble_gap_set_path_loss_reporting_param(uint16_t conn_handle,
uint8_t high_threshold,
uint8_t high_hysteresis,
uint8_t low_threshold,
uint8_t low_hysteresis,
uint16_t min_time_spent)
{
#if MYNEWT_VAL(BLE_POWER_CONTROL)
struct ble_hci_le_set_path_loss_report_param_cp cmd;
uint16_t opcode;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PATH_LOSS_REPORT_PARAM);
cmd.conn_handle = htole16(conn_handle);
cmd.high_threshold = high_threshold;
cmd.high_hysteresis = high_hysteresis;
cmd.low_threshold = low_threshold;
cmd.low_hysteresis = low_hysteresis;
cmd.min_time_spent = min_time_spent;
return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
#else
return BLE_HS_ENOTSUP;
#endif
}
int
ble_gap_set_path_loss_reporting_enable(uint16_t conn_handle,
uint8_t enable)
{
#if MYNEWT_VAL(BLE_POWER_CONTROL)
struct ble_hci_le_set_path_loss_report_enable_cp cmd;
uint16_t opcode;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PATH_LOSS_REPORT_ENABLE);
cmd.conn_handle = htole16(conn_handle);
cmd.enable = enable;
return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
#else
return BLE_HS_ENOTSUP;
#endif
}
int
ble_gap_set_transmit_power_reporting_enable(uint16_t conn_handle,
uint8_t local_enable,
uint8_t remote_enable)
{
#if MYNEWT_VAL(BLE_POWER_CONTROL)
struct ble_hci_le_set_transmit_power_report_enable_cp cmd;
uint16_t opcode;
opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_TRANS_PWR_REPORT_ENABLE);
cmd.conn_handle = htole16(conn_handle);
cmd.local_enable = local_enable;
cmd.remote_enable = remote_enable;
return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
#else
return BLE_HS_ENOTSUP;
#endif
}
+5
View File
@@ -93,6 +93,11 @@ void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev
void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc);
void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev);
#if MYNEWT_VAL(BLE_POWER_CONTROL)
void ble_gap_rx_transmit_power_report(const struct ble_hci_ev_le_subev_transmit_power_report *ev);
void ble_gap_rx_le_pathloss_threshold(const struct ble_hci_ev_le_subev_path_loss_threshold *ev);
#endif
struct ble_gap_conn_complete
{
uint8_t status;
+38
View File
@@ -60,6 +60,10 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_lost;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_scan_req_rcvd;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_transfer;
#if MYNEWT_VAL(BLE_POWER_CONTROL)
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_pathloss_threshold;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_transmit_power_report;
#endif
/* Statistics */
struct host_hci_stats
@@ -116,6 +120,10 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = {
[BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED] = ble_hs_hci_evt_le_adv_set_terminated,
[BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD] = ble_hs_hci_evt_le_scan_req_rcvd,
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER] = ble_hs_hci_evt_le_periodic_adv_sync_transfer,
#if MYNEWT_VAL(BLE_POWER_CONTROL)
[BLE_HCI_LE_SUBEV_PATH_LOSS_THRESHOLD] = ble_hs_hci_evt_le_pathloss_threshold,
[BLE_HCI_LE_SUBEV_TRANSMIT_POWER_REPORT] = ble_hs_hci_evt_le_transmit_power_report,
#endif
};
#define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \
@@ -641,6 +649,36 @@ ble_hs_hci_evt_le_periodic_adv_sync_lost(uint8_t subevent, const void *data,
return 0;
}
#if MYNEWT_VAL(BLE_POWER_CONTROL)
static int
ble_hs_hci_evt_le_pathloss_threshold(uint8_t subevent, const void *data,
unsigned int len)
{
const struct ble_hci_ev_le_subev_path_loss_threshold *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_EBADDATA;
}
ble_gap_rx_le_pathloss_threshold(ev);
return 0;
}
static int
ble_hs_hci_evt_le_transmit_power_report(uint8_t subevent, const void *data,
unsigned int len)
{
const struct ble_hci_ev_le_subev_transmit_power_report *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_EBADDATA;
}
ble_gap_rx_transmit_power_report(ev);
return 0;
}
#endif
static int
ble_hs_hci_evt_le_periodic_adv_sync_transfer(uint8_t subevent, const void *data,
unsigned int len)
+63
View File
@@ -1122,6 +1122,49 @@ struct ble_hci_vs_css_set_conn_slot_cp {
uint16_t slot_idx;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_ENH_READ_TRANSMIT_POWER_LEVEL (0x0076)
struct ble_hci_le_enh_read_transmit_power_level_cp {
uint16_t conn_handle;
uint8_t phy;
} __attribute__((packed));
struct ble_hci_le_enh_read_transmit_power_level_rp {
uint8_t status;
uint16_t conn_handle;
uint8_t phy;
uint8_t curr_tx_power_level;
uint8_t max_tx_power_level;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_READ_REMOTE_TRANSMIT_POWER_LEVEL (0x0077)
struct ble_hci_le_read_remote_transmit_power_level_cp {
uint16_t conn_handle;
uint8_t phy;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_SET_PATH_LOSS_REPORT_PARAM (0x0078)
struct ble_hci_le_set_path_loss_report_param_cp {
uint16_t conn_handle;
uint8_t high_threshold;
uint8_t high_hysteresis;
uint8_t low_threshold;
uint8_t low_hysteresis;
uint16_t min_time_spent;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_SET_PATH_LOSS_REPORT_ENABLE (0x0079)
struct ble_hci_le_set_path_loss_report_enable_cp {
uint16_t conn_handle;
uint8_t enable;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_SET_TRANS_PWR_REPORT_ENABLE (0x007A)
struct ble_hci_le_set_transmit_power_report_enable_cp {
uint16_t conn_handle;
uint8_t local_enable;
uint8_t remote_enable;
} __attribute__((packed));
/* Command Specific Definitions */
/* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */
#define BLE_HCI_CTLR_TO_HOST_FC_OFF (0)
@@ -1823,6 +1866,26 @@ struct ble_hci_ev_le_subev_peer_sca_complete {
uint8_t sca;
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_PATH_LOSS_THRESHOLD (0x20)
struct ble_hci_ev_le_subev_path_loss_threshold {
uint8_t subev_code;
uint16_t conn_handle;
uint8_t current_path_loss;
uint8_t zone_entered;
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_TRANSMIT_POWER_REPORT (0x21)
struct ble_hci_ev_le_subev_transmit_power_report {
uint8_t subev_code;
uint8_t status;
uint16_t conn_handle;
uint8_t reason;
uint8_t phy;
uint8_t transmit_power_level;
uint8_t transmit_power_level_flag;
uint8_t delta;
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT (0x22)
struct ble_hci_ev_le_subev_biginfo_adv_report {
uint8_t subev_code;
+5
View File
@@ -108,6 +108,11 @@ syscfg.defs:
implementations.
value: 0
BLE_POWER_CONTROL:
description: >
This enabled LE Power Control feature
value: 0
# Allow periodic sync transfer only if 5.1 or higher
syscfg.restrictions:
- "'BLE_PERIODIC_ADV_SYNC_TRANSFER == 0' || 'BLE_VERSION >= 51'"
@@ -498,6 +498,10 @@
#define MYNEWT_VAL_BLE_WHITELIST (1)
#endif
#ifndef MYNEWT_VAL_BLE_POWER_CONTROL
#define MYNEWT_VAL_BLE_POWER_CONTROL (0)
#endif
/*** @apache-mynewt-nimble/nimble/host */
#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU
#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256)
@@ -499,6 +499,10 @@
#define MYNEWT_VAL_BLE_WHITELIST (1)
#endif
#ifndef MYNEWT_VAL_BLE_POWER_CONTROL
#define MYNEWT_VAL_BLE_POWER_CONTROL (0)
#endif
/*** @apache-mynewt-nimble/nimble/host */
#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU
#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256)
@@ -498,6 +498,10 @@
#define MYNEWT_VAL_BLE_WHITELIST (1)
#endif
#ifndef MYNEWT_VAL_BLE_POWER_CONTROL
#define MYNEWT_VAL_BLE_POWER_CONTROL (0)
#endif
/*** @apache-mynewt-nimble/nimble/host */
#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU
#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256)
+4
View File
@@ -497,6 +497,10 @@
#define MYNEWT_VAL_BLE_WHITELIST (1)
#endif
#ifndef MYNEWT_VAL_BLE_POWER_CONTROL
#define MYNEWT_VAL_BLE_POWER_CONTROL (0)
#endif
/*** @apache-mynewt-nimble/nimble/host */
#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU
#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256)
+4
View File
@@ -858,6 +858,10 @@
#define MYNEWT_VAL_BLE_WHITELIST (1)
#endif
#ifndef MYNEWT_VAL_BLE_POWER_CONTROL
#define MYNEWT_VAL_BLE_POWER_CONTROL (0)
#endif
/*** @apache-mynewt-nimble/nimble/controller */
#ifndef MYNEWT_VAL_BLE_CONTROLLER
#define MYNEWT_VAL_BLE_CONTROLLER (1)