This is an automated email from the ASF dual-hosted git repository.
janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
The following commit(s) were added to refs/heads/master by this push:
new ff51d48 nimble/ll: Add VS command for setting transmit power
ff51d48 is described below
commit ff51d481cc1e2f16f124ce545a7510e42fb1b033
Author: Szymon Janc <[email protected]>
AuthorDate: Tue Dec 28 15:12:42 2021 +0100
nimble/ll: Add VS command for setting transmit power
This command allows to override TX power configured with
BLE_LL_TX_PWR_DBM syscfg value. If 0xff is provided BLE_LL_TX_PWR_DBM
TX power is restored.
---
nimble/controller/src/ble_ll.c | 4 +-
nimble/controller/src/ble_ll_adv.c | 9 ++--
nimble/controller/src/ble_ll_hci_vs.c | 85 +++++++++++++++++++++++++++++++++++
nimble/controller/src/ble_ll_priv.h | 2 +
nimble/controller/syscfg.yml | 4 +-
nimble/include/nimble/hci_common.h | 14 +++++-
6 files changed, 111 insertions(+), 7 deletions(-)
diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c
index f21f55c..1e378bc 100644
--- a/nimble/controller/src/ble_ll.c
+++ b/nimble/controller/src/ble_ll.c
@@ -65,6 +65,8 @@
* right thing to do.
*/
+int8_t g_ble_ll_tx_power = MYNEWT_VAL(BLE_LL_TX_PWR_DBM);
+
/* Supported states */
#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER)
#define BLE_LL_S_NCA ((uint64_t)1 << 0)
@@ -1391,7 +1393,7 @@ ble_ll_task(void *arg)
ble_phy_init();
/* Set output power to 1mW (0 dBm) */
- ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM));
+ ble_phy_txpwr_set(g_ble_ll_tx_power);
/* Register callback for transport */
ble_hci_trans_cfg_ll(ble_ll_hci_cmd_rx, NULL, ble_ll_hci_acl_rx, NULL);
diff --git a/nimble/controller/src/ble_ll_adv.c
b/nimble/controller/src/ble_ll_adv.c
index 8a6cd1f..db17dc4 100644
--- a/nimble/controller/src/ble_ll_adv.c
+++ b/nimble/controller/src/ble_ll_adv.c
@@ -41,6 +41,7 @@
#include "controller/ble_ll_utils.h"
#include "controller/ble_ll_rfmgmt.h"
#include "ble_ll_conn_priv.h"
+#include "ble_ll_priv.h"
#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER)
@@ -1023,7 +1024,7 @@ ble_ll_adv_tx_done(void *arg)
struct ble_ll_adv_sm *advsm;
/* reset power to max after advertising */
- ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM));
+ ble_phy_txpwr_set(g_ble_ll_tx_power);
advsm = (struct ble_ll_adv_sm *)arg;
@@ -1687,7 +1688,7 @@ ble_ll_adv_halt(void)
ble_ll_trace_u32(BLE_LL_TRACE_ID_ADV_HALT, advsm->adv_instance);
- ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM));
+ ble_phy_txpwr_set(g_ble_ll_tx_power);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
if (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING) {
@@ -2112,8 +2113,8 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg,
uint8_t *hdr_byte)
static void
ble_ll_adv_sync_tx_done(struct ble_ll_adv_sm *advsm)
{
- /* reset power to max after advertising */
- ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM));
+ /* reset power to default after advertising */
+ ble_phy_txpwr_set(g_ble_ll_tx_power);
/* for sync we trace a no pri nor sec set */
ble_ll_trace_u32x2(BLE_LL_TRACE_ID_ADV_TXDONE, advsm->adv_instance, 0);
diff --git a/nimble/controller/src/ble_ll_hci_vs.c
b/nimble/controller/src/ble_ll_hci_vs.c
index 8903525..f2057ea 100644
--- a/nimble/controller/src/ble_ll_hci_vs.c
+++ b/nimble/controller/src/ble_ll_hci_vs.c
@@ -21,7 +21,12 @@
#include "syscfg/syscfg.h"
#include "controller/ble_ll.h"
#include "controller/ble_ll_hci.h"
+#include "controller/ble_ll_sync.h"
+#include "controller/ble_ll_adv.h"
+#include "controller/ble_ll_scan.h"
#include "controller/ble_hw.h"
+#include "ble_ll_conn_priv.h"
+#include "ble_ll_priv.h"
#if MYNEWT_VAL(BLE_LL_HCI_VS)
@@ -51,9 +56,89 @@ ble_ll_hci_vs_rd_static_addr(uint16_t ocf,
return BLE_ERR_SUCCESS;
}
+/* disallow changing TX power if there is any radio activity
+ * note: we could allow to change it if there is no TX activity (eg only
+ * passive scan or sync) but lets just keep this simple for now
+ */
+static int
+ble_ll_hci_vs_is_controller_busy(void)
+{
+#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
+ struct ble_ll_conn_sm *cur;
+ int i = 0;
+#endif
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) &&
MYNEWT_VAL(BLE_LL_ROLE_OBSERVER)
+ if (ble_ll_sync_enabled()) {
+ return 1;
+ }
+#endif
+
+#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER)
+ if (ble_ll_adv_enabled()) {
+ return 1;
+ }
+#endif
+
+#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER)
+ if (ble_ll_scan_enabled()) {
+ return 1;
+ }
+#endif
+
+#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)
+ if (g_ble_ll_conn_create_sm.connsm) {
+ return 1;
+ }
+#endif
+
+#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
+ STAILQ_FOREACH(cur, &g_ble_ll_conn_free_list, free_stqe) {
+ i++;
+ }
+
+ /* check if all connection objects are free */
+ if (i < MYNEWT_VAL(BLE_MAX_CONNECTIONS)) {
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+static int
+ble_ll_hci_vs_set_tx_power(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen,
+ uint8_t *rspbuf, uint8_t *rsplen)
+{
+ const struct ble_hci_vs_set_tx_pwr_cp *cmd = (const void *) cmdbuf;
+ struct ble_hci_vs_set_tx_pwr_rp *rsp = (void *) rspbuf;
+
+ if (cmdlen != sizeof(*cmd)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ if (ble_ll_hci_vs_is_controller_busy()) {
+ return BLE_ERR_CMD_DISALLOWED;
+ }
+
+ if (cmd->tx_power == 127) {
+ /* restore reset default */
+ g_ble_ll_tx_power = MYNEWT_VAL(BLE_LL_TX_PWR_DBM);
+ } else {
+ g_ble_ll_tx_power = ble_phy_txpower_round(cmd->tx_power);
+ }
+
+ rsp->tx_power = g_ble_ll_tx_power;
+ *rsplen = sizeof(*rsp);
+
+ return BLE_ERR_SUCCESS;
+}
+
static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = {
BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_RD_STATIC_ADDR,
ble_ll_hci_vs_rd_static_addr),
+ BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_TX_PWR,
+ ble_ll_hci_vs_set_tx_power),
};
static struct ble_ll_hci_vs_cmd *
diff --git a/nimble/controller/src/ble_ll_priv.h
b/nimble/controller/src/ble_ll_priv.h
index 900950e..ca8e082 100644
--- a/nimble/controller/src/ble_ll_priv.h
+++ b/nimble/controller/src/ble_ll_priv.h
@@ -24,6 +24,8 @@
extern "C" {
#endif
+extern int8_t g_ble_ll_tx_power;
+
#ifdef MYNEWT
#include "syscfg/syscfg.h"
diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml
index 41384cb..afb3859 100644
--- a/nimble/controller/syscfg.yml
+++ b/nimble/controller/syscfg.yml
@@ -68,7 +68,9 @@ syscfg.defs:
range: 0..500
BLE_LL_TX_PWR_DBM:
- description: 'Transmit power level.'
+ description: >
+ Default Transmit power level (in dBm). Actual transmit power
+ may be rounded up or down depending on used radio.
value: '0'
BLE_LL_NUM_COMP_PKT_ITVL_MS:
diff --git a/nimble/include/nimble/hci_common.h
b/nimble/include/nimble/hci_common.h
index 4851fd0..e483083 100644
--- a/nimble/include/nimble/hci_common.h
+++ b/nimble/include/nimble/hci_common.h
@@ -1062,11 +1062,23 @@ struct ble_hci_le_set_host_feat_cp {
} __attribute__((packed));
/* --- Vendor specific commands (OGF 0x003F) */
-#define BLE_HCI_OCF_VS_RD_STATIC_ADDR (0x0001)
+/* Read Random Static Address */
+#define BLE_HCI_OCF_VS_RD_STATIC_ADDR (0x0001)
struct ble_hci_vs_rd_static_addr_rp {
uint8_t addr[6];
} __attribute__((packed));
+/* Set default transmit power. Actual selected TX power is returned
+ * in reply. Setting 0xff restores controller reset default.
+ */
+#define BLE_HCI_OCF_VS_SET_TX_PWR (0x0002)
+struct ble_hci_vs_set_tx_pwr_cp {
+ int8_t tx_power;
+} __attribute__((packed));
+struct ble_hci_vs_set_tx_pwr_rp {
+ int8_t tx_power;
+} __attribute__((packed));
+
/* Command Specific Definitions */
/* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */
#define BLE_HCI_CTLR_TO_HOST_FC_OFF (0)