Skip to content

Commit

Permalink
[Bluetooth]: Workaround for inquiry results with RSSI and page scan mode
Browse files Browse the repository at this point in the history
This patch implements a workaround for buggy Bluetooth 1.2 devices from
Silicon Wave. Their inquiry results with RSSI contain the page scan mode
field. This field was removed in the final Bluetooth 1.2 specification.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Marcel Holtmann authored and David S. Miller committed Aug 29, 2005
1 parent 4aa769b commit 45bb4bf
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 13 deletions.
9 changes: 9 additions & 0 deletions include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,15 @@ struct inquiry_info_with_rssi {
__u16 clock_offset;
__s8 rssi;
} __attribute__ ((packed));
struct inquiry_info_with_rssi_and_pscan_mode {
bdaddr_t bdaddr;
__u8 pscan_rep_mode;
__u8 pscan_period_mode;
__u8 pscan_mode;
__u8 dev_class[3];
__u16 clock_offset;
__s8 rssi;
} __attribute__ ((packed));

#define HCI_EV_CONN_COMPLETE 0x03
struct hci_ev_conn_complete {
Expand Down
55 changes: 42 additions & 13 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,14 +484,18 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
/* Inquiry Result */
static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct inquiry_data data;
struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1);
int num_rsp = *((__u8 *) skb->data);

BT_DBG("%s num_rsp %d", hdev->name, num_rsp);

if (!num_rsp)
return;

hci_dev_lock(hdev);

for (; num_rsp; num_rsp--) {
struct inquiry_data data;
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
Expand All @@ -502,30 +506,55 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
info++;
hci_inquiry_cache_update(hdev, &data);
}

hci_dev_unlock(hdev);
}

/* Inquiry Result With RSSI */
static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct inquiry_info_with_rssi *info = (struct inquiry_info_with_rssi *) (skb->data + 1);
struct inquiry_data data;
int num_rsp = *((__u8 *) skb->data);

BT_DBG("%s num_rsp %d", hdev->name, num_rsp);

if (!num_rsp)
return;

hci_dev_lock(hdev);
for (; num_rsp; num_rsp--) {
struct inquiry_data data;
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
data.pscan_mode = 0x00;
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = info->rssi;
info++;
hci_inquiry_cache_update(hdev, &data);

if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
struct inquiry_info_with_rssi_and_pscan_mode *info =
(struct inquiry_info_with_rssi_and_pscan_mode *) (skb->data + 1);

for (; num_rsp; num_rsp--) {
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
data.pscan_mode = info->pscan_mode;
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = info->rssi;
info++;
hci_inquiry_cache_update(hdev, &data);
}
} else {
struct inquiry_info_with_rssi *info =
(struct inquiry_info_with_rssi *) (skb->data + 1);

for (; num_rsp; num_rsp--) {
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
data.pscan_mode = 0x00;
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = info->rssi;
info++;
hci_inquiry_cache_update(hdev, &data);
}
}

hci_dev_unlock(hdev);
}

Expand Down

0 comments on commit 45bb4bf

Please sign in to comment.