mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 09:32:34 +00:00
ipq807x: backport fix for Bluetooth LE-only HCI controllers
This backports an essential fix for Bluetooth LE-only HCI devices from
kernel 4.9: 39385cb5f327 ("Bluetooth: Fix using the correct source
address type").
Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
This commit is contained in:
committed by
John Crispin
parent
f34db0bb24
commit
3f03cfa7c4
@@ -0,0 +1,131 @@
|
||||
From 39385cb5f3274735b03ed1f8e7ff517b02a0beed Mon Sep 17 00:00:00 2001
|
||||
From: Johan Hedberg <johan.hedberg@intel.com>
|
||||
Date: Sat, 12 Nov 2016 17:03:07 +0200
|
||||
Subject: [PATCH] Bluetooth: Fix using the correct source address type
|
||||
|
||||
The hci_get_route() API is used to look up local HCI devices, however
|
||||
so far it has been incapable of dealing with anything else than the
|
||||
public address of HCI devices. This completely breaks with LE-only HCI
|
||||
devices that do not come with a public address, but use a static
|
||||
random address instead.
|
||||
|
||||
This patch exteds the hci_get_route() API with a src_type parameter
|
||||
that's used for comparing with the right address of each HCI device.
|
||||
|
||||
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
|
||||
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
|
||||
---
|
||||
include/net/bluetooth/hci_core.h | 2 +-
|
||||
net/bluetooth/6lowpan.c | 4 ++--
|
||||
net/bluetooth/hci_conn.c | 26 ++++++++++++++++++++++++--
|
||||
net/bluetooth/l2cap_core.c | 2 +-
|
||||
net/bluetooth/rfcomm/tty.c | 2 +-
|
||||
net/bluetooth/sco.c | 2 +-
|
||||
6 files changed, 30 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/include/net/bluetooth/hci_core.h
|
||||
+++ b/include/net/bluetooth/hci_core.h
|
||||
@@ -1003,7 +1003,7 @@ static inline void hci_set_drvdata(struc
|
||||
}
|
||||
|
||||
struct hci_dev *hci_dev_get(int index);
|
||||
-struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src);
|
||||
+struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, u8 src_type);
|
||||
|
||||
struct hci_dev *hci_alloc_dev(void);
|
||||
void hci_free_dev(struct hci_dev *hdev);
|
||||
--- a/net/bluetooth/6lowpan.c
|
||||
+++ b/net/bluetooth/6lowpan.c
|
||||
@@ -1102,7 +1102,6 @@ static int get_l2cap_conn(char *buf, bda
|
||||
{
|
||||
struct hci_conn *hcon;
|
||||
struct hci_dev *hdev;
|
||||
- bdaddr_t *src = BDADDR_ANY;
|
||||
int n;
|
||||
|
||||
n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu",
|
||||
@@ -1113,7 +1112,8 @@ static int get_l2cap_conn(char *buf, bda
|
||||
if (n < 7)
|
||||
return -EINVAL;
|
||||
|
||||
- hdev = hci_get_route(addr, src);
|
||||
+ /* The LE_PUBLIC address type is ignored because of BDADDR_ANY */
|
||||
+ hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC);
|
||||
if (!hdev)
|
||||
return -ENOENT;
|
||||
|
||||
--- a/net/bluetooth/hci_conn.c
|
||||
+++ b/net/bluetooth/hci_conn.c
|
||||
@@ -609,7 +609,7 @@ int hci_conn_del(struct hci_conn *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
|
||||
+struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type)
|
||||
{
|
||||
int use_src = bacmp(src, BDADDR_ANY);
|
||||
struct hci_dev *hdev = NULL, *d;
|
||||
@@ -630,7 +630,29 @@ struct hci_dev *hci_get_route(bdaddr_t *
|
||||
*/
|
||||
|
||||
if (use_src) {
|
||||
- if (!bacmp(&d->bdaddr, src)) {
|
||||
+ bdaddr_t id_addr;
|
||||
+ u8 id_addr_type;
|
||||
+
|
||||
+ if (src_type == BDADDR_BREDR) {
|
||||
+ if (!lmp_bredr_capable(d))
|
||||
+ continue;
|
||||
+ bacpy(&id_addr, &d->bdaddr);
|
||||
+ id_addr_type = BDADDR_BREDR;
|
||||
+ } else {
|
||||
+ if (!lmp_le_capable(d))
|
||||
+ continue;
|
||||
+
|
||||
+ hci_copy_identity_address(d, &id_addr,
|
||||
+ &id_addr_type);
|
||||
+
|
||||
+ /* Convert from HCI to three-value type */
|
||||
+ if (id_addr_type == ADDR_LE_DEV_PUBLIC)
|
||||
+ id_addr_type = BDADDR_LE_PUBLIC;
|
||||
+ else
|
||||
+ id_addr_type = BDADDR_LE_RANDOM;
|
||||
+ }
|
||||
+
|
||||
+ if (!bacmp(&id_addr, src) && id_addr_type == src_type) {
|
||||
hdev = d; break;
|
||||
}
|
||||
} else {
|
||||
--- a/net/bluetooth/l2cap_core.c
|
||||
+++ b/net/bluetooth/l2cap_core.c
|
||||
@@ -7044,7 +7044,7 @@ int l2cap_chan_connect(struct l2cap_chan
|
||||
BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst,
|
||||
dst_type, __le16_to_cpu(psm));
|
||||
|
||||
- hdev = hci_get_route(dst, &chan->src);
|
||||
+ hdev = hci_get_route(dst, &chan->src, chan->src_type);
|
||||
if (!hdev)
|
||||
return -EHOSTUNREACH;
|
||||
|
||||
--- a/net/bluetooth/rfcomm/tty.c
|
||||
+++ b/net/bluetooth/rfcomm/tty.c
|
||||
@@ -178,7 +178,7 @@ static void rfcomm_reparent_device(struc
|
||||
struct hci_dev *hdev;
|
||||
struct hci_conn *conn;
|
||||
|
||||
- hdev = hci_get_route(&dev->dst, &dev->src);
|
||||
+ hdev = hci_get_route(&dev->dst, &dev->src, BDADDR_BREDR);
|
||||
if (!hdev)
|
||||
return;
|
||||
|
||||
--- a/net/bluetooth/sco.c
|
||||
+++ b/net/bluetooth/sco.c
|
||||
@@ -219,7 +219,7 @@ static int sco_connect(struct sock *sk)
|
||||
|
||||
BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
|
||||
|
||||
- hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src);
|
||||
+ hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
|
||||
if (!hdev)
|
||||
return -EHOSTUNREACH;
|
||||
|
||||
Reference in New Issue
Block a user