Commit 35ed663f authored by David S. Miller's avatar David S. Miller

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2018-02-15

Here's the first bluetooth-next pull request targetting the 4.17 kernel
release.

 - Fixes & cleanups to Atheros and Marvell drivers
 - Support for two new Realtek controllers
 - Support for new Intel Bluetooth controller
 - Fix for supporting multiple slave-role Bluetooth LE connections
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ddd00103 907f8499
...@@ -203,6 +203,12 @@ static const struct usb_device_id ath3k_blist_tbl[] = { ...@@ -203,6 +203,12 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
static inline void ath3k_log_failed_loading(int err, int len, int size)
{
BT_ERR("Error in firmware loading err = %d, len = %d, size = %d",
err, len, size);
}
#define USB_REQ_DFU_DNLOAD 1 #define USB_REQ_DFU_DNLOAD 1
#define BULK_SIZE 4096 #define BULK_SIZE 4096
#define FW_HDR_SIZE 20 #define FW_HDR_SIZE 20
...@@ -227,15 +233,16 @@ static int ath3k_load_firmware(struct usb_device *udev, ...@@ -227,15 +233,16 @@ static int ath3k_load_firmware(struct usb_device *udev,
return -ENOMEM; return -ENOMEM;
} }
memcpy(send_buf, firmware->data, 20); memcpy(send_buf, firmware->data, FW_HDR_SIZE);
err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR, err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR,
0, 0, send_buf, 20, USB_CTRL_SET_TIMEOUT); 0, 0, send_buf, FW_HDR_SIZE,
USB_CTRL_SET_TIMEOUT);
if (err < 0) { if (err < 0) {
BT_ERR("Can't change to loading configuration err"); BT_ERR("Can't change to loading configuration err");
goto error; goto error;
} }
sent += 20; sent += FW_HDR_SIZE;
count -= 20; count -= FW_HDR_SIZE;
pipe = usb_sndbulkpipe(udev, 0x02); pipe = usb_sndbulkpipe(udev, 0x02);
...@@ -250,8 +257,7 @@ static int ath3k_load_firmware(struct usb_device *udev, ...@@ -250,8 +257,7 @@ static int ath3k_load_firmware(struct usb_device *udev,
&len, 3000); &len, 3000);
if (err || (len != size)) { if (err || (len != size)) {
BT_ERR("Error in firmware loading err = %d," ath3k_log_failed_loading(err, len, size);
"len = %d, size = %d", err, len, size);
goto error; goto error;
} }
...@@ -350,8 +356,7 @@ static int ath3k_load_fwfile(struct usb_device *udev, ...@@ -350,8 +356,7 @@ static int ath3k_load_fwfile(struct usb_device *udev,
err = usb_bulk_msg(udev, pipe, send_buf, size, err = usb_bulk_msg(udev, pipe, send_buf, size,
&len, 3000); &len, 3000);
if (err || (len != size)) { if (err || (len != size)) {
BT_ERR("Error in firmware loading err = %d," ath3k_log_failed_loading(err, len, size);
"len = %d, size = %d", err, len, size);
kfree(send_buf); kfree(send_buf);
return err; return err;
} }
...@@ -398,7 +403,7 @@ static int ath3k_set_normal_mode(struct usb_device *udev) ...@@ -398,7 +403,7 @@ static int ath3k_set_normal_mode(struct usb_device *udev)
static int ath3k_load_patch(struct usb_device *udev) static int ath3k_load_patch(struct usb_device *udev)
{ {
unsigned char fw_state; unsigned char fw_state;
char filename[ATH3K_NAME_LEN] = {0}; char filename[ATH3K_NAME_LEN];
const struct firmware *firmware; const struct firmware *firmware;
struct ath3k_version fw_version; struct ath3k_version fw_version;
__u32 pt_rom_version, pt_build_version; __u32 pt_rom_version, pt_build_version;
...@@ -451,7 +456,7 @@ static int ath3k_load_patch(struct usb_device *udev) ...@@ -451,7 +456,7 @@ static int ath3k_load_patch(struct usb_device *udev)
static int ath3k_load_syscfg(struct usb_device *udev) static int ath3k_load_syscfg(struct usb_device *udev)
{ {
unsigned char fw_state; unsigned char fw_state;
char filename[ATH3K_NAME_LEN] = {0}; char filename[ATH3K_NAME_LEN];
const struct firmware *firmware; const struct firmware *firmware;
struct ath3k_version fw_version; struct ath3k_version fw_version;
int clk_value, ret; int clk_value, ret;
...@@ -522,7 +527,6 @@ static int ath3k_probe(struct usb_interface *intf, ...@@ -522,7 +527,6 @@ static int ath3k_probe(struct usb_interface *intf,
/* load patch and sysconfig files for AR3012 */ /* load patch and sysconfig files for AR3012 */
if (id->driver_info & BTUSB_ATH3012) { if (id->driver_info & BTUSB_ATH3012) {
/* New firmware with patch and sysconfig files already loaded */ /* New firmware with patch and sysconfig files already loaded */
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001) if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001)
return -ENODEV; return -ENODEV;
...@@ -565,7 +569,7 @@ static int ath3k_probe(struct usb_interface *intf, ...@@ -565,7 +569,7 @@ static int ath3k_probe(struct usb_interface *intf,
static void ath3k_disconnect(struct usb_interface *intf) static void ath3k_disconnect(struct usb_interface *intf)
{ {
BT_DBG("ath3k_disconnect intf %p", intf); BT_DBG("%s intf %p", __func__, intf);
} }
static struct usb_driver ath3k_driver = { static struct usb_driver ath3k_driver = {
......
...@@ -183,7 +183,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode, ...@@ -183,7 +183,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
return -EFAULT; return -EFAULT;
} }
skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC); skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_KERNEL);
if (!skb) { if (!skb) {
BT_ERR("No free skb"); BT_ERR("No free skb");
return -ENOMEM; return -ENOMEM;
......
...@@ -35,6 +35,60 @@ ...@@ -35,6 +35,60 @@
#define RTL_ROM_LMP_8761A 0x8761 #define RTL_ROM_LMP_8761A 0x8761
#define RTL_ROM_LMP_8822B 0x8822 #define RTL_ROM_LMP_8822B 0x8822
#define IC_MATCH_FL_LMPSUBV (1 << 0)
#define IC_MATCH_FL_HCIREV (1 << 1)
#define IC_INFO(lmps, hcir) \
.match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_HCIREV, \
.lmp_subver = (lmps), \
.hci_rev = (hcir)
struct id_table {
__u16 match_flags;
__u16 lmp_subver;
__u16 hci_rev;
bool config_needed;
char *fw_name;
char *cfg_name;
};
static const struct id_table ic_id_table[] = {
/* 8723B */
{ IC_INFO(RTL_ROM_LMP_8723B, 0xb),
.config_needed = false,
.fw_name = "rtl_bt/rtl8723b_fw.bin",
.cfg_name = "rtl_bt/rtl8723b_config.bin" },
/* 8723D */
{ IC_INFO(RTL_ROM_LMP_8723B, 0xd),
.config_needed = true,
.fw_name = "rtl_bt/rtl8723d_fw.bin",
.cfg_name = "rtl_bt/rtl8723d_config.bin" },
/* 8821A */
{ IC_INFO(RTL_ROM_LMP_8821A, 0xa),
.config_needed = false,
.fw_name = "rtl_bt/rtl8821a_fw.bin",
.cfg_name = "rtl_bt/rtl8821a_config.bin" },
/* 8821C */
{ IC_INFO(RTL_ROM_LMP_8821A, 0xc),
.config_needed = false,
.fw_name = "rtl_bt/rtl8821c_fw.bin",
.cfg_name = "rtl_bt/rtl8821c_config.bin" },
/* 8761A */
{ IC_MATCH_FL_LMPSUBV, RTL_ROM_LMP_8761A, 0x0,
.config_needed = false,
.fw_name = "rtl_bt/rtl8761a_fw.bin",
.cfg_name = "rtl_bt/rtl8761a_config.bin" },
/* 8822B */
{ IC_INFO(RTL_ROM_LMP_8822B, 0xb),
.config_needed = true,
.fw_name = "rtl_bt/rtl8822b_fw.bin",
.cfg_name = "rtl_bt/rtl8822b_config.bin" },
};
static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version) static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version)
{ {
struct rtl_rom_version_evt *rom_version; struct rtl_rom_version_evt *rom_version;
...@@ -64,7 +118,7 @@ static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version) ...@@ -64,7 +118,7 @@ static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version)
return 0; return 0;
} }
static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver, static int rtlbt_parse_firmware(struct hci_dev *hdev, u16 lmp_subver,
const struct firmware *fw, const struct firmware *fw,
unsigned char **_buf) unsigned char **_buf)
{ {
...@@ -88,6 +142,8 @@ static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver, ...@@ -88,6 +142,8 @@ static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver,
{ RTL_ROM_LMP_8821A, 2 }, { RTL_ROM_LMP_8821A, 2 },
{ RTL_ROM_LMP_8761A, 3 }, { RTL_ROM_LMP_8761A, 3 },
{ RTL_ROM_LMP_8822B, 8 }, { RTL_ROM_LMP_8822B, 8 },
{ RTL_ROM_LMP_8723B, 9 }, /* 8723D */
{ RTL_ROM_LMP_8821A, 10 }, /* 8821C */
}; };
ret = rtl_read_rom_version(hdev, &rom_version); ret = rtl_read_rom_version(hdev, &rom_version);
...@@ -320,8 +376,8 @@ static int btrtl_setup_rtl8723a(struct hci_dev *hdev) ...@@ -320,8 +376,8 @@ static int btrtl_setup_rtl8723a(struct hci_dev *hdev)
return ret; return ret;
} }
static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver, static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 hci_rev,
const char *fw_name) u16 lmp_subver)
{ {
unsigned char *fw_data = NULL; unsigned char *fw_data = NULL;
const struct firmware *fw; const struct firmware *fw;
...@@ -330,39 +386,40 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver, ...@@ -330,39 +386,40 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
u8 *cfg_buff = NULL; u8 *cfg_buff = NULL;
u8 *tbuff; u8 *tbuff;
char *cfg_name = NULL; char *cfg_name = NULL;
bool config_needed = false; char *fw_name = NULL;
int i;
for (i = 0; i < ARRAY_SIZE(ic_id_table); i++) {
if ((ic_id_table[i].match_flags & IC_MATCH_FL_LMPSUBV) &&
(ic_id_table[i].lmp_subver != lmp_subver))
continue;
if ((ic_id_table[i].match_flags & IC_MATCH_FL_HCIREV) &&
(ic_id_table[i].hci_rev != hci_rev))
continue;
switch (lmp_subver) {
case RTL_ROM_LMP_8723B:
cfg_name = "rtl_bt/rtl8723b_config.bin";
break;
case RTL_ROM_LMP_8821A:
cfg_name = "rtl_bt/rtl8821a_config.bin";
break;
case RTL_ROM_LMP_8761A:
cfg_name = "rtl_bt/rtl8761a_config.bin";
break;
case RTL_ROM_LMP_8822B:
cfg_name = "rtl_bt/rtl8822b_config.bin";
config_needed = true;
break;
default:
BT_ERR("%s: rtl: no config according to lmp_subver %04x",
hdev->name, lmp_subver);
break; break;
} }
if (i >= ARRAY_SIZE(ic_id_table)) {
BT_ERR("%s: unknown IC info, lmp subver %04x, hci rev %04x",
hdev->name, lmp_subver, hci_rev);
return -EINVAL;
}
cfg_name = ic_id_table[i].cfg_name;
if (cfg_name) { if (cfg_name) {
cfg_sz = rtl_load_config(hdev, cfg_name, &cfg_buff); cfg_sz = rtl_load_config(hdev, cfg_name, &cfg_buff);
if (cfg_sz < 0) { if (cfg_sz < 0) {
cfg_sz = 0; cfg_sz = 0;
if (config_needed) if (ic_id_table[i].config_needed)
BT_ERR("Necessary config file %s not found\n", BT_ERR("Necessary config file %s not found\n",
cfg_name); cfg_name);
} }
} else } else
cfg_sz = 0; cfg_sz = 0;
fw_name = ic_id_table[i].fw_name;
bt_dev_info(hdev, "rtl: loading %s", fw_name); bt_dev_info(hdev, "rtl: loading %s", fw_name);
ret = request_firmware(&fw, fw_name, &hdev->dev); ret = request_firmware(&fw, fw_name, &hdev->dev);
if (ret < 0) { if (ret < 0) {
...@@ -370,7 +427,7 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver, ...@@ -370,7 +427,7 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
goto err_req_fw; goto err_req_fw;
} }
ret = rtl8723b_parse_firmware(hdev, lmp_subver, fw, &fw_data); ret = rtlbt_parse_firmware(hdev, lmp_subver, fw, &fw_data);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -429,7 +486,7 @@ int btrtl_setup_realtek(struct hci_dev *hdev) ...@@ -429,7 +486,7 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct hci_rp_read_local_version *resp; struct hci_rp_read_local_version *resp;
u16 lmp_subver; u16 hci_rev, lmp_subver;
skb = btrtl_read_local_version(hdev); skb = btrtl_read_local_version(hdev);
if (IS_ERR(skb)) if (IS_ERR(skb))
...@@ -441,6 +498,7 @@ int btrtl_setup_realtek(struct hci_dev *hdev) ...@@ -441,6 +498,7 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
resp->hci_ver, resp->hci_rev, resp->hci_ver, resp->hci_rev,
resp->lmp_ver, resp->lmp_subver); resp->lmp_ver, resp->lmp_subver);
hci_rev = le16_to_cpu(resp->hci_rev);
lmp_subver = le16_to_cpu(resp->lmp_subver); lmp_subver = le16_to_cpu(resp->lmp_subver);
kfree_skb(skb); kfree_skb(skb);
...@@ -455,17 +513,10 @@ int btrtl_setup_realtek(struct hci_dev *hdev) ...@@ -455,17 +513,10 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
case RTL_ROM_LMP_3499: case RTL_ROM_LMP_3499:
return btrtl_setup_rtl8723a(hdev); return btrtl_setup_rtl8723a(hdev);
case RTL_ROM_LMP_8723B: case RTL_ROM_LMP_8723B:
return btrtl_setup_rtl8723b(hdev, lmp_subver,
"rtl_bt/rtl8723b_fw.bin");
case RTL_ROM_LMP_8821A: case RTL_ROM_LMP_8821A:
return btrtl_setup_rtl8723b(hdev, lmp_subver,
"rtl_bt/rtl8821a_fw.bin");
case RTL_ROM_LMP_8761A: case RTL_ROM_LMP_8761A:
return btrtl_setup_rtl8723b(hdev, lmp_subver,
"rtl_bt/rtl8761a_fw.bin");
case RTL_ROM_LMP_8822B: case RTL_ROM_LMP_8822B:
return btrtl_setup_rtl8723b(hdev, lmp_subver, return btrtl_setup_rtl8723b(hdev, hci_rev, lmp_subver);
"rtl_bt/rtl8822b_fw.bin");
default: default:
bt_dev_info(hdev, "rtl: assuming no firmware upload needed"); bt_dev_info(hdev, "rtl: assuming no firmware upload needed");
return 0; return 0;
......
...@@ -339,6 +339,7 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -339,6 +339,7 @@ static const struct usb_device_id blacklist_table[] = {
/* Intel Bluetooth devices */ /* Intel Bluetooth devices */
{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW }, { USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW },
{ USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_NEW },
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
...@@ -373,6 +374,9 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -373,6 +374,9 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
/* Additional Realtek 8822BE Bluetooth devices */
{ USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK },
/* Silicon Wave based devices */ /* Silicon Wave based devices */
{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE }, { USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
...@@ -2057,6 +2061,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2057,6 +2061,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
case 0x0c: /* WsP */ case 0x0c: /* WsP */
case 0x11: /* JfP */ case 0x11: /* JfP */
case 0x12: /* ThP */ case 0x12: /* ThP */
case 0x13: /* HrP */
case 0x14: /* QnJ, IcP */
break; break;
default: default:
BT_ERR("%s: Unsupported Intel hardware variant (%u)", BT_ERR("%s: Unsupported Intel hardware variant (%u)",
...@@ -2149,6 +2155,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2149,6 +2155,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
break; break;
case 0x11: /* JfP */ case 0x11: /* JfP */
case 0x12: /* ThP */ case 0x12: /* ThP */
case 0x13: /* HrP */
case 0x14: /* QnJ, IcP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi", snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi",
le16_to_cpu(ver.hw_variant), le16_to_cpu(ver.hw_variant),
le16_to_cpu(ver.hw_revision), le16_to_cpu(ver.hw_revision),
...@@ -2180,6 +2188,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2180,6 +2188,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
break; break;
case 0x11: /* JfP */ case 0x11: /* JfP */
case 0x12: /* ThP */ case 0x12: /* ThP */
case 0x13: /* HrP */
case 0x14: /* QnJ, IcP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc", snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc",
le16_to_cpu(ver.hw_variant), le16_to_cpu(ver.hw_variant),
le16_to_cpu(ver.hw_revision), le16_to_cpu(ver.hw_revision),
......
...@@ -71,12 +71,12 @@ static int ath_wakeup_ar3k(struct tty_struct *tty) ...@@ -71,12 +71,12 @@ static int ath_wakeup_ar3k(struct tty_struct *tty)
/* Clear RTS first */ /* Clear RTS first */
tty->driver->ops->tiocmget(tty); tty->driver->ops->tiocmget(tty);
tty->driver->ops->tiocmset(tty, 0x00, TIOCM_RTS); tty->driver->ops->tiocmset(tty, 0x00, TIOCM_RTS);
mdelay(20); msleep(20);
/* Set RTS, wake up board */ /* Set RTS, wake up board */
tty->driver->ops->tiocmget(tty); tty->driver->ops->tiocmget(tty);
tty->driver->ops->tiocmset(tty, TIOCM_RTS, 0x00); tty->driver->ops->tiocmset(tty, TIOCM_RTS, 0x00);
mdelay(20); msleep(20);
status = tty->driver->ops->tiocmget(tty); status = tty->driver->ops->tiocmget(tty);
return status; return status;
......
...@@ -650,7 +650,7 @@ static int download_firmware(struct ll_device *lldev) ...@@ -650,7 +650,7 @@ static int download_firmware(struct ll_device *lldev)
break; break;
case ACTION_DELAY: /* sleep */ case ACTION_DELAY: /* sleep */
bt_dev_info(lldev->hu.hdev, "sleep command in scr"); bt_dev_info(lldev->hu.hdev, "sleep command in scr");
mdelay(((struct bts_action_delay *)action_ptr)->msec); msleep(((struct bts_action_delay *)action_ptr)->msec);
break; break;
} }
len -= (sizeof(struct bts_action) + len -= (sizeof(struct bts_action) +
......
...@@ -934,8 +934,8 @@ static bool is_advertising_allowed(struct hci_dev *hdev, bool connectable) ...@@ -934,8 +934,8 @@ static bool is_advertising_allowed(struct hci_dev *hdev, bool connectable)
/* Slave connection state and connectable mode bit 38 /* Slave connection state and connectable mode bit 38
* and scannable bit 21. * and scannable bit 21.
*/ */
if (connectable && (!(hdev->le_states[4] & 0x01) || if (connectable && (!(hdev->le_states[4] & 0x40) ||
!(hdev->le_states[2] & 0x40))) !(hdev->le_states[2] & 0x20)))
return false; return false;
} }
...@@ -948,7 +948,7 @@ static bool is_advertising_allowed(struct hci_dev *hdev, bool connectable) ...@@ -948,7 +948,7 @@ static bool is_advertising_allowed(struct hci_dev *hdev, bool connectable)
/* Master connection state and connectable mode bit 35 and /* Master connection state and connectable mode bit 35 and
* scannable 19. * scannable 19.
*/ */
if (connectable && (!(hdev->le_states[4] & 0x10) || if (connectable && (!(hdev->le_states[4] & 0x08) ||
!(hdev->le_states[2] & 0x08))) !(hdev->le_states[2] & 0x08)))
return false; return false;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment