@@ -815,6 +815,15 @@ struct mgmt_rp_add_ext_adv_data {
__u8 instance;
} __packed;
+#define MGMT_CAP_LE_TX_PWR_MIN 0x0000
+#define MGMT_CAP_LE_TX_PWR_MAX 0x0001
+
+#define MGMT_OP_READ_CONTROLLER_CAP 0x0056
+#define MGMT_OP_READ_CONTROLLER_CAP_SIZE 0
+struct mgmt_rp_read_controller_cap {
+ __u8 capabilities[0];
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
@@ -124,6 +124,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_REMOVE_ADV_MONITOR,
MGMT_OP_ADD_EXT_ADV_PARAMS,
MGMT_OP_ADD_EXT_ADV_DATA,
+ MGMT_OP_READ_CONTROLLER_CAP,
};
static const u16 mgmt_events[] = {
@@ -181,6 +182,7 @@ static const u16 mgmt_untrusted_commands[] = {
MGMT_OP_READ_EXP_FEATURES_INFO,
MGMT_OP_READ_DEF_SYSTEM_CONFIG,
MGMT_OP_READ_DEF_RUNTIME_CONFIG,
+ MGMT_OP_READ_CONTROLLER_CAP,
};
static const u16 mgmt_untrusted_events[] = {
@@ -4356,6 +4358,42 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
return err;
}
+static int read_controller_cap(struct sock *sk, struct hci_dev *hdev,
+ void *data, u16 len)
+{
+ u8 i = 0;
+
+ /* This command will return its data in TVL format. Currently we only
+ * wish to include LE tx power parameters, so this struct can be given
+ * a fixed size as data types are not changing.
+ */
+ struct {
+ struct mgmt_tlv entry;
+ __s8 value;
+ } __packed cap[2];
+
+ BT_DBG("request for %s", hdev->name);
+ memset(cap, 0, sizeof(cap));
+
+ hci_dev_lock(hdev);
+
+ /* Append LE tx power bounds */
+ cap[i].entry.type = cpu_to_le16(MGMT_CAP_LE_TX_PWR_MIN);
+ cap[i].entry.length = sizeof(__s8);
+ cap[i].value = hdev->min_le_tx_power;
+ i++;
+
+ cap[i].entry.type = cpu_to_le16(MGMT_CAP_LE_TX_PWR_MAX);
+ cap[i].entry.length = sizeof(__s8);
+ cap[i].value = hdev->max_le_tx_power;
+ i++;
+
+ hci_dev_unlock(hdev);
+
+ return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONTROLLER_CAP,
+ MGMT_STATUS_SUCCESS, cap, sizeof(cap));
+}
+
static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
u16 opcode, struct sk_buff *skb)
{
@@ -8208,6 +8246,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
HCI_MGMT_VAR_LEN },
{ add_ext_adv_data, MGMT_ADD_EXT_ADV_DATA_SIZE,
HCI_MGMT_VAR_LEN },
+ { read_controller_cap, MGMT_OP_READ_CONTROLLER_CAP_SIZE },
};
void mgmt_index_added(struct hci_dev *hdev)