Bluetooth: Query LE tx power on startup
Queries tx power via HCI_LE_Read_Transmit_Power command when the hci device is initialized, and stores resulting min/max LE power in hdev struct. If command isn't available (< BT5 support), min/max values both default to HCI_TX_POWER_INVALID. This patch is manually verified by ensuring BT5 devices correctly query and receive controller tx power range. Reviewed-by: Sonny Sasaka <sonnysasaka@chromium.org> Signed-off-by: Daniel Winkler <danielwinkler@google.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
9bf9f4b630
commit
7c395ea521
|
@ -1797,6 +1797,13 @@ struct hci_cp_le_set_adv_set_rand_addr {
|
|||
bdaddr_t bdaddr;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_READ_TRANSMIT_POWER 0x204b
|
||||
struct hci_rp_le_read_transmit_power {
|
||||
__u8 status;
|
||||
__s8 min_le_tx_power;
|
||||
__s8 max_le_tx_power;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_READ_BUFFER_SIZE_V2 0x2060
|
||||
struct hci_rp_le_read_buffer_size_v2 {
|
||||
__u8 status;
|
||||
|
|
|
@ -384,6 +384,8 @@ struct hci_dev {
|
|||
__u16 def_page_timeout;
|
||||
__u16 def_multi_adv_rotation_duration;
|
||||
__u16 def_le_autoconnect_timeout;
|
||||
__s8 min_le_tx_power;
|
||||
__s8 max_le_tx_power;
|
||||
|
||||
__u16 pkt_type;
|
||||
__u16 esco_type;
|
||||
|
|
|
@ -741,6 +741,12 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
|
|||
hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
|
||||
}
|
||||
|
||||
if (hdev->commands[38] & 0x80) {
|
||||
/* Read LE Min/Max Tx Power*/
|
||||
hci_req_add(req, HCI_OP_LE_READ_TRANSMIT_POWER,
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
if (hdev->commands[26] & 0x40) {
|
||||
/* Read LE White List Size */
|
||||
hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE,
|
||||
|
@ -3660,6 +3666,8 @@ struct hci_dev *hci_alloc_dev(void)
|
|||
hdev->le_num_of_adv_sets = HCI_MAX_ADV_INSTANCES;
|
||||
hdev->def_multi_adv_rotation_duration = HCI_DEFAULT_ADV_DURATION;
|
||||
hdev->def_le_autoconnect_timeout = HCI_LE_AUTOCONN_TIMEOUT;
|
||||
hdev->min_le_tx_power = HCI_TX_POWER_INVALID;
|
||||
hdev->max_le_tx_power = HCI_TX_POWER_INVALID;
|
||||
|
||||
hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT;
|
||||
hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT;
|
||||
|
|
|
@ -1202,6 +1202,20 @@ static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
|
|||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static void hci_cc_le_read_transmit_power(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_le_read_transmit_power *rp = (void *)skb->data;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
return;
|
||||
|
||||
hdev->min_le_tx_power = rp->min_le_tx_power;
|
||||
hdev->max_le_tx_power = rp->max_le_tx_power;
|
||||
}
|
||||
|
||||
static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 *sent, status = *((__u8 *) skb->data);
|
||||
|
@ -3582,6 +3596,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
|
|||
hci_cc_le_set_adv_set_random_addr(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_LE_READ_TRANSMIT_POWER:
|
||||
hci_cc_le_read_transmit_power(hdev, skb);
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue