Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 341538
b: refs/heads/master
c: 3f0f524
h: refs/heads/master
v: v3
  • Loading branch information
Johan Hedberg authored and Gustavo Padovan committed Nov 19, 2012
1 parent ce19a32 commit 85e846c
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bbaf444a89dd7dd7effd8ed2f4e4ec64da3cc1da
refs/heads/master: 3f0f524bafcd2025c12e215f13207c7be0a13bf9
15 changes: 15 additions & 0 deletions trunk/include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,13 @@ enum {
#define EIR_SSP_RAND_R 0x0F /* Simple Pairing Randomizer R */
#define EIR_DEVICE_ID 0x10 /* device ID */

/* Low Energy Advertising Flags */
#define LE_AD_LIMITED 0x01 /* Limited Discoverable */
#define LE_AD_GENERAL 0x02 /* General Discoverable */
#define LE_AD_NO_BREDR 0x04 /* BR/EDR not supported */
#define LE_AD_SIM_LE_BREDR_CTRL 0x08 /* Simultaneous LE & BR/EDR Controller */
#define LE_AD_SIM_LE_BREDR_HOST 0x10 /* Simultaneous LE & BR/EDR Host */

/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000

Expand Down Expand Up @@ -942,6 +949,14 @@ struct hci_rp_le_read_adv_tx_power {
__s8 tx_power;
} __packed;

#define HCI_MAX_AD_LENGTH 31

#define HCI_OP_LE_SET_ADV_DATA 0x2008
struct hci_cp_le_set_adv_data {
__u8 length;
__u8 data[HCI_MAX_AD_LENGTH];
} __packed;

#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
struct hci_cp_le_set_scan_param {
__u8 type;
Expand Down
4 changes: 4 additions & 0 deletions trunk/include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ struct hci_dev {
struct le_scan_params le_scan_params;

__s8 adv_tx_power;
__u8 adv_data[HCI_MAX_AD_LENGTH];
__u8 adv_data_len;

int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
Expand Down Expand Up @@ -734,6 +736,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
u8 *randomizer);
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);

int hci_update_ad(struct hci_dev *hdev);

void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);

int hci_recv_frame(struct sk_buff *skb);
Expand Down
94 changes: 94 additions & 0 deletions trunk/net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,99 @@ int hci_inquiry(void __user *arg)
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)
Expand Down Expand Up @@ -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);
Expand Down
11 changes: 10 additions & 1 deletion trunk/net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
hdev->discovery.state = DISCOVERY_STOPPED;
hdev->inq_tx_power = HCI_TX_POWER_INVALID;
hdev->adv_tx_power = HCI_TX_POWER_INVALID;

memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
hdev->adv_data_len = 0;
}

static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
Expand All @@ -226,6 +229,9 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)

hci_dev_unlock(hdev);

if (!status && !test_bit(HCI_INIT, &hdev->flags))
hci_update_ad(hdev);

hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
}

Expand Down Expand Up @@ -1091,8 +1097,11 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,

BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);

if (!rp->status)
if (!rp->status) {
hdev->adv_tx_power = rp->tx_power;
if (!test_bit(HCI_INIT, &hdev->flags))
hci_update_ad(hdev);
}

hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
}
Expand Down

0 comments on commit 85e846c

Please sign in to comment.