Bluetooth: Add support for setting LE advertising data

This patch adds support for setting basing LE advertising data. The
three elements supported for now are the advertising flags, the TX power
and the friendly name.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
This commit is contained in:
Johan Hedberg
2012-11-08 01:23:00 +01:00
committed by Gustavo Padovan
parent bbaf444a89
commit 3f0f524baf
4 changed files with 123 additions and 1 deletions

View File

@@ -594,6 +594,99 @@ done:
return err;
}
static u8 create_ad(struct hci_dev *hdev, u8 *ptr)
{
u8 ad_len = 0, flags = 0;
size_t name_len;
if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
flags |= LE_AD_GENERAL;
if (!lmp_bredr_capable(hdev))
flags |= LE_AD_NO_BREDR;
if (lmp_le_br_capable(hdev))
flags |= LE_AD_SIM_LE_BREDR_CTRL;
if (lmp_host_le_br_capable(hdev))
flags |= LE_AD_SIM_LE_BREDR_HOST;
if (flags) {
BT_DBG("adv flags 0x%02x", flags);
ptr[0] = 2;
ptr[1] = EIR_FLAGS;
ptr[2] = flags;
ad_len += 3;
ptr += 3;
}
if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
ptr[0] = 2;
ptr[1] = EIR_TX_POWER;
ptr[2] = (u8) hdev->adv_tx_power;
ad_len += 3;
ptr += 3;
}
name_len = strlen(hdev->dev_name);
if (name_len > 0) {
size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
if (name_len > max_len) {
name_len = max_len;
ptr[1] = EIR_NAME_SHORT;
} else
ptr[1] = EIR_NAME_COMPLETE;
ptr[0] = name_len + 1;
memcpy(ptr + 2, hdev->dev_name, name_len);
ad_len += (name_len + 2);
ptr += (name_len + 2);
}
return ad_len;
}
int hci_update_ad(struct hci_dev *hdev)
{
struct hci_cp_le_set_adv_data cp;
u8 len;
int err;
hci_dev_lock(hdev);
if (!lmp_le_capable(hdev)) {
err = -EINVAL;
goto unlock;
}
memset(&cp, 0, sizeof(cp));
len = create_ad(hdev, cp.data);
if (hdev->adv_data_len == len &&
memcmp(cp.data, hdev->adv_data, len) == 0) {
err = 0;
goto unlock;
}
memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
hdev->adv_data_len = len;
cp.length = len;
err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
unlock:
hci_dev_unlock(hdev);
return err;
}
/* ---- HCI ioctl helpers ---- */
int hci_dev_open(__u16 dev)
@@ -651,6 +744,7 @@ int hci_dev_open(__u16 dev)
hci_dev_hold(hdev);
set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP);
hci_update_ad(hdev);
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
mgmt_valid_hdev(hdev)) {
hci_dev_lock(hdev);