Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== pull request: bluetooth-next 2015-02-03 Here's what's likely the last bluetooth-next pull request for 3.20. Notable changes include: - xHCI workaround + a new id for the ath3k driver - Several new ids for the btusb driver - Support for new Intel Bluetooth controllers - Minor cleanups to ieee802154 code - Nested sleep warning fix in socket accept() code path - Fixes for Out of Band pairing handling - Support for LE scan restarting for HCI_QUIRK_STRICT_DUPLICATE_FILTER - Improvements to data we expose through debugfs - Proper handling of Hardware Error HCI events Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
45e826fd57
|
@ -108,6 +108,7 @@ static const struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3393) },
|
||||
{ USB_DEVICE(0x13d3, 0x3402) },
|
||||
{ USB_DEVICE(0x13d3, 0x3408) },
|
||||
{ USB_DEVICE(0x13d3, 0x3423) },
|
||||
{ USB_DEVICE(0x13d3, 0x3432) },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
|
@ -162,6 +163,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
|
@ -174,6 +176,8 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
#define USB_REQ_DFU_DNLOAD 1
|
||||
#define BULK_SIZE 4096
|
||||
#define FW_HDR_SIZE 20
|
||||
#define TIMEGAP_USEC_MIN 50
|
||||
#define TIMEGAP_USEC_MAX 100
|
||||
|
||||
static int ath3k_load_firmware(struct usb_device *udev,
|
||||
const struct firmware *firmware)
|
||||
|
@ -205,6 +209,9 @@ static int ath3k_load_firmware(struct usb_device *udev,
|
|||
pipe = usb_sndbulkpipe(udev, 0x02);
|
||||
|
||||
while (count) {
|
||||
/* workaround the compatibility issue with xHCI controller*/
|
||||
usleep_range(TIMEGAP_USEC_MIN, TIMEGAP_USEC_MAX);
|
||||
|
||||
size = min_t(uint, count, BULK_SIZE);
|
||||
memcpy(send_buf, firmware->data + sent, size);
|
||||
|
||||
|
@ -302,6 +309,9 @@ static int ath3k_load_fwfile(struct usb_device *udev,
|
|||
pipe = usb_sndbulkpipe(udev, 0x02);
|
||||
|
||||
while (count) {
|
||||
/* workaround the compatibility issue with xHCI controller*/
|
||||
usleep_range(TIMEGAP_USEC_MIN, TIMEGAP_USEC_MAX);
|
||||
|
||||
size = min_t(uint, count, BULK_SIZE);
|
||||
memcpy(send_buf, firmware->data + sent, size);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#define VERSION "0.6"
|
||||
#define VERSION "0.7"
|
||||
|
||||
static bool disable_scofix;
|
||||
static bool force_scofix;
|
||||
|
@ -50,11 +50,16 @@ static struct usb_driver btusb_driver;
|
|||
#define BTUSB_BCM_PATCHRAM 0x400
|
||||
#define BTUSB_MARVELL 0x800
|
||||
#define BTUSB_SWAVE 0x1000
|
||||
#define BTUSB_INTEL_NEW 0x2000
|
||||
#define BTUSB_AMP 0x4000
|
||||
|
||||
static const struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
|
||||
|
||||
/* Generic Bluetooth AMP device */
|
||||
{ USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP },
|
||||
|
||||
/* Apple-specific (Broadcom) devices */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) },
|
||||
|
||||
|
@ -110,16 +115,24 @@ static const struct usb_device_id btusb_table[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3404),
|
||||
.driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Broadcom BCM20702B0 (Dynex/Insignia) */
|
||||
{ USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Foxconn - Hon Hai */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
|
||||
.driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Lite-On Technology - Broadcom based */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x04ca, 0xff, 0x01, 0x01),
|
||||
.driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Broadcom devices with vendor specific id */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
|
||||
.driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* ASUSTek Computer - Broadcom based */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) },
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01),
|
||||
.driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Belkin F8065bf - Broadcom based */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
|
||||
|
@ -189,6 +202,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
|
@ -253,14 +267,19 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x16d3, 0x0002),
|
||||
.driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
|
||||
|
||||
/* Intel Bluetooth device */
|
||||
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
|
||||
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
|
||||
|
||||
/* Marvell device */
|
||||
/* Marvell Bluetooth devices */
|
||||
{ USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL },
|
||||
{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
|
||||
|
||||
/* Intel Bluetooth devices */
|
||||
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
|
||||
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
|
||||
{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW },
|
||||
|
||||
/* Other Intel Bluetooth devices */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
|
||||
.driver_info = BTUSB_IGNORE },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
@ -271,6 +290,11 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
#define BTUSB_ISOC_RUNNING 2
|
||||
#define BTUSB_SUSPENDING 3
|
||||
#define BTUSB_DID_ISO_RESUME 4
|
||||
#define BTUSB_BOOTLOADER 5
|
||||
#define BTUSB_DOWNLOADING 6
|
||||
#define BTUSB_FIRMWARE_LOADED 7
|
||||
#define BTUSB_FIRMWARE_FAILED 8
|
||||
#define BTUSB_BOOTING 9
|
||||
|
||||
struct btusb_data {
|
||||
struct hci_dev *hdev;
|
||||
|
@ -304,6 +328,7 @@ struct btusb_data {
|
|||
struct usb_endpoint_descriptor *isoc_rx_ep;
|
||||
|
||||
__u8 cmdreq_type;
|
||||
__u8 cmdreq;
|
||||
|
||||
unsigned int sco_num;
|
||||
int isoc_altsetting;
|
||||
|
@ -313,6 +338,16 @@ struct btusb_data {
|
|||
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
|
||||
};
|
||||
|
||||
static int btusb_wait_on_bit_timeout(void *word, int bit, unsigned long timeout,
|
||||
unsigned mode)
|
||||
{
|
||||
might_sleep();
|
||||
if (!test_bit(bit, word))
|
||||
return 0;
|
||||
return out_of_line_wait_on_bit_timeout(word, bit, bit_wait_timeout,
|
||||
mode, timeout);
|
||||
}
|
||||
|
||||
static inline void btusb_free_frags(struct btusb_data *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -957,7 +992,7 @@ static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
dr->bRequestType = data->cmdreq_type;
|
||||
dr->bRequest = 0;
|
||||
dr->bRequest = data->cmdreq;
|
||||
dr->wIndex = 0;
|
||||
dr->wValue = 0;
|
||||
dr->wLength = __cpu_to_le16(skb->len);
|
||||
|
@ -1295,6 +1330,26 @@ struct intel_version {
|
|||
u8 fw_patch_num;
|
||||
} __packed;
|
||||
|
||||
struct intel_boot_params {
|
||||
__u8 status;
|
||||
__u8 otp_format;
|
||||
__u8 otp_content;
|
||||
__u8 otp_patch;
|
||||
__le16 dev_revid;
|
||||
__u8 secure_boot;
|
||||
__u8 key_from_hdr;
|
||||
__u8 key_type;
|
||||
__u8 otp_lock;
|
||||
__u8 api_lock;
|
||||
__u8 debug_lock;
|
||||
bdaddr_t otp_bdaddr;
|
||||
__u8 min_fw_build_nn;
|
||||
__u8 min_fw_build_cw;
|
||||
__u8 min_fw_build_yy;
|
||||
__u8 limited_cce;
|
||||
__u8 unlocked_state;
|
||||
} __packed;
|
||||
|
||||
static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
|
||||
struct intel_version *ver)
|
||||
{
|
||||
|
@ -1703,6 +1758,562 @@ exit_mfg_deactivate:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct hci_event_hdr *hdr;
|
||||
struct hci_ev_cmd_complete *evt;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
hdr = (struct hci_event_hdr *)skb_put(skb, sizeof(*hdr));
|
||||
hdr->evt = HCI_EV_CMD_COMPLETE;
|
||||
hdr->plen = sizeof(*evt) + 1;
|
||||
|
||||
evt = (struct hci_ev_cmd_complete *)skb_put(skb, sizeof(*evt));
|
||||
evt->ncmd = 0x01;
|
||||
evt->opcode = cpu_to_le16(opcode);
|
||||
|
||||
*skb_put(skb, 1) = 0x00;
|
||||
|
||||
bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
|
||||
|
||||
return hci_recv_frame(hdev, skb);
|
||||
}
|
||||
|
||||
static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer,
|
||||
int count)
|
||||
{
|
||||
/* When the device is in bootloader mode, then it can send
|
||||
* events via the bulk endpoint. These events are treated the
|
||||
* same way as the ones received from the interrupt endpoint.
|
||||
*/
|
||||
if (test_bit(BTUSB_BOOTLOADER, &data->flags))
|
||||
return btusb_recv_intr(data, buffer, count);
|
||||
|
||||
return btusb_recv_bulk(data, buffer, count);
|
||||
}
|
||||
|
||||
static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
|
||||
if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
|
||||
struct hci_event_hdr *hdr = (void *)skb->data;
|
||||
|
||||
/* When the firmware loading completes the device sends
|
||||
* out a vendor specific event indicating the result of
|
||||
* the firmware loading.
|
||||
*/
|
||||
if (skb->len == 7 && hdr->evt == 0xff && hdr->plen == 0x05 &&
|
||||
skb->data[2] == 0x06) {
|
||||
if (skb->data[3] != 0x00)
|
||||
test_bit(BTUSB_FIRMWARE_FAILED, &data->flags);
|
||||
|
||||
if (test_and_clear_bit(BTUSB_DOWNLOADING,
|
||||
&data->flags) &&
|
||||
test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) {
|
||||
smp_mb__after_atomic();
|
||||
wake_up_bit(&data->flags, BTUSB_DOWNLOADING);
|
||||
}
|
||||
}
|
||||
|
||||
/* When switching to the operational firmware the device
|
||||
* sends a vendor specific event indicating that the bootup
|
||||
* completed.
|
||||
*/
|
||||
if (skb->len == 9 && hdr->evt == 0xff && hdr->plen == 0x07 &&
|
||||
skb->data[2] == 0x02) {
|
||||
if (test_and_clear_bit(BTUSB_BOOTING, &data->flags)) {
|
||||
smp_mb__after_atomic();
|
||||
wake_up_bit(&data->flags, BTUSB_BOOTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hci_recv_frame(hdev, skb);
|
||||
}
|
||||
|
||||
static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
struct urb *urb;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
switch (bt_cb(skb)->pkt_type) {
|
||||
case HCI_COMMAND_PKT:
|
||||
if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
|
||||
struct hci_command_hdr *cmd = (void *)skb->data;
|
||||
__u16 opcode = le16_to_cpu(cmd->opcode);
|
||||
|
||||
/* When in bootloader mode and the command 0xfc09
|
||||
* is received, it needs to be send down the
|
||||
* bulk endpoint. So allocate a bulk URB instead.
|
||||
*/
|
||||
if (opcode == 0xfc09)
|
||||
urb = alloc_bulk_urb(hdev, skb);
|
||||
else
|
||||
urb = alloc_ctrl_urb(hdev, skb);
|
||||
|
||||
/* When the 0xfc01 command is issued to boot into
|
||||
* the operational firmware, it will actually not
|
||||
* send a command complete event. To keep the flow
|
||||
* control working inject that event here.
|
||||
*/
|
||||
if (opcode == 0xfc01)
|
||||
inject_cmd_complete(hdev, opcode);
|
||||
} else {
|
||||
urb = alloc_ctrl_urb(hdev, skb);
|
||||
}
|
||||
if (IS_ERR(urb))
|
||||
return PTR_ERR(urb);
|
||||
|
||||
hdev->stat.cmd_tx++;
|
||||
return submit_or_queue_tx_urb(hdev, urb);
|
||||
|
||||
case HCI_ACLDATA_PKT:
|
||||
urb = alloc_bulk_urb(hdev, skb);
|
||||
if (IS_ERR(urb))
|
||||
return PTR_ERR(urb);
|
||||
|
||||
hdev->stat.acl_tx++;
|
||||
return submit_or_queue_tx_urb(hdev, urb);
|
||||
|
||||
case HCI_SCODATA_PKT:
|
||||
if (hci_conn_num(hdev, SCO_LINK) < 1)
|
||||
return -ENODEV;
|
||||
|
||||
urb = alloc_isoc_urb(hdev, skb);
|
||||
if (IS_ERR(urb))
|
||||
return PTR_ERR(urb);
|
||||
|
||||
hdev->stat.sco_tx++;
|
||||
return submit_tx_urb(hdev, urb);
|
||||
}
|
||||
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
static int btusb_intel_secure_send(struct hci_dev *hdev, u8 fragment_type,
|
||||
u32 plen, const void *param)
|
||||
{
|
||||
while (plen > 0) {
|
||||
struct sk_buff *skb;
|
||||
u8 cmd_param[253], fragment_len = (plen > 252) ? 252 : plen;
|
||||
|
||||
cmd_param[0] = fragment_type;
|
||||
memcpy(cmd_param + 1, param, fragment_len);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc09, fragment_len + 1,
|
||||
cmd_param, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
plen -= fragment_len;
|
||||
param += fragment_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btusb_intel_version_info(struct hci_dev *hdev,
|
||||
struct intel_version *ver)
|
||||
{
|
||||
const char *variant;
|
||||
|
||||
switch (ver->fw_variant) {
|
||||
case 0x06:
|
||||
variant = "Bootloader";
|
||||
break;
|
||||
case 0x23:
|
||||
variant = "Firmware";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
BT_INFO("%s: %s revision %u.%u build %u week %u %u", hdev->name,
|
||||
variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f,
|
||||
ver->fw_build_num, ver->fw_build_ww, 2000 + ver->fw_build_yy);
|
||||
}
|
||||
|
||||
static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
{
|
||||
static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
|
||||
0x00, 0x08, 0x04, 0x00 };
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
struct sk_buff *skb;
|
||||
struct intel_version *ver;
|
||||
struct intel_boot_params *params;
|
||||
const struct firmware *fw;
|
||||
const u8 *fw_ptr;
|
||||
char fwname[64];
|
||||
ktime_t calltime, delta, rettime;
|
||||
unsigned long long duration;
|
||||
int err;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
calltime = ktime_get();
|
||||
|
||||
/* Read the Intel version information to determine if the device
|
||||
* is in bootloader mode or if it already has operational firmware
|
||||
* loaded.
|
||||
*/
|
||||
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s: Reading Intel version information failed (%ld)",
|
||||
hdev->name, PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*ver)) {
|
||||
BT_ERR("%s: Intel version event size mismatch", hdev->name);
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
ver = (struct intel_version *)skb->data;
|
||||
if (ver->status) {
|
||||
BT_ERR("%s: Intel version command failure (%02x)",
|
||||
hdev->name, ver->status);
|
||||
err = -bt_to_errno(ver->status);
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* The hardware platform number has a fixed value of 0x37 and
|
||||
* for now only accept this single value.
|
||||
*/
|
||||
if (ver->hw_platform != 0x37) {
|
||||
BT_ERR("%s: Unsupported Intel hardware platform (%u)",
|
||||
hdev->name, ver->hw_platform);
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* At the moment only the hardware variant iBT 3.0 (LnP/SfP) is
|
||||
* supported by this firmware loading method. This check has been
|
||||
* put in place to ensure correct forward compatibility options
|
||||
* when newer hardware variants come along.
|
||||
*/
|
||||
if (ver->hw_variant != 0x0b) {
|
||||
BT_ERR("%s: Unsupported Intel hardware variant (%u)",
|
||||
hdev->name, ver->hw_variant);
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
btusb_intel_version_info(hdev, ver);
|
||||
|
||||
/* The firmware variant determines if the device is in bootloader
|
||||
* mode or is running operational firmware. The value 0x06 identifies
|
||||
* the bootloader and the value 0x23 identifies the operational
|
||||
* firmware.
|
||||
*
|
||||
* When the operational firmware is already present, then only
|
||||
* the check for valid Bluetooth device address is needed. This
|
||||
* determines if the device will be added as configured or
|
||||
* unconfigured controller.
|
||||
*
|
||||
* It is not possible to use the Secure Boot Parameters in this
|
||||
* case since that command is only available in bootloader mode.
|
||||
*/
|
||||
if (ver->fw_variant == 0x23) {
|
||||
kfree_skb(skb);
|
||||
clear_bit(BTUSB_BOOTLOADER, &data->flags);
|
||||
btusb_check_bdaddr_intel(hdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the device is not in bootloader mode, then the only possible
|
||||
* choice is to return an error and abort the device initialization.
|
||||
*/
|
||||
if (ver->fw_variant != 0x06) {
|
||||
BT_ERR("%s: Unsupported Intel firmware variant (%u)",
|
||||
hdev->name, ver->fw_variant);
|
||||
kfree_skb(skb);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Read the secure boot parameters to identify the operating
|
||||
* details of the bootloader.
|
||||
*/
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s: Reading Intel boot parameters failed (%ld)",
|
||||
hdev->name, PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*params)) {
|
||||
BT_ERR("%s: Intel boot parameters size mismatch", hdev->name);
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
params = (struct intel_boot_params *)skb->data;
|
||||
if (params->status) {
|
||||
BT_ERR("%s: Intel boot parameters command failure (%02x)",
|
||||
hdev->name, params->status);
|
||||
err = -bt_to_errno(params->status);
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
BT_INFO("%s: Device revision is %u", hdev->name,
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
BT_INFO("%s: Secure boot is %s", hdev->name,
|
||||
params->secure_boot ? "enabled" : "disabled");
|
||||
|
||||
BT_INFO("%s: Minimum firmware build %u week %u %u", hdev->name,
|
||||
params->min_fw_build_nn, params->min_fw_build_cw,
|
||||
2000 + params->min_fw_build_yy);
|
||||
|
||||
/* It is required that every single firmware fragment is acknowledged
|
||||
* with a command complete event. If the boot parameters indicate
|
||||
* that this bootloader does not send them, then abort the setup.
|
||||
*/
|
||||
if (params->limited_cce != 0x00) {
|
||||
BT_ERR("%s: Unsupported Intel firmware loading method (%u)",
|
||||
hdev->name, params->limited_cce);
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If the OTP has no valid Bluetooth device address, then there will
|
||||
* also be no valid address for the operational firmware.
|
||||
*/
|
||||
if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) {
|
||||
BT_INFO("%s: No device address configured", hdev->name);
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
|
||||
}
|
||||
|
||||
/* With this Intel bootloader only the hardware variant and device
|
||||
* revision information are used to select the right firmware.
|
||||
*
|
||||
* Currently this bootloader support is limited to hardware variant
|
||||
* iBT 3.0 (LnP/SfP) which is identified by the value 11 (0x0b).
|
||||
*/
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.sfi",
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
err = request_firmware(&fw, fwname, &hdev->dev);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to load Intel firmware file (%d)",
|
||||
hdev->name, err);
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
BT_INFO("%s: Found device firmware: %s", hdev->name, fwname);
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
if (fw->size < 644) {
|
||||
BT_ERR("%s: Invalid size of firmware file (%zu)",
|
||||
hdev->name, fw->size);
|
||||
err = -EBADF;
|
||||
goto done;
|
||||
}
|
||||
|
||||
set_bit(BTUSB_DOWNLOADING, &data->flags);
|
||||
|
||||
/* Start the firmware download transaction with the Init fragment
|
||||
* represented by the 128 bytes of CSS header.
|
||||
*/
|
||||
err = btusb_intel_secure_send(hdev, 0x00, 128, fw->data);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware header (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of public key information from the firmware
|
||||
* as the PKey fragment.
|
||||
*/
|
||||
err = btusb_intel_secure_send(hdev, 0x03, 256, fw->data + 128);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware public key (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of signature information from the firmware
|
||||
* as the Sign fragment.
|
||||
*/
|
||||
err = btusb_intel_secure_send(hdev, 0x02, 256, fw->data + 388);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware signature (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data + 644;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd = (void *)fw_ptr;
|
||||
u8 cmd_len;
|
||||
|
||||
cmd_len = sizeof(*cmd) + cmd->plen;
|
||||
|
||||
/* Send each command from the firmware data buffer as
|
||||
* a single Data fragment.
|
||||
*/
|
||||
err = btusb_intel_secure_send(hdev, 0x01, cmd_len, fw_ptr);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware data (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr += cmd_len;
|
||||
}
|
||||
|
||||
set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
|
||||
|
||||
BT_INFO("%s: Waiting for firmware download to complete", hdev->name);
|
||||
|
||||
/* Before switching the device into operational mode and with that
|
||||
* booting the loaded firmware, wait for the bootloader notification
|
||||
* that all fragments have been successfully received.
|
||||
*
|
||||
* When the event processing receives the notification, then the
|
||||
* BTUSB_DOWNLOADING flag will be cleared.
|
||||
*
|
||||
* The firmware loading should not take longer than 5 seconds
|
||||
* and thus just timeout if that happens and fail the setup
|
||||
* of this device.
|
||||
*/
|
||||
err = btusb_wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING,
|
||||
msecs_to_jiffies(5000),
|
||||
TASK_INTERRUPTIBLE);
|
||||
if (err == 1) {
|
||||
BT_ERR("%s: Firmware loading interrupted", hdev->name);
|
||||
err = -EINTR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
BT_ERR("%s: Firmware loading timeout", hdev->name);
|
||||
err = -ETIMEDOUT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) {
|
||||
BT_ERR("%s: Firmware loading failed", hdev->name);
|
||||
err = -ENOEXEC;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rettime = ktime_get();
|
||||
delta = ktime_sub(rettime, calltime);
|
||||
duration = (unsigned long long) ktime_to_ns(delta) >> 10;
|
||||
|
||||
BT_INFO("%s: Firmware loaded in %llu usecs", hdev->name, duration);
|
||||
|
||||
done:
|
||||
release_firmware(fw);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
calltime = ktime_get();
|
||||
|
||||
set_bit(BTUSB_BOOTING, &data->flags);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
/* The bootloader will not indicate when the device is ready. This
|
||||
* is done by the operational firmware sending bootup notification.
|
||||
*
|
||||
* Booting into operational firmware should not take longer than
|
||||
* 1 second. However if that happens, then just fail the setup
|
||||
* since something went wrong.
|
||||
*/
|
||||
BT_INFO("%s: Waiting for device to boot", hdev->name);
|
||||
|
||||
err = btusb_wait_on_bit_timeout(&data->flags, BTUSB_BOOTING,
|
||||
msecs_to_jiffies(1000),
|
||||
TASK_INTERRUPTIBLE);
|
||||
|
||||
if (err == 1) {
|
||||
BT_ERR("%s: Device boot interrupted", hdev->name);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
BT_ERR("%s: Device boot timeout", hdev->name);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
rettime = ktime_get();
|
||||
delta = ktime_sub(rettime, calltime);
|
||||
duration = (unsigned long long) ktime_to_ns(delta) >> 10;
|
||||
|
||||
BT_INFO("%s: Device booted in %llu usecs", hdev->name, duration);
|
||||
|
||||
clear_bit(BTUSB_BOOTLOADER, &data->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btusb_hw_error_intel(struct hci_dev *hdev, u8 code)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u8 type = 0x00;
|
||||
|
||||
BT_ERR("%s: Hardware error 0x%2.2x", hdev->name, code);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s: Reset after hardware error failed (%ld)",
|
||||
hdev->name, PTR_ERR(skb));
|
||||
return;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s: Retrieving Intel exception info failed (%ld)",
|
||||
hdev->name, PTR_ERR(skb));
|
||||
return;
|
||||
}
|
||||
|
||||
if (skb->len != 13) {
|
||||
BT_ERR("%s: Exception info size mismatch", hdev->name);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (skb->data[0] != 0x00) {
|
||||
BT_ERR("%s: Exception info command failure (%02x)",
|
||||
hdev->name, skb->data[0]);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_ERR("%s: Exception info %s", hdev->name, (char *)(skb->data + 1));
|
||||
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
@ -2033,7 +2644,13 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
|
||||
return -ENODEV;
|
||||
|
||||
data->cmdreq_type = USB_TYPE_CLASS;
|
||||
if (id->driver_info & BTUSB_AMP) {
|
||||
data->cmdreq_type = USB_TYPE_CLASS | 0x01;
|
||||
data->cmdreq = 0x2b;
|
||||
} else {
|
||||
data->cmdreq_type = USB_TYPE_CLASS;
|
||||
data->cmdreq = 0x00;
|
||||
}
|
||||
|
||||
data->udev = interface_to_usbdev(intf);
|
||||
data->intf = intf;
|
||||
|
@ -2049,8 +2666,14 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
init_usb_anchor(&data->isoc_anchor);
|
||||
spin_lock_init(&data->rxlock);
|
||||
|
||||
data->recv_event = hci_recv_frame;
|
||||
data->recv_bulk = btusb_recv_bulk;
|
||||
if (id->driver_info & BTUSB_INTEL_NEW) {
|
||||
data->recv_event = btusb_recv_event_intel;
|
||||
data->recv_bulk = btusb_recv_bulk_intel;
|
||||
set_bit(BTUSB_BOOTLOADER, &data->flags);
|
||||
} else {
|
||||
data->recv_event = hci_recv_frame;
|
||||
data->recv_bulk = btusb_recv_bulk;
|
||||
}
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev)
|
||||
|
@ -2059,6 +2682,11 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
hdev->bus = HCI_USB;
|
||||
hci_set_drvdata(hdev, data);
|
||||
|
||||
if (id->driver_info & BTUSB_AMP)
|
||||
hdev->dev_type = HCI_AMP;
|
||||
else
|
||||
hdev->dev_type = HCI_BREDR;
|
||||
|
||||
data->hdev = hdev;
|
||||
|
||||
SET_HCIDEV_DEV(hdev, &intf->dev);
|
||||
|
@ -2081,6 +2709,15 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
if (id->driver_info & BTUSB_INTEL) {
|
||||
hdev->setup = btusb_setup_intel;
|
||||
hdev->set_bdaddr = btusb_set_bdaddr_intel;
|
||||
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_INTEL_NEW) {
|
||||
hdev->send = btusb_send_frame_intel;
|
||||
hdev->setup = btusb_setup_intel_new;
|
||||
hdev->hw_error = btusb_hw_error_intel;
|
||||
hdev->set_bdaddr = btusb_set_bdaddr_intel;
|
||||
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_MARVELL)
|
||||
|
@ -2094,11 +2731,18 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
if (id->driver_info & BTUSB_INTEL_BOOT)
|
||||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
||||
|
||||
if (id->driver_info & BTUSB_ATH3012)
|
||||
if (id->driver_info & BTUSB_ATH3012) {
|
||||
hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
|
||||
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
|
||||
}
|
||||
|
||||
/* Interface numbers are hardcoded in the specification */
|
||||
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
||||
if (id->driver_info & BTUSB_AMP) {
|
||||
/* AMP controllers do not support SCO packets */
|
||||
data->isoc = NULL;
|
||||
} else {
|
||||
/* Interface numbers are hardcoded in the specification */
|
||||
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
||||
}
|
||||
|
||||
if (!reset)
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
@ -2192,7 +2836,6 @@ static void btusb_disconnect(struct usb_interface *intf)
|
|||
else if (data->isoc)
|
||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||
|
||||
btusb_free_frags(data);
|
||||
hci_free_dev(hdev);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,9 @@
|
|||
#define CC2520_FREG_MASK 0x3F
|
||||
|
||||
/* status byte values */
|
||||
#define CC2520_STATUS_XOSC32M_STABLE (1 << 7)
|
||||
#define CC2520_STATUS_RSSI_VALID (1 << 6)
|
||||
#define CC2520_STATUS_TX_UNDERFLOW (1 << 3)
|
||||
#define CC2520_STATUS_XOSC32M_STABLE BIT(7)
|
||||
#define CC2520_STATUS_RSSI_VALID BIT(6)
|
||||
#define CC2520_STATUS_TX_UNDERFLOW BIT(3)
|
||||
|
||||
/* IEEE-802.15.4 defined constants (2.4 GHz logical channels) */
|
||||
#define CC2520_MINCHANNEL 11
|
||||
|
@ -549,14 +549,14 @@ cc2520_ed(struct ieee802154_hw *hw, u8 *level)
|
|||
u8 rssi;
|
||||
int ret;
|
||||
|
||||
ret = cc2520_read_register(priv , CC2520_RSSISTAT, &status);
|
||||
ret = cc2520_read_register(priv, CC2520_RSSISTAT, &status);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (status != RSSI_VALID)
|
||||
return -EINVAL;
|
||||
|
||||
ret = cc2520_read_register(priv , CC2520_RSSI, &rssi);
|
||||
ret = cc2520_read_register(priv, CC2520_RSSI, &rssi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -79,6 +79,8 @@ struct discovery_state {
|
|||
s8 rssi;
|
||||
u16 uuid_count;
|
||||
u8 (*uuids)[16];
|
||||
unsigned long scan_start;
|
||||
unsigned long scan_duration;
|
||||
};
|
||||
|
||||
struct hci_conn_hash {
|
||||
|
@ -145,6 +147,7 @@ struct oob_data {
|
|||
struct list_head list;
|
||||
bdaddr_t bdaddr;
|
||||
u8 bdaddr_type;
|
||||
u8 present;
|
||||
u8 hash192[16];
|
||||
u8 rand192[16];
|
||||
u8 hash256[16];
|
||||
|
@ -232,6 +235,7 @@ struct hci_dev {
|
|||
__u16 conn_info_min_age;
|
||||
__u16 conn_info_max_age;
|
||||
__u8 ssp_debug_mode;
|
||||
__u8 hw_error_code;
|
||||
__u32 clock;
|
||||
|
||||
__u16 devid_source;
|
||||
|
@ -293,6 +297,7 @@ struct hci_dev {
|
|||
|
||||
struct work_struct power_on;
|
||||
struct delayed_work power_off;
|
||||
struct work_struct error_reset;
|
||||
|
||||
__u16 discov_timeout;
|
||||
struct delayed_work discov_off;
|
||||
|
@ -351,6 +356,7 @@ struct hci_dev {
|
|||
unsigned long dev_flags;
|
||||
|
||||
struct delayed_work le_scan_disable;
|
||||
struct delayed_work le_scan_restart;
|
||||
|
||||
__s8 adv_tx_power;
|
||||
__u8 adv_data[HCI_MAX_AD_LENGTH];
|
||||
|
@ -369,6 +375,7 @@ struct hci_dev {
|
|||
int (*setup)(struct hci_dev *hdev);
|
||||
int (*send)(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
void (*notify)(struct hci_dev *hdev, unsigned int evt);
|
||||
void (*hw_error)(struct hci_dev *hdev, u8 code);
|
||||
int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
|
||||
};
|
||||
|
||||
|
@ -527,6 +534,8 @@ static inline void hci_discovery_filter_clear(struct hci_dev *hdev)
|
|||
hdev->discovery.uuid_count = 0;
|
||||
kfree(hdev->discovery.uuids);
|
||||
hdev->discovery.uuids = NULL;
|
||||
hdev->discovery.scan_start = 0;
|
||||
hdev->discovery.scan_duration = 0;
|
||||
}
|
||||
|
||||
bool hci_discovery_active(struct hci_dev *hdev);
|
||||
|
@ -1325,6 +1334,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
|
|||
#define DISCOV_INTERLEAVED_TIMEOUT 5120 /* msec */
|
||||
#define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04
|
||||
#define DISCOV_BREDR_INQUIRY_LEN 0x08
|
||||
#define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */
|
||||
|
||||
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
|
||||
int mgmt_new_settings(struct hci_dev *hdev);
|
||||
|
@ -1369,7 +1379,6 @@ int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||
void mgmt_auth_failed(struct hci_conn *conn, u8 status);
|
||||
void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
|
||||
void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
|
||||
void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
|
||||
void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
|
||||
u8 status);
|
||||
void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
|
||||
|
|
|
@ -301,10 +301,6 @@ struct mgmt_cp_user_passkey_neg_reply {
|
|||
#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0020
|
||||
#define MGMT_READ_LOCAL_OOB_DATA_SIZE 0
|
||||
struct mgmt_rp_read_local_oob_data {
|
||||
__u8 hash[16];
|
||||
__u8 rand[16];
|
||||
} __packed;
|
||||
struct mgmt_rp_read_local_oob_ext_data {
|
||||
__u8 hash192[16];
|
||||
__u8 rand192[16];
|
||||
__u8 hash256[16];
|
||||
|
|
|
@ -511,13 +511,12 @@ static int bnep_session(void *arg)
|
|||
|
||||
static struct device *bnep_get_device(struct bnep_session *session)
|
||||
{
|
||||
struct hci_conn *conn;
|
||||
struct l2cap_conn *conn = l2cap_pi(session->sock->sk)->chan->conn;
|
||||
|
||||
conn = l2cap_pi(session->sock->sk)->chan->conn->hcon;
|
||||
if (!conn)
|
||||
if (!conn || !conn->hcon)
|
||||
return NULL;
|
||||
|
||||
return &conn->dev;
|
||||
return &conn->hcon->dev;
|
||||
}
|
||||
|
||||
static struct device_type bnep_type = {
|
||||
|
|
|
@ -609,6 +609,7 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
|
|||
|
||||
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
|
||||
u8 mode = 0x01;
|
||||
|
||||
hci_req_add(req, HCI_OP_WRITE_SSP_MODE,
|
||||
sizeof(mode), &mode);
|
||||
} else {
|
||||
|
@ -870,8 +871,10 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt)
|
|||
hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
|
||||
|
||||
/* Enable Secure Connections if supported and configured */
|
||||
if (bredr_sc_enabled(hdev)) {
|
||||
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
|
||||
bredr_sc_enabled(hdev)) {
|
||||
u8 support = 0x01;
|
||||
|
||||
hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT,
|
||||
sizeof(support), &support);
|
||||
}
|
||||
|
@ -1614,6 +1617,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
|
|||
cancel_delayed_work(&hdev->service_cache);
|
||||
|
||||
cancel_delayed_work_sync(&hdev->le_scan_disable);
|
||||
cancel_delayed_work_sync(&hdev->le_scan_restart);
|
||||
|
||||
if (test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||
cancel_delayed_work_sync(&hdev->rpa_expired);
|
||||
|
@ -1625,6 +1629,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
|
|||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
|
||||
|
||||
if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
|
||||
if (hdev->dev_type == HCI_BREDR)
|
||||
mgmt_powered(hdev, 0);
|
||||
|
@ -1635,6 +1641,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
|
|||
hci_conn_hash_flush(hdev);
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
smp_unregister(hdev);
|
||||
|
||||
hci_notify(hdev, HCI_DEV_DOWN);
|
||||
|
||||
if (hdev->flush)
|
||||
|
@ -1714,32 +1722,14 @@ done:
|
|||
return err;
|
||||
}
|
||||
|
||||
int hci_dev_reset(__u16 dev)
|
||||
static int hci_dev_do_reset(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
hdev = hci_dev_get(dev);
|
||||
if (!hdev)
|
||||
return -ENODEV;
|
||||
BT_DBG("%s %p", hdev->name, hdev);
|
||||
|
||||
hci_req_lock(hdev);
|
||||
|
||||
if (!test_bit(HCI_UP, &hdev->flags)) {
|
||||
ret = -ENETDOWN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Drop queues */
|
||||
skb_queue_purge(&hdev->rx_q);
|
||||
skb_queue_purge(&hdev->cmd_q);
|
||||
|
@ -1762,12 +1752,41 @@ int hci_dev_reset(__u16 dev)
|
|||
|
||||
ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT);
|
||||
|
||||
done:
|
||||
hci_req_unlock(hdev);
|
||||
hci_dev_put(hdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hci_dev_reset(__u16 dev)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
int err;
|
||||
|
||||
hdev = hci_dev_get(dev);
|
||||
if (!hdev)
|
||||
return -ENODEV;
|
||||
|
||||
if (!test_bit(HCI_UP, &hdev->flags)) {
|
||||
err = -ENETDOWN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
|
||||
err = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = hci_dev_do_reset(hdev);
|
||||
|
||||
done:
|
||||
hci_dev_put(hdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
int hci_dev_reset_stat(__u16 dev)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
|
@ -2131,8 +2150,24 @@ static void hci_power_off(struct work_struct *work)
|
|||
BT_DBG("%s", hdev->name);
|
||||
|
||||
hci_dev_do_close(hdev);
|
||||
}
|
||||
|
||||
smp_unregister(hdev);
|
||||
static void hci_error_reset(struct work_struct *work)
|
||||
{
|
||||
struct hci_dev *hdev = container_of(work, struct hci_dev, error_reset);
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (hdev->hw_error)
|
||||
hdev->hw_error(hdev, hdev->hw_error_code);
|
||||
else
|
||||
BT_ERR("%s hardware error 0x%2.2x", hdev->name,
|
||||
hdev->hw_error_code);
|
||||
|
||||
if (hci_dev_do_close(hdev))
|
||||
return;
|
||||
|
||||
hci_dev_do_open(hdev);
|
||||
}
|
||||
|
||||
static void hci_discov_off(struct work_struct *work)
|
||||
|
@ -2547,9 +2582,15 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||
if (hash192 && rand192) {
|
||||
memcpy(data->hash192, hash192, sizeof(data->hash192));
|
||||
memcpy(data->rand192, rand192, sizeof(data->rand192));
|
||||
if (hash256 && rand256)
|
||||
data->present = 0x03;
|
||||
} else {
|
||||
memset(data->hash192, 0, sizeof(data->hash192));
|
||||
memset(data->rand192, 0, sizeof(data->rand192));
|
||||
if (hash256 && rand256)
|
||||
data->present = 0x02;
|
||||
else
|
||||
data->present = 0x00;
|
||||
}
|
||||
|
||||
if (hash256 && rand256) {
|
||||
|
@ -2558,6 +2599,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||
} else {
|
||||
memset(data->hash256, 0, sizeof(data->hash256));
|
||||
memset(data->rand256, 0, sizeof(data->rand256));
|
||||
if (hash192 && rand192)
|
||||
data->present = 0x01;
|
||||
}
|
||||
|
||||
BT_DBG("%s for %pMR", hdev->name, bdaddr);
|
||||
|
@ -2788,6 +2831,8 @@ static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status,
|
|||
return;
|
||||
}
|
||||
|
||||
hdev->discovery.scan_start = 0;
|
||||
|
||||
switch (hdev->discovery.type) {
|
||||
case DISCOV_TYPE_LE:
|
||||
hci_dev_lock(hdev);
|
||||
|
@ -2827,6 +2872,8 @@ static void le_scan_disable_work(struct work_struct *work)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
cancel_delayed_work_sync(&hdev->le_scan_restart);
|
||||
|
||||
hci_req_init(&req, hdev);
|
||||
|
||||
hci_req_add_le_scan_disable(&req);
|
||||
|
@ -2836,6 +2883,74 @@ static void le_scan_disable_work(struct work_struct *work)
|
|||
BT_ERR("Disable LE scanning request failed: err %d", err);
|
||||
}
|
||||
|
||||
static void le_scan_restart_work_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode)
|
||||
{
|
||||
unsigned long timeout, duration, scan_start, now;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (status) {
|
||||
BT_ERR("Failed to restart LE scan: status %d", status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) ||
|
||||
!hdev->discovery.scan_start)
|
||||
return;
|
||||
|
||||
/* When the scan was started, hdev->le_scan_disable has been queued
|
||||
* after duration from scan_start. During scan restart this job
|
||||
* has been canceled, and we need to queue it again after proper
|
||||
* timeout, to make sure that scan does not run indefinitely.
|
||||
*/
|
||||
duration = hdev->discovery.scan_duration;
|
||||
scan_start = hdev->discovery.scan_start;
|
||||
now = jiffies;
|
||||
if (now - scan_start <= duration) {
|
||||
int elapsed;
|
||||
|
||||
if (now >= scan_start)
|
||||
elapsed = now - scan_start;
|
||||
else
|
||||
elapsed = ULONG_MAX - scan_start + now;
|
||||
|
||||
timeout = duration - elapsed;
|
||||
} else {
|
||||
timeout = 0;
|
||||
}
|
||||
queue_delayed_work(hdev->workqueue,
|
||||
&hdev->le_scan_disable, timeout);
|
||||
}
|
||||
|
||||
static void le_scan_restart_work(struct work_struct *work)
|
||||
{
|
||||
struct hci_dev *hdev = container_of(work, struct hci_dev,
|
||||
le_scan_restart.work);
|
||||
struct hci_request req;
|
||||
struct hci_cp_le_set_scan_enable cp;
|
||||
int err;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
/* If controller is not scanning we are done. */
|
||||
if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
|
||||
return;
|
||||
|
||||
hci_req_init(&req, hdev);
|
||||
|
||||
hci_req_add_le_scan_disable(&req);
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
cp.enable = LE_SCAN_ENABLE;
|
||||
cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
|
||||
hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
|
||||
|
||||
err = hci_req_run(&req, le_scan_restart_work_complete);
|
||||
if (err)
|
||||
BT_ERR("Restart LE scan request failed: err %d", err);
|
||||
}
|
||||
|
||||
/* Copy the Identity Address of the controller.
|
||||
*
|
||||
* If the controller has a public BD_ADDR, then by default use that one.
|
||||
|
@ -2927,10 +3042,12 @@ struct hci_dev *hci_alloc_dev(void)
|
|||
INIT_WORK(&hdev->cmd_work, hci_cmd_work);
|
||||
INIT_WORK(&hdev->tx_work, hci_tx_work);
|
||||
INIT_WORK(&hdev->power_on, hci_power_on);
|
||||
INIT_WORK(&hdev->error_reset, hci_error_reset);
|
||||
|
||||
INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
|
||||
INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
|
||||
INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
|
||||
INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work);
|
||||
|
||||
skb_queue_head_init(&hdev->rx_q);
|
||||
skb_queue_head_init(&hdev->cmd_q);
|
||||
|
@ -3100,8 +3217,6 @@ void hci_unregister_dev(struct hci_dev *hdev)
|
|||
rfkill_destroy(hdev->rfkill);
|
||||
}
|
||||
|
||||
smp_unregister(hdev);
|
||||
|
||||
device_del(&hdev->dev);
|
||||
|
||||
debugfs_remove_recursive(hdev->debugfs);
|
||||
|
|
|
@ -156,6 +156,35 @@ static const struct file_operations uuids_fops = {
|
|||
.release = single_release,
|
||||
};
|
||||
|
||||
static int remote_oob_show(struct seq_file *f, void *ptr)
|
||||
{
|
||||
struct hci_dev *hdev = f->private;
|
||||
struct oob_data *data;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
list_for_each_entry(data, &hdev->remote_oob_data, list) {
|
||||
seq_printf(f, "%pMR (type %u) %u %*phN %*phN %*phN %*phN\n",
|
||||
&data->bdaddr, data->bdaddr_type, data->present,
|
||||
16, data->hash192, 16, data->rand192,
|
||||
16, data->hash256, 19, data->rand256);
|
||||
}
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int remote_oob_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, remote_oob_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations remote_oob_fops = {
|
||||
.open = remote_oob_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int conn_info_min_age_set(void *data, u64 val)
|
||||
{
|
||||
struct hci_dev *hdev = data;
|
||||
|
@ -212,6 +241,24 @@ static int conn_info_max_age_get(void *data, u64 *val)
|
|||
DEFINE_SIMPLE_ATTRIBUTE(conn_info_max_age_fops, conn_info_max_age_get,
|
||||
conn_info_max_age_set, "%llu\n");
|
||||
|
||||
static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hci_dev *hdev = file->private_data;
|
||||
char buf[3];
|
||||
|
||||
buf[0] = test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags) ? 'Y': 'N';
|
||||
buf[1] = '\n';
|
||||
buf[2] = '\0';
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static const struct file_operations use_debug_keys_fops = {
|
||||
.open = simple_open,
|
||||
.read = use_debug_keys_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
@ -238,17 +285,26 @@ void hci_debugfs_create_common(struct hci_dev *hdev)
|
|||
&hdev->manufacturer);
|
||||
debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
|
||||
debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
|
||||
debugfs_create_u8("hardware_error", 0444, hdev->debugfs,
|
||||
&hdev->hw_error_code);
|
||||
|
||||
debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
|
||||
&device_list_fops);
|
||||
debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
|
||||
&blacklist_fops);
|
||||
debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
|
||||
debugfs_create_file("remote_oob", 0400, hdev->debugfs, hdev,
|
||||
&remote_oob_fops);
|
||||
|
||||
debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
|
||||
&conn_info_min_age_fops);
|
||||
debugfs_create_file("conn_info_max_age", 0644, hdev->debugfs, hdev,
|
||||
&conn_info_max_age_fops);
|
||||
|
||||
if (lmp_ssp_capable(hdev) || lmp_le_capable(hdev))
|
||||
debugfs_create_file("use_debug_keys", 0444, hdev->debugfs,
|
||||
hdev, &use_debug_keys_fops);
|
||||
|
||||
if (lmp_sc_capable(hdev) || lmp_le_capable(hdev))
|
||||
debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
|
||||
hdev, &sc_only_mode_fops);
|
||||
|
@ -354,6 +410,24 @@ static int voice_setting_get(void *data, u64 *val)
|
|||
DEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get,
|
||||
NULL, "0x%4.4llx\n");
|
||||
|
||||
static ssize_t ssp_debug_mode_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hci_dev *hdev = file->private_data;
|
||||
char buf[3];
|
||||
|
||||
buf[0] = hdev->ssp_debug_mode ? 'Y': 'N';
|
||||
buf[1] = '\n';
|
||||
buf[2] = '\0';
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static const struct file_operations ssp_debug_mode_fops = {
|
||||
.open = simple_open,
|
||||
.read = ssp_debug_mode_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int auto_accept_delay_set(void *data, u64 val)
|
||||
{
|
||||
struct hci_dev *hdev = data;
|
||||
|
@ -474,9 +548,12 @@ void hci_debugfs_create_bredr(struct hci_dev *hdev)
|
|||
debugfs_create_file("voice_setting", 0444, hdev->debugfs, hdev,
|
||||
&voice_setting_fops);
|
||||
|
||||
if (lmp_ssp_capable(hdev))
|
||||
if (lmp_ssp_capable(hdev)) {
|
||||
debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs,
|
||||
hdev, &ssp_debug_mode_fops);
|
||||
debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
|
||||
hdev, &auto_accept_delay_fops);
|
||||
}
|
||||
|
||||
if (lmp_sniff_capable(hdev)) {
|
||||
debugfs_create_file("idle_timeout", 0644, hdev->debugfs,
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
#include "amp.h"
|
||||
#include "smp.h"
|
||||
|
||||
#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
|
||||
/* Handle HCI Event packets */
|
||||
|
||||
static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
@ -197,7 +200,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
/* Reset all non-persistent flags */
|
||||
hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
|
||||
|
||||
hdev->discovery.state = DISCOVERY_STOPPED;
|
||||
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
|
||||
|
||||
hdev->inq_tx_power = HCI_TX_POWER_INVALID;
|
||||
hdev->adv_tx_power = HCI_TX_POWER_INVALID;
|
||||
|
||||
|
@ -525,9 +529,7 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
hdev->features[1][0] &= ~LMP_HOST_SC;
|
||||
}
|
||||
|
||||
if (test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||
mgmt_sc_enable_complete(hdev, sent->support, status);
|
||||
else if (!status) {
|
||||
if (!test_bit(HCI_MGMT, &hdev->dev_flags) && !status) {
|
||||
if (sent->support)
|
||||
set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
|
||||
else
|
||||
|
@ -1487,6 +1489,21 @@ unlock:
|
|||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
u8 status = *((u8 *) skb->data);
|
||||
u8 *mode;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
if (status)
|
||||
return;
|
||||
|
||||
mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE);
|
||||
if (mode)
|
||||
hdev->ssp_debug_mode = *mode;
|
||||
}
|
||||
|
||||
static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
|
||||
{
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
@ -2669,7 +2686,8 @@ static void hci_remote_features_evt(struct hci_dev *hdev,
|
|||
if (conn->state != BT_CONFIG)
|
||||
goto unlock;
|
||||
|
||||
if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
|
||||
if (!ev->status && lmp_ext_feat_capable(hdev) &&
|
||||
lmp_ext_feat_capable(conn)) {
|
||||
struct hci_cp_read_remote_ext_features cp;
|
||||
cp.handle = ev->handle;
|
||||
cp.page = 0x01;
|
||||
|
@ -2980,6 +2998,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
hci_cc_read_tx_power(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_WRITE_SSP_DEBUG_MODE:
|
||||
hci_cc_write_ssp_debug_mode(hdev, skb);
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
|
||||
break;
|
||||
|
@ -3098,7 +3120,9 @@ static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
{
|
||||
struct hci_ev_hardware_error *ev = (void *) skb->data;
|
||||
|
||||
BT_ERR("%s hardware error 0x%2.2x", hdev->name, ev->code);
|
||||
hdev->hw_error_code = ev->code;
|
||||
|
||||
queue_work(hdev->req_workqueue, &hdev->error_reset);
|
||||
}
|
||||
|
||||
static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
@ -3857,6 +3881,52 @@ static u8 hci_get_auth_req(struct hci_conn *conn)
|
|||
return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01);
|
||||
}
|
||||
|
||||
static u8 bredr_oob_data_present(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
struct oob_data *data;
|
||||
|
||||
data = hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR);
|
||||
if (!data)
|
||||
return 0x00;
|
||||
|
||||
if (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) {
|
||||
if (bredr_sc_enabled(hdev)) {
|
||||
/* When Secure Connections is enabled, then just
|
||||
* return the present value stored with the OOB
|
||||
* data. The stored value contains the right present
|
||||
* information. However it can only be trusted when
|
||||
* not in Secure Connection Only mode.
|
||||
*/
|
||||
if (!test_bit(HCI_SC_ONLY, &hdev->dev_flags))
|
||||
return data->present;
|
||||
|
||||
/* When Secure Connections Only mode is enabled, then
|
||||
* the P-256 values are required. If they are not
|
||||
* available, then do not declare that OOB data is
|
||||
* present.
|
||||
*/
|
||||
if (!memcmp(data->rand256, ZERO_KEY, 16) ||
|
||||
!memcmp(data->hash256, ZERO_KEY, 16))
|
||||
return 0x00;
|
||||
|
||||
return 0x02;
|
||||
}
|
||||
|
||||
/* When Secure Connections is not enabled or actually
|
||||
* not supported by the hardware, then check that if
|
||||
* P-192 data values are present.
|
||||
*/
|
||||
if (!memcmp(data->rand192, ZERO_KEY, 16) ||
|
||||
!memcmp(data->hash192, ZERO_KEY, 16))
|
||||
return 0x00;
|
||||
|
||||
return 0x01;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_io_capa_request *ev = (void *) skb->data;
|
||||
|
@ -3908,12 +3978,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
conn->auth_type &= HCI_AT_NO_BONDING_MITM;
|
||||
|
||||
cp.authentication = conn->auth_type;
|
||||
|
||||
if (hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR) &&
|
||||
(conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
|
||||
cp.oob_data = 0x01;
|
||||
else
|
||||
cp.oob_data = 0x00;
|
||||
cp.oob_data = bredr_oob_data_present(conn);
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
|
||||
sizeof(cp), &cp);
|
||||
|
@ -4165,34 +4230,40 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
|
|||
goto unlock;
|
||||
|
||||
data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR);
|
||||
if (data) {
|
||||
if (bredr_sc_enabled(hdev)) {
|
||||
struct hci_cp_remote_oob_ext_data_reply cp;
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
|
||||
memcpy(cp.rand192, data->rand192, sizeof(cp.rand192));
|
||||
memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
|
||||
memcpy(cp.rand256, data->rand256, sizeof(cp.rand256));
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
|
||||
sizeof(cp), &cp);
|
||||
} else {
|
||||
struct hci_cp_remote_oob_data_reply cp;
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
memcpy(cp.hash, data->hash192, sizeof(cp.hash));
|
||||
memcpy(cp.rand, data->rand192, sizeof(cp.rand));
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
} else {
|
||||
if (!data) {
|
||||
struct hci_cp_remote_oob_data_neg_reply cp;
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
|
||||
sizeof(cp), &cp);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (bredr_sc_enabled(hdev)) {
|
||||
struct hci_cp_remote_oob_ext_data_reply cp;
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
if (test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
|
||||
memset(cp.hash192, 0, sizeof(cp.hash192));
|
||||
memset(cp.rand192, 0, sizeof(cp.rand192));
|
||||
} else {
|
||||
memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
|
||||
memcpy(cp.rand192, data->rand192, sizeof(cp.rand192));
|
||||
}
|
||||
memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
|
||||
memcpy(cp.rand256, data->rand256, sizeof(cp.rand256));
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
|
||||
sizeof(cp), &cp);
|
||||
} else {
|
||||
struct hci_cp_remote_oob_data_reply cp;
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
memcpy(cp.hash, data->hash192, sizeof(cp.hash));
|
||||
memcpy(cp.rand, data->rand192, sizeof(cp.rand));
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
unlock:
|
||||
|
|
|
@ -302,7 +302,7 @@ done:
|
|||
static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
|
||||
int flags)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||
struct sock *sk = sock->sk, *nsk;
|
||||
long timeo;
|
||||
int err = 0;
|
||||
|
@ -316,8 +316,6 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
|
|||
/* Wait for an incoming connection. (wake-one). */
|
||||
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
||||
while (1) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (sk->sk_state != BT_LISTEN) {
|
||||
err = -EBADFD;
|
||||
break;
|
||||
|
@ -338,10 +336,11 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
|
|||
}
|
||||
|
||||
release_sock(sk);
|
||||
timeo = schedule_timeout(timeo);
|
||||
|
||||
timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
|
||||
|
||||
lock_sock_nested(sk, L2CAP_NESTING_PARENT);
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(sk_sleep(sk), &wait);
|
||||
|
||||
if (err)
|
||||
|
|
|
@ -131,6 +131,9 @@ static const u16 mgmt_events[] = {
|
|||
|
||||
#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
|
||||
|
||||
#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
|
||||
struct pending_cmd {
|
||||
struct list_head list;
|
||||
u16 opcode;
|
||||
|
@ -3633,10 +3636,16 @@ unlock:
|
|||
static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
|
||||
void *data, u16 len)
|
||||
{
|
||||
struct mgmt_addr_info *addr = data;
|
||||
int err;
|
||||
|
||||
BT_DBG("%s ", hdev->name);
|
||||
|
||||
if (!bdaddr_type_is_valid(addr->type))
|
||||
return cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
|
||||
MGMT_STATUS_INVALID_PARAMS, addr,
|
||||
sizeof(*addr));
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
|
||||
|
@ -3663,28 +3672,53 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
|
|||
status, &cp->addr, sizeof(cp->addr));
|
||||
} else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
|
||||
struct mgmt_cp_add_remote_oob_ext_data *cp = data;
|
||||
u8 *rand192, *hash192;
|
||||
u8 *rand192, *hash192, *rand256, *hash256;
|
||||
u8 status;
|
||||
|
||||
if (cp->addr.type != BDADDR_BREDR) {
|
||||
err = cmd_complete(sk, hdev->id,
|
||||
MGMT_OP_ADD_REMOTE_OOB_DATA,
|
||||
MGMT_STATUS_INVALID_PARAMS,
|
||||
&cp->addr, sizeof(cp->addr));
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (bdaddr_type_is_le(cp->addr.type)) {
|
||||
/* Enforce zero-valued 192-bit parameters as
|
||||
* long as legacy SMP OOB isn't implemented.
|
||||
*/
|
||||
if (memcmp(cp->rand192, ZERO_KEY, 16) ||
|
||||
memcmp(cp->hash192, ZERO_KEY, 16)) {
|
||||
err = cmd_complete(sk, hdev->id,
|
||||
MGMT_OP_ADD_REMOTE_OOB_DATA,
|
||||
MGMT_STATUS_INVALID_PARAMS,
|
||||
addr, sizeof(*addr));
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
rand192 = NULL;
|
||||
hash192 = NULL;
|
||||
} else {
|
||||
rand192 = cp->rand192;
|
||||
hash192 = cp->hash192;
|
||||
/* In case one of the P-192 values is set to zero,
|
||||
* then just disable OOB data for P-192.
|
||||
*/
|
||||
if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
|
||||
!memcmp(cp->hash192, ZERO_KEY, 16)) {
|
||||
rand192 = NULL;
|
||||
hash192 = NULL;
|
||||
} else {
|
||||
rand192 = cp->rand192;
|
||||
hash192 = cp->hash192;
|
||||
}
|
||||
}
|
||||
|
||||
/* In case one of the P-256 values is set to zero, then just
|
||||
* disable OOB data for P-256.
|
||||
*/
|
||||
if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
|
||||
!memcmp(cp->hash256, ZERO_KEY, 16)) {
|
||||
rand256 = NULL;
|
||||
hash256 = NULL;
|
||||
} else {
|
||||
rand256 = cp->rand256;
|
||||
hash256 = cp->hash256;
|
||||
}
|
||||
|
||||
err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
|
||||
cp->addr.type, hash192, rand192,
|
||||
cp->hash256, cp->rand256);
|
||||
hash256, rand256);
|
||||
if (err < 0)
|
||||
status = MGMT_STATUS_FAILED;
|
||||
else
|
||||
|
@ -3862,6 +3896,9 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status,
|
|||
|
||||
hci_discovery_set_state(hdev, DISCOVERY_FINDING);
|
||||
|
||||
/* If the scan involves LE scan, pick proper timeout to schedule
|
||||
* hdev->le_scan_disable that will stop it.
|
||||
*/
|
||||
switch (hdev->discovery.type) {
|
||||
case DISCOV_TYPE_LE:
|
||||
timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
|
||||
|
@ -3878,9 +3915,23 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status,
|
|||
break;
|
||||
}
|
||||
|
||||
if (timeout)
|
||||
if (timeout) {
|
||||
/* When service discovery is used and the controller has
|
||||
* a strict duplicate filter, it is important to remember
|
||||
* the start and duration of the scan. This is required
|
||||
* for restarting scanning during the discovery phase.
|
||||
*/
|
||||
if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
|
||||
&hdev->quirks) &&
|
||||
(hdev->discovery.uuid_count > 0 ||
|
||||
hdev->discovery.rssi != HCI_RSSI_INVALID)) {
|
||||
hdev->discovery.scan_start = jiffies;
|
||||
hdev->discovery.scan_duration = timeout;
|
||||
}
|
||||
|
||||
queue_delayed_work(hdev->workqueue,
|
||||
&hdev->le_scan_disable, timeout);
|
||||
}
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
|
@ -4691,9 +4742,16 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
|||
* Dual-mode controllers shall operate with the public
|
||||
* address as its identity address for BR/EDR and LE. So
|
||||
* reject the attempt to create an invalid configuration.
|
||||
*
|
||||
* The same restrictions applies when secure connections
|
||||
* has been enabled. For BR/EDR this is a controller feature
|
||||
* while for LE it is a host stack feature. This means that
|
||||
* switching BR/EDR back on when secure connections has been
|
||||
* enabled is not a supported transaction.
|
||||
*/
|
||||
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
|
||||
bacmp(&hdev->static_addr, BDADDR_ANY)) {
|
||||
(bacmp(&hdev->static_addr, BDADDR_ANY) ||
|
||||
test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) {
|
||||
err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
|
||||
MGMT_STATUS_REJECTED);
|
||||
goto unlock;
|
||||
|
@ -4736,11 +4794,57 @@ unlock:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
struct mgmt_mode *cp;
|
||||
|
||||
BT_DBG("%s status %u", hdev->name, status);
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
|
||||
if (!cmd)
|
||||
goto unlock;
|
||||
|
||||
if (status) {
|
||||
cmd_status(cmd->sk, cmd->index, cmd->opcode,
|
||||
mgmt_status(status));
|
||||
goto remove;
|
||||
}
|
||||
|
||||
cp = cmd->param;
|
||||
|
||||
switch (cp->val) {
|
||||
case 0x00:
|
||||
clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
|
||||
clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
|
||||
break;
|
||||
case 0x01:
|
||||
set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
|
||||
clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
|
||||
break;
|
||||
case 0x02:
|
||||
set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
|
||||
set_bit(HCI_SC_ONLY, &hdev->dev_flags);
|
||||
break;
|
||||
}
|
||||
|
||||
send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
|
||||
new_settings(hdev, cmd->sk);
|
||||
|
||||
remove:
|
||||
mgmt_pending_remove(cmd);
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
|
||||
void *data, u16 len)
|
||||
{
|
||||
struct mgmt_mode *cp = data;
|
||||
struct pending_cmd *cmd;
|
||||
struct hci_request req;
|
||||
u8 val;
|
||||
int err;
|
||||
|
||||
|
@ -4751,6 +4855,12 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
|
|||
return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
|
||||
MGMT_STATUS_NOT_SUPPORTED);
|
||||
|
||||
if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
|
||||
lmp_sc_capable(hdev) &&
|
||||
!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
|
||||
return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
|
||||
MGMT_STATUS_REJECTED);
|
||||
|
||||
if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
|
||||
return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
|
||||
MGMT_STATUS_INVALID_PARAMS);
|
||||
|
@ -4804,17 +4914,14 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
|
||||
hci_req_init(&req, hdev);
|
||||
hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
|
||||
err = hci_req_run(&req, sc_enable_complete);
|
||||
if (err < 0) {
|
||||
mgmt_pending_remove(cmd);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (cp->val == 0x02)
|
||||
set_bit(HCI_SC_ONLY, &hdev->dev_flags);
|
||||
else
|
||||
clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
|
||||
|
||||
failed:
|
||||
hci_dev_unlock(hdev);
|
||||
return err;
|
||||
|
@ -6262,14 +6369,16 @@ static int powered_update_hci(struct hci_dev *hdev)
|
|||
|
||||
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
|
||||
!lmp_host_ssp_capable(hdev)) {
|
||||
u8 ssp = 1;
|
||||
u8 mode = 0x01;
|
||||
|
||||
hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
|
||||
}
|
||||
hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
|
||||
|
||||
if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
|
||||
u8 sc = 0x01;
|
||||
hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, sizeof(sc), &sc);
|
||||
if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
|
||||
u8 support = 0x01;
|
||||
|
||||
hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
|
||||
sizeof(support), &support);
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
|
||||
|
@ -6989,43 +7098,6 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
|
|||
hci_req_run(&req, NULL);
|
||||
}
|
||||
|
||||
void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
|
||||
{
|
||||
struct cmd_lookup match = { NULL, hdev };
|
||||
bool changed = false;
|
||||
|
||||
if (status) {
|
||||
u8 mgmt_err = mgmt_status(status);
|
||||
|
||||
if (enable) {
|
||||
if (test_and_clear_bit(HCI_SC_ENABLED,
|
||||
&hdev->dev_flags))
|
||||
new_settings(hdev, NULL);
|
||||
clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
|
||||
}
|
||||
|
||||
mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
|
||||
cmd_status_rsp, &mgmt_err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
|
||||
} else {
|
||||
changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
|
||||
clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
|
||||
}
|
||||
|
||||
mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
|
||||
settings_rsp, &match);
|
||||
|
||||
if (changed)
|
||||
new_settings(hdev, match.sk);
|
||||
|
||||
if (match.sk)
|
||||
sock_put(match.sk);
|
||||
}
|
||||
|
||||
static void sk_lookup(struct pending_cmd *cmd, void *data)
|
||||
{
|
||||
struct cmd_lookup *match = data;
|
||||
|
@ -7096,28 +7168,21 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
|
|||
cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||
mgmt_status(status));
|
||||
} else {
|
||||
struct mgmt_rp_read_local_oob_data rp;
|
||||
size_t rp_size = sizeof(rp);
|
||||
|
||||
memcpy(rp.hash192, hash192, sizeof(rp.hash192));
|
||||
memcpy(rp.rand192, rand192, sizeof(rp.rand192));
|
||||
|
||||
if (bredr_sc_enabled(hdev) && hash256 && rand256) {
|
||||
struct mgmt_rp_read_local_oob_ext_data rp;
|
||||
|
||||
memcpy(rp.hash192, hash192, sizeof(rp.hash192));
|
||||
memcpy(rp.rand192, rand192, sizeof(rp.rand192));
|
||||
|
||||
memcpy(rp.hash256, hash256, sizeof(rp.hash256));
|
||||
memcpy(rp.rand256, rand256, sizeof(rp.rand256));
|
||||
|
||||
cmd_complete(cmd->sk, hdev->id,
|
||||
MGMT_OP_READ_LOCAL_OOB_DATA, 0,
|
||||
&rp, sizeof(rp));
|
||||
} else {
|
||||
struct mgmt_rp_read_local_oob_data rp;
|
||||
|
||||
memcpy(rp.hash, hash192, sizeof(rp.hash));
|
||||
memcpy(rp.rand, rand192, sizeof(rp.rand));
|
||||
|
||||
cmd_complete(cmd->sk, hdev->id,
|
||||
MGMT_OP_READ_LOCAL_OOB_DATA, 0,
|
||||
&rp, sizeof(rp));
|
||||
rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
|
||||
}
|
||||
|
||||
cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, 0,
|
||||
&rp, rp_size);
|
||||
}
|
||||
|
||||
mgmt_pending_remove(cmd);
|
||||
|
@ -7190,6 +7255,21 @@ static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
|
|||
return false;
|
||||
}
|
||||
|
||||
static void restart_le_scan(struct hci_dev *hdev)
|
||||
{
|
||||
/* If controller is not scanning we are done. */
|
||||
if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
|
||||
return;
|
||||
|
||||
if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
|
||||
hdev->discovery.scan_start +
|
||||
hdev->discovery.scan_duration))
|
||||
return;
|
||||
|
||||
queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
|
||||
DISCOV_LE_RESTART_DELAY);
|
||||
}
|
||||
|
||||
void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
||||
u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
|
||||
u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
|
||||
|
@ -7212,14 +7292,18 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||
|
||||
/* When using service discovery with a RSSI threshold, then check
|
||||
* if such a RSSI threshold is specified. If a RSSI threshold has
|
||||
* been specified, then all results with a RSSI smaller than the
|
||||
* RSSI threshold will be dropped.
|
||||
* been specified, and HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set,
|
||||
* then all results with a RSSI smaller than the RSSI threshold will be
|
||||
* dropped. If the quirk is set, let it through for further processing,
|
||||
* as we might need to restart the scan.
|
||||
*
|
||||
* For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
|
||||
* the results are also dropped.
|
||||
*/
|
||||
if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
|
||||
(rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID))
|
||||
(rssi == HCI_RSSI_INVALID ||
|
||||
(rssi < hdev->discovery.rssi &&
|
||||
!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
|
||||
return;
|
||||
|
||||
/* Make sure that the buffer is big enough. The 5 extra bytes
|
||||
|
@ -7238,7 +7322,8 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||
* However when using service discovery, the value 127 will be
|
||||
* returned when the RSSI is not available.
|
||||
*/
|
||||
if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi)
|
||||
if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
|
||||
link_type == ACL_LINK)
|
||||
rssi = 0;
|
||||
|
||||
bacpy(&ev->addr.bdaddr, bdaddr);
|
||||
|
@ -7253,12 +7338,20 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||
* kept and checking possible scan response data
|
||||
* will be skipped.
|
||||
*/
|
||||
if (hdev->discovery.uuid_count > 0)
|
||||
if (hdev->discovery.uuid_count > 0) {
|
||||
match = eir_has_uuids(eir, eir_len,
|
||||
hdev->discovery.uuid_count,
|
||||
hdev->discovery.uuids);
|
||||
else
|
||||
/* If duplicate filtering does not report RSSI changes,
|
||||
* then restart scanning to ensure updated result with
|
||||
* updated RSSI values.
|
||||
*/
|
||||
if (match && test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
|
||||
&hdev->quirks))
|
||||
restart_le_scan(hdev);
|
||||
} else {
|
||||
match = true;
|
||||
}
|
||||
|
||||
if (!match && !scan_rsp_len)
|
||||
return;
|
||||
|
@ -7291,6 +7384,14 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||
hdev->discovery.uuid_count,
|
||||
hdev->discovery.uuids))
|
||||
return;
|
||||
|
||||
/* If duplicate filtering does not report RSSI changes,
|
||||
* then restart scanning to ensure updated result with
|
||||
* updated RSSI values.
|
||||
*/
|
||||
if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
|
||||
&hdev->quirks))
|
||||
restart_le_scan(hdev);
|
||||
}
|
||||
|
||||
/* Append scan response data to event */
|
||||
|
@ -7304,6 +7405,14 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Validate the reported RSSI value against the RSSI threshold once more
|
||||
* incase HCI_QUIRK_STRICT_DUPLICATE_FILTER forced a restart of LE
|
||||
* scanning.
|
||||
*/
|
||||
if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
|
||||
rssi < hdev->discovery.rssi)
|
||||
return;
|
||||
|
||||
ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
|
||||
ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
|
||||
|
||||
|
|
|
@ -468,7 +468,7 @@ done:
|
|||
|
||||
static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||
struct sock *sk = sock->sk, *nsk;
|
||||
long timeo;
|
||||
int err = 0;
|
||||
|
@ -487,8 +487,6 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
|
|||
/* Wait for an incoming connection. (wake-one). */
|
||||
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
||||
while (1) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (sk->sk_state != BT_LISTEN) {
|
||||
err = -EBADFD;
|
||||
break;
|
||||
|
@ -509,10 +507,11 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
|
|||
}
|
||||
|
||||
release_sock(sk);
|
||||
timeo = schedule_timeout(timeo);
|
||||
|
||||
timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
|
||||
|
||||
lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(sk_sleep(sk), &wait);
|
||||
|
||||
if (err)
|
||||
|
|
|
@ -618,7 +618,7 @@ done:
|
|||
|
||||
static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||
struct sock *sk = sock->sk, *ch;
|
||||
long timeo;
|
||||
int err = 0;
|
||||
|
@ -632,8 +632,6 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag
|
|||
/* Wait for an incoming connection. (wake-one). */
|
||||
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
||||
while (1) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (sk->sk_state != BT_LISTEN) {
|
||||
err = -EBADFD;
|
||||
break;
|
||||
|
@ -654,10 +652,10 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag
|
|||
}
|
||||
|
||||
release_sock(sk);
|
||||
timeo = schedule_timeout(timeo);
|
||||
|
||||
timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
|
||||
lock_sock(sk);
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(sk_sleep(sk), &wait);
|
||||
|
||||
if (err)
|
||||
|
|
|
@ -620,7 +620,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
|
|||
|
||||
oob_data = hci_find_remote_oob_data(hdev, &hcon->dst,
|
||||
bdaddr_type);
|
||||
if (oob_data) {
|
||||
if (oob_data && oob_data->present) {
|
||||
set_bit(SMP_FLAG_OOB, &smp->flags);
|
||||
oob_flag = SMP_OOB_PRESENT;
|
||||
memcpy(smp->rr, oob_data->rand256, 16);
|
||||
|
|
Loading…
Reference in New Issue