|
@@ -102,6 +102,7 @@ static const u16 mgmt_commands[] = {
|
|
|
MGMT_OP_READ_ADV_FEATURES,
|
|
|
MGMT_OP_ADD_ADVERTISING,
|
|
|
MGMT_OP_REMOVE_ADVERTISING,
|
|
|
+ MGMT_OP_GET_ADV_SIZE_INFO,
|
|
|
};
|
|
|
|
|
|
static const u16 mgmt_events[] = {
|
|
@@ -7059,6 +7060,62 @@ unlock:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static u8 tlv_data_max_len(u32 adv_flags, bool is_adv_data)
|
|
|
+{
|
|
|
+ u8 max_len = HCI_MAX_AD_LENGTH;
|
|
|
+
|
|
|
+ if (is_adv_data) {
|
|
|
+ if (adv_flags & (MGMT_ADV_FLAG_DISCOV |
|
|
|
+ MGMT_ADV_FLAG_LIMITED_DISCOV |
|
|
|
+ MGMT_ADV_FLAG_MANAGED_FLAGS))
|
|
|
+ max_len -= 3;
|
|
|
+
|
|
|
+ if (adv_flags & MGMT_ADV_FLAG_TX_POWER)
|
|
|
+ max_len -= 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ return max_len;
|
|
|
+}
|
|
|
+
|
|
|
+static int get_adv_size_info(struct sock *sk, struct hci_dev *hdev,
|
|
|
+ void *data, u16 data_len)
|
|
|
+{
|
|
|
+ struct mgmt_cp_get_adv_size_info *cp = data;
|
|
|
+ struct mgmt_rp_get_adv_size_info rp;
|
|
|
+ u32 flags, supported_flags;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ BT_DBG("%s", hdev->name);
|
|
|
+
|
|
|
+ if (!lmp_le_capable(hdev))
|
|
|
+ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
|
|
|
+ MGMT_STATUS_REJECTED);
|
|
|
+
|
|
|
+ if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES)
|
|
|
+ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
|
|
|
+ MGMT_STATUS_INVALID_PARAMS);
|
|
|
+
|
|
|
+ flags = __le32_to_cpu(cp->flags);
|
|
|
+
|
|
|
+ /* The current implementation only supports a subset of the specified
|
|
|
+ * flags.
|
|
|
+ */
|
|
|
+ supported_flags = get_supported_adv_flags(hdev);
|
|
|
+ if (flags & ~supported_flags)
|
|
|
+ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
|
|
|
+ MGMT_STATUS_INVALID_PARAMS);
|
|
|
+
|
|
|
+ rp.instance = cp->instance;
|
|
|
+ rp.flags = cp->flags;
|
|
|
+ rp.max_adv_data_len = tlv_data_max_len(flags, true);
|
|
|
+ rp.max_scan_rsp_len = tlv_data_max_len(flags, false);
|
|
|
+
|
|
|
+ err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
|
|
|
+ MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
static const struct hci_mgmt_handler mgmt_handlers[] = {
|
|
|
{ NULL }, /* 0x0000 (no command) */
|
|
|
{ read_version, MGMT_READ_VERSION_SIZE,
|
|
@@ -7146,6 +7203,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
|
|
|
{ add_advertising, MGMT_ADD_ADVERTISING_SIZE,
|
|
|
HCI_MGMT_VAR_LEN },
|
|
|
{ remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
|
|
|
+ { get_adv_size_info, MGMT_GET_ADV_SIZE_INFO_SIZE },
|
|
|
};
|
|
|
|
|
|
void mgmt_index_added(struct hci_dev *hdev)
|