From fd8d03bd8b1dbba81f70a892541813faab097285 Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Mon, 6 Jul 2020 10:01:04 -0400 Subject: [PATCH] bluetooth: conn: add api for getting tx power level Added a new Bluetooth API that can be used to read the current and maximum transmit power level of the radio. The reading operation is performed over HCI. Signed-off-by: Kamil Piszczek --- include/bluetooth/conn.h | 24 ++++++++++++++++ subsys/bluetooth/host/conn.c | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/include/bluetooth/conn.h b/include/bluetooth/conn.h index df2e5653a5f..1a1c2e2fed9 100644 --- a/include/bluetooth/conn.h +++ b/include/bluetooth/conn.h @@ -370,6 +370,19 @@ struct bt_conn_remote_info { }; }; +/** LE Transmit Power Level Structure */ +struct bt_conn_le_tx_power { + + /** Input: 1M, 2M, Coded S2 or Coded S8 */ + uint8_t phy; + + /** Output: current transmit power level */ + int8_t current_level; + + /** Output: maximum transmit power level */ + int8_t max_level; +}; + /** @brief Get connection info * * @param conn Connection object. @@ -397,6 +410,17 @@ int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info); int bt_conn_get_remote_info(struct bt_conn *conn, struct bt_conn_remote_info *remote_info); +/** @brief Get connection transmit power level. + * + * @param conn Connection object. + * @param tx_power_level Transmit power level descriptor. + * + * @return Zero on success or (negative) error code on failure. + * @return -ENOBUFS HCI command buffer is not available. + */ +int bt_conn_le_get_tx_power_level(struct bt_conn *conn, + struct bt_conn_le_tx_power *tx_power_level); + /** @brief Update the connection parameters. * * If the local device is in the peripheral role then updating the connection diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 034daa82730..0d2b4d6262c 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -1974,6 +1974,60 @@ int bt_conn_get_remote_info(struct bt_conn *conn, } } +/* Read Transmit Power Level HCI command */ +static int bt_conn_get_tx_power_level(struct bt_conn *conn, uint8_t type, + int8_t *tx_power_level) +{ + int err; + struct bt_hci_rp_read_tx_power_level *rp; + struct net_buf *rsp; + struct bt_hci_cp_read_tx_power_level *cp; + struct net_buf *buf; + + buf = bt_hci_cmd_create(BT_HCI_OP_READ_TX_POWER_LEVEL, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + cp->type = type; + cp->handle = sys_cpu_to_le16(conn->handle); + + err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_TX_POWER_LEVEL, buf, &rsp); + if (err) { + return err; + } + + rp = (void *) rsp->data; + *tx_power_level = rp->tx_power_level; + net_buf_unref(rsp); + + return 0; +} + +int bt_conn_le_get_tx_power_level(struct bt_conn *conn, + struct bt_conn_le_tx_power *tx_power_level) +{ + int err; + + if (tx_power_level->phy != 0) { + /* Extend the implementation when LE Enhanced Read Transmit + * Power Level HCI command is available for use. + */ + return -ENOTSUP; + } + + err = bt_conn_get_tx_power_level(conn, BT_TX_POWER_LEVEL_CURRENT, + &tx_power_level->current_level); + if (err) { + return err; + } + + err = bt_conn_get_tx_power_level(conn, BT_TX_POWER_LEVEL_MAX, + &tx_power_level->max_level); + return err; +} + static int conn_disconnect(struct bt_conn *conn, uint8_t reason) { int err;