Skip to content

Commit a5eb1ae

Browse files
committed
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Conflicts: drivers/bluetooth/btusb.c
2 parents 737be10 + d7b2545 commit a5eb1ae

File tree

13 files changed

+653
-124
lines changed

13 files changed

+653
-124
lines changed

drivers/bluetooth/btusb.c

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static struct usb_driver btusb_driver;
4949
#define BTUSB_WRONG_SCO_MTU 0x40
5050
#define BTUSB_ATH3012 0x80
5151
#define BTUSB_INTEL 0x100
52+
#define BTUSB_BCM_PATCHRAM 0x200
5253

5354
static const struct usb_device_id btusb_table[] = {
5455
/* Generic Bluetooth USB device */
@@ -111,7 +112,8 @@ static const struct usb_device_id btusb_table[] = {
111112
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
112113

113114
/* Broadcom devices with vendor specific id */
114-
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
115+
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
116+
.driver_info = BTUSB_BCM_PATCHRAM },
115117

116118
/* Belkin F8065bf - Broadcom based */
117119
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
@@ -1381,6 +1383,154 @@ static int btusb_setup_intel(struct hci_dev *hdev)
13811383
return 0;
13821384
}
13831385

1386+
static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
1387+
{
1388+
struct btusb_data *data = hci_get_drvdata(hdev);
1389+
struct usb_device *udev = data->udev;
1390+
char fw_name[64];
1391+
const struct firmware *fw;
1392+
const u8 *fw_ptr;
1393+
size_t fw_size;
1394+
const struct hci_command_hdr *cmd;
1395+
const u8 *cmd_param;
1396+
u16 opcode;
1397+
struct sk_buff *skb;
1398+
struct hci_rp_read_local_version *ver;
1399+
long ret;
1400+
1401+
snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd",
1402+
udev->product ? udev->product : "BCM",
1403+
le16_to_cpu(udev->descriptor.idVendor),
1404+
le16_to_cpu(udev->descriptor.idProduct));
1405+
1406+
ret = request_firmware(&fw, fw_name, &hdev->dev);
1407+
if (ret < 0) {
1408+
BT_INFO("%s: BCM: patch %s not found", hdev->name,
1409+
fw_name);
1410+
return 0;
1411+
}
1412+
1413+
/* Reset */
1414+
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
1415+
if (IS_ERR(skb)) {
1416+
ret = PTR_ERR(skb);
1417+
BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret);
1418+
goto done;
1419+
}
1420+
kfree_skb(skb);
1421+
1422+
/* Read Local Version Info */
1423+
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
1424+
HCI_INIT_TIMEOUT);
1425+
if (IS_ERR(skb)) {
1426+
ret = PTR_ERR(skb);
1427+
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
1428+
hdev->name, ret);
1429+
goto done;
1430+
}
1431+
1432+
if (skb->len != sizeof(*ver)) {
1433+
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
1434+
hdev->name);
1435+
kfree_skb(skb);
1436+
ret = -EIO;
1437+
goto done;
1438+
}
1439+
1440+
ver = (struct hci_rp_read_local_version *) skb->data;
1441+
BT_INFO("%s: BCM: patching hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
1442+
"lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev,
1443+
ver->lmp_ver, ver->lmp_subver);
1444+
kfree_skb(skb);
1445+
1446+
/* Start Download */
1447+
skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT);
1448+
if (IS_ERR(skb)) {
1449+
ret = PTR_ERR(skb);
1450+
BT_ERR("%s: BCM: Download Minidrv command failed (%ld)",
1451+
hdev->name, ret);
1452+
goto reset_fw;
1453+
}
1454+
kfree_skb(skb);
1455+
1456+
/* 50 msec delay after Download Minidrv completes */
1457+
msleep(50);
1458+
1459+
fw_ptr = fw->data;
1460+
fw_size = fw->size;
1461+
1462+
while (fw_size >= sizeof(*cmd)) {
1463+
cmd = (struct hci_command_hdr *) fw_ptr;
1464+
fw_ptr += sizeof(*cmd);
1465+
fw_size -= sizeof(*cmd);
1466+
1467+
if (fw_size < cmd->plen) {
1468+
BT_ERR("%s: BCM: patch %s is corrupted",
1469+
hdev->name, fw_name);
1470+
ret = -EINVAL;
1471+
goto reset_fw;
1472+
}
1473+
1474+
cmd_param = fw_ptr;
1475+
fw_ptr += cmd->plen;
1476+
fw_size -= cmd->plen;
1477+
1478+
opcode = le16_to_cpu(cmd->opcode);
1479+
1480+
skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param,
1481+
HCI_INIT_TIMEOUT);
1482+
if (IS_ERR(skb)) {
1483+
ret = PTR_ERR(skb);
1484+
BT_ERR("%s: BCM: patch command %04x failed (%ld)",
1485+
hdev->name, opcode, ret);
1486+
goto reset_fw;
1487+
}
1488+
kfree_skb(skb);
1489+
}
1490+
1491+
/* 250 msec delay after Launch Ram completes */
1492+
msleep(250);
1493+
1494+
reset_fw:
1495+
/* Reset */
1496+
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
1497+
if (IS_ERR(skb)) {
1498+
ret = PTR_ERR(skb);
1499+
BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret);
1500+
goto done;
1501+
}
1502+
kfree_skb(skb);
1503+
1504+
/* Read Local Version Info */
1505+
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
1506+
HCI_INIT_TIMEOUT);
1507+
if (IS_ERR(skb)) {
1508+
ret = PTR_ERR(skb);
1509+
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
1510+
hdev->name, ret);
1511+
goto done;
1512+
}
1513+
1514+
if (skb->len != sizeof(*ver)) {
1515+
BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
1516+
hdev->name);
1517+
kfree_skb(skb);
1518+
ret = -EIO;
1519+
goto done;
1520+
}
1521+
1522+
ver = (struct hci_rp_read_local_version *) skb->data;
1523+
BT_INFO("%s: BCM: firmware hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
1524+
"lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev,
1525+
ver->lmp_ver, ver->lmp_subver);
1526+
kfree_skb(skb);
1527+
1528+
done:
1529+
release_firmware(fw);
1530+
1531+
return ret;
1532+
}
1533+
13841534
static int btusb_probe(struct usb_interface *intf,
13851535
const struct usb_device_id *id)
13861536
{
@@ -1486,6 +1636,9 @@ static int btusb_probe(struct usb_interface *intf,
14861636
if (id->driver_info & BTUSB_BCM92035)
14871637
hdev->setup = btusb_setup_bcm92035;
14881638

1639+
if (id->driver_info & BTUSB_BCM_PATCHRAM)
1640+
hdev->setup = btusb_setup_bcm_patchram;
1641+
14891642
if (id->driver_info & BTUSB_INTEL)
14901643
hdev->setup = btusb_setup_intel;
14911644

include/net/bluetooth/hci.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,17 @@ struct hci_cp_write_page_scan_activity {
10541054
__le16 window;
10551055
} __packed;
10561056

1057+
#define HCI_OP_READ_TX_POWER 0x0c2d
1058+
struct hci_cp_read_tx_power {
1059+
__le16 handle;
1060+
__u8 type;
1061+
} __packed;
1062+
struct hci_rp_read_tx_power {
1063+
__u8 status;
1064+
__le16 handle;
1065+
__s8 tx_power;
1066+
} __packed;
1067+
10571068
#define HCI_OP_READ_PAGE_SCAN_TYPE 0x0c46
10581069
struct hci_rp_read_page_scan_type {
10591070
__u8 status;
@@ -1064,6 +1075,16 @@ struct hci_rp_read_page_scan_type {
10641075
#define PAGE_SCAN_TYPE_STANDARD 0x00
10651076
#define PAGE_SCAN_TYPE_INTERLACED 0x01
10661077

1078+
#define HCI_OP_READ_RSSI 0x1405
1079+
struct hci_cp_read_rssi {
1080+
__le16 handle;
1081+
} __packed;
1082+
struct hci_rp_read_rssi {
1083+
__u8 status;
1084+
__le16 handle;
1085+
__s8 rssi;
1086+
} __packed;
1087+
10671088
#define HCI_OP_READ_LOCAL_AMP_INFO 0x1409
10681089
struct hci_rp_read_local_amp_info {
10691090
__u8 status;

include/net/bluetooth/hci_core.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ struct oob_data {
145145
/* Default LE RPA expiry time, 15 minutes */
146146
#define HCI_DEFAULT_RPA_TIMEOUT (15 * 60)
147147

148+
/* Default min/max age of connection information (1s/3s) */
149+
#define DEFAULT_CONN_INFO_MIN_AGE 1000
150+
#define DEFAULT_CONN_INFO_MAX_AGE 3000
151+
148152
struct amp_assoc {
149153
__u16 len;
150154
__u16 offset;
@@ -200,6 +204,8 @@ struct hci_dev {
200204
__u16 le_conn_min_interval;
201205
__u16 le_conn_max_interval;
202206
__u16 discov_interleaved_timeout;
207+
__u16 conn_info_min_age;
208+
__u16 conn_info_max_age;
203209
__u8 ssp_debug_mode;
204210

205211
__u16 devid_source;
@@ -374,8 +380,13 @@ struct hci_conn {
374380
__u16 setting;
375381
__u16 le_conn_min_interval;
376382
__u16 le_conn_max_interval;
383+
__s8 rssi;
384+
__s8 tx_power;
385+
__s8 max_tx_power;
377386
unsigned long flags;
378387

388+
unsigned long conn_info_timestamp;
389+
379390
__u8 remote_cap;
380391
__u8 remote_auth;
381392
__u8 remote_id;

include/net/bluetooth/mgmt.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ struct mgmt_cp_load_link_keys {
181181
} __packed;
182182
#define MGMT_LOAD_LINK_KEYS_SIZE 3
183183

184+
#define MGMT_LTK_UNAUTHENTICATED 0x00
185+
#define MGMT_LTK_AUTHENTICATED 0x01
186+
184187
struct mgmt_ltk_info {
185188
struct mgmt_addr_info addr;
186189
__u8 type;
@@ -409,6 +412,18 @@ struct mgmt_cp_load_irks {
409412
} __packed;
410413
#define MGMT_LOAD_IRKS_SIZE 2
411414

415+
#define MGMT_OP_GET_CONN_INFO 0x0031
416+
struct mgmt_cp_get_conn_info {
417+
struct mgmt_addr_info addr;
418+
} __packed;
419+
#define MGMT_GET_CONN_INFO_SIZE MGMT_ADDR_INFO_SIZE
420+
struct mgmt_rp_get_conn_info {
421+
struct mgmt_addr_info addr;
422+
__s8 rssi;
423+
__s8 tx_power;
424+
__s8 max_tx_power;
425+
} __packed;
426+
412427
#define MGMT_EV_CMD_COMPLETE 0x0001
413428
struct mgmt_ev_cmd_complete {
414429
__le16 opcode;

include/net/bluetooth/rfcomm.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ struct rfcomm_dlc {
173173
struct sk_buff_head tx_queue;
174174
struct timer_list timer;
175175

176-
spinlock_t lock;
176+
struct mutex lock;
177177
unsigned long state;
178178
unsigned long flags;
179179
atomic_t refcnt;
@@ -244,8 +244,8 @@ int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
244244
void rfcomm_dlc_accept(struct rfcomm_dlc *d);
245245
struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel);
246246

247-
#define rfcomm_dlc_lock(d) spin_lock(&d->lock)
248-
#define rfcomm_dlc_unlock(d) spin_unlock(&d->lock)
247+
#define rfcomm_dlc_lock(d) mutex_lock(&d->lock)
248+
#define rfcomm_dlc_unlock(d) mutex_unlock(&d->lock)
249249

250250
static inline void rfcomm_dlc_hold(struct rfcomm_dlc *d)
251251
{

net/bluetooth/hci_conn.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include <net/bluetooth/bluetooth.h>
3030
#include <net/bluetooth/hci_core.h>
31+
#include <net/bluetooth/l2cap.h>
3132

3233
#include "smp.h"
3334
#include "a2mp.h"
@@ -407,6 +408,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
407408
conn->io_capability = hdev->io_capability;
408409
conn->remote_auth = 0xff;
409410
conn->key_type = 0xff;
411+
conn->tx_power = HCI_TX_POWER_INVALID;
412+
conn->max_tx_power = HCI_TX_POWER_INVALID;
410413

411414
set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
412415
conn->disc_timeout = HCI_DISCONN_TIMEOUT;

0 commit comments

Comments
 (0)