Commit 748a7099 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 2017-12-18

Here's the first bluetooth-next pull request for the 4.16 kernel.

 - hci_ll: multiple cleanups & fixes
 - Remove Gustavo Padovan from the MAINTAINERS file
 - Support BLE Adversing while connected (if the controller can do it)
 - DT updates for TI chips
 - Various other smaller cleanups & fixes

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 566bd54b 22b371cb
TI WiLink 7/8 (wl12xx/wl18xx) Shared Transport BT/FM/GPS devices
Texas Instruments Bluetooth Chips
---------------------------------
This documents the binding structure and common properties for serial
attached TI Bluetooth devices. The following chips are included in this
binding:
* TI CC256x Bluetooth devices
* TI WiLink 7/8 (wl12xx/wl18xx) Shared Transport BT/FM/GPS devices
TI WiLink devices have a UART interface for providing Bluetooth, FM radio,
and GPS over what's called "shared transport". The shared transport is
standard BT HCI protocol with additional channels for the other functions.
These devices also have a separate WiFi interface as described in
TI WiLink devices also have a separate WiFi interface as described in
wireless/ti,wlcore.txt.
This bindings follows the UART slave device binding in
......@@ -12,6 +20,7 @@ This bindings follows the UART slave device binding in
Required properties:
- compatible: should be one of the following:
"ti,cc2560"
"ti,wl1271-st"
"ti,wl1273-st"
"ti,wl1281-st"
......@@ -32,6 +41,9 @@ Optional properties:
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entry:
"ext_clock" (External clock provided to the TI combo chip).
- nvmem-cells: phandle to nvmem data cell that contains a 6 byte BD address
with the most significant byte first (big-endian).
- nvmem-cell-names: "bd-address" (required when nvmem-cells is specified)
Example:
......@@ -43,5 +55,7 @@ Example:
enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
clocks = <&clk32k_wl18xx>;
clock-names = "ext_clock";
nvmem-cells = <&bd_address>;
nvmem-cell-names = "bd-address";
};
};
......@@ -2689,7 +2689,6 @@ F: drivers/mtd/devices/block2mtd.c
BLUETOOTH DRIVERS
M: Marcel Holtmann <marcel@holtmann.org>
M: Gustavo Padovan <gustavo@padovan.org>
M: Johan Hedberg <johan.hedberg@gmail.com>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
......@@ -2700,7 +2699,6 @@ F: drivers/bluetooth/
BLUETOOTH SUBSYSTEM
M: Marcel Holtmann <marcel@holtmann.org>
M: Gustavo Padovan <gustavo@padovan.org>
M: Johan Hedberg <johan.hedberg@gmail.com>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
......
......@@ -31,6 +31,16 @@ config BT_HCIBTUSB
Say Y here to compile support for Bluetooth USB devices into the
kernel or say M to compile it as module (btusb).
config BT_HCIBTUSB_AUTOSUSPEND
bool "Enable USB autosuspend for Bluetooth USB devices by default"
depends on BT_HCIBTUSB
help
Say Y here to enable USB autosuspend for Bluetooth USB devices by
default.
This can be overridden by passing btusb.enable_autosuspend=[y|n]
on the kernel commandline.
config BT_HCIBTUSB_BCM
bool "Broadcom protocol support"
depends on BT_HCIBTUSB
......
......@@ -302,9 +302,7 @@ static void bluecard_write_wakeup(struct bluecard_info *info)
}
/* Wait until the command reaches the baseband */
prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
schedule_timeout(HZ/10);
finish_wait(&wq, &wait);
mdelay(100);
/* Set baud on baseband */
info->ctrl_reg &= ~0x03;
......@@ -316,9 +314,7 @@ static void bluecard_write_wakeup(struct bluecard_info *info)
outb(info->ctrl_reg, iobase + REG_CONTROL);
/* Wait before the next HCI packet can be send */
prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
finish_wait(&wq, &wait);
mdelay(1000);
}
if (len == skb->len) {
......
......@@ -88,7 +88,8 @@ static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
break;
}
kfree_skb(skb);
if (!ret)
kfree_skb(skb);
return ret;
}
......
......@@ -31,6 +31,7 @@
#include <linux/errno.h>
#include <linux/skbuff.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
......@@ -292,6 +293,14 @@ static int btsdio_probe(struct sdio_func *func,
tuple = tuple->next;
}
/* BCM43341 devices soldered onto the PCB (non-removable) use an
* uart connection for bluetooth, ignore the BT SDIO interface.
*/
if (func->vendor == SDIO_VENDOR_ID_BROADCOM &&
func->device == SDIO_DEVICE_ID_BROADCOM_43341 &&
!mmc_card_is_removable(func->card->host))
return -ENODEV;
data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
......
......@@ -40,6 +40,7 @@
static bool disable_scofix;
static bool force_scofix;
static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
static bool reset = true;
......@@ -3213,6 +3214,9 @@ static int btusb_probe(struct usb_interface *intf,
}
#endif
if (enable_autosuspend)
usb_enable_autosuspend(data->udev);
err = hci_register_dev(hdev);
if (err < 0)
goto out_free_dev;
......@@ -3425,6 +3429,9 @@ MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
module_param(force_scofix, bool, 0644);
MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size");
module_param(enable_autosuspend, bool, 0644);
MODULE_PARM_DESC(enable_autosuspend, "Enable USB autosuspend by default");
module_param(reset, bool, 0644);
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
......
......@@ -939,6 +939,7 @@ static const struct acpi_device_id bcm_acpi_match[] = {
{ "BCM2E65", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E67", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E71", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E72", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E7B", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E7C", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E7E", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
......
......@@ -53,9 +53,14 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <linux/gpio/consumer.h>
#include <linux/nvmem-consumer.h>
#include "hci_uart.h"
/* Vendor-specific HCI commands */
#define HCI_VS_WRITE_BD_ADDR 0xfc06
#define HCI_VS_UPDATE_UART_HCI_BAUDRATE 0xff36
/* HCILL commands */
#define HCILL_GO_TO_SLEEP_IND 0x30
#define HCILL_GO_TO_SLEEP_ACK 0x31
......@@ -86,6 +91,7 @@ struct ll_device {
struct serdev_device *serdev;
struct gpio_desc *enable_gpio;
struct clk *ext_clk;
bdaddr_t bdaddr;
};
struct ll_struct {
......@@ -620,7 +626,7 @@ static int download_firmware(struct ll_device *lldev)
case ACTION_SEND_COMMAND: /* action send */
bt_dev_dbg(lldev->hu.hdev, "S");
cmd = (struct hci_command *)action_ptr;
if (cmd->opcode == 0xff36) {
if (cmd->opcode == HCI_VS_UPDATE_UART_HCI_BAUDRATE) {
/* ignore remote change
* baud rate HCI VS command
*/
......@@ -628,11 +634,11 @@ static int download_firmware(struct ll_device *lldev)
break;
}
if (cmd->prefix != 1)
bt_dev_dbg(lldev->hu.hdev, "command type %d\n", cmd->prefix);
bt_dev_dbg(lldev->hu.hdev, "command type %d", cmd->prefix);
skb = __hci_cmd_sync(lldev->hu.hdev, cmd->opcode, cmd->plen, &cmd->speed, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(lldev->hu.hdev, "send command failed\n");
bt_dev_err(lldev->hu.hdev, "send command failed");
err = PTR_ERR(skb);
goto out_rel_fw;
}
......@@ -659,6 +665,24 @@ static int download_firmware(struct ll_device *lldev)
return err;
}
static int ll_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
bdaddr_t bdaddr_swapped;
struct sk_buff *skb;
/* HCI_VS_WRITE_BD_ADDR (at least on a CC2560A chip) expects the BD
* address to be MSB first, but bdaddr_t has the convention of being
* LSB first.
*/
baswap(&bdaddr_swapped, bdaddr);
skb = __hci_cmd_sync(hdev, HCI_VS_WRITE_BD_ADDR, sizeof(bdaddr_t),
&bdaddr_swapped, HCI_INIT_TIMEOUT);
if (!IS_ERR(skb))
kfree_skb(skb);
return PTR_ERR_OR_ZERO(skb);
}
static int ll_setup(struct hci_uart *hu)
{
int err, retry = 3;
......@@ -671,14 +695,20 @@ static int ll_setup(struct hci_uart *hu)
lldev = serdev_device_get_drvdata(serdev);
hu->hdev->set_bdaddr = ll_set_bdaddr;
serdev_device_set_flow_control(serdev, true);
do {
/* Configure BT_EN to HIGH state */
/* Reset the Bluetooth device */
gpiod_set_value_cansleep(lldev->enable_gpio, 0);
msleep(5);
gpiod_set_value_cansleep(lldev->enable_gpio, 1);
msleep(100);
err = serdev_device_wait_for_cts(serdev, true, 200);
if (err) {
bt_dev_err(hu->hdev, "Failed to get CTS");
return err;
}
err = download_firmware(lldev);
if (!err)
......@@ -691,6 +721,18 @@ static int ll_setup(struct hci_uart *hu)
if (err)
return err;
/* Set BD address if one was specified at probe */
if (!bacmp(&lldev->bdaddr, BDADDR_NONE)) {
/* This means that there was an error getting the BD address
* during probe, so mark the device as having a bad address.
*/
set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks);
} else if (bacmp(&lldev->bdaddr, BDADDR_ANY)) {
err = ll_set_bdaddr(hu->hdev, &lldev->bdaddr);
if (err)
set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks);
}
/* Operational speed if any */
if (hu->oper_speed)
speed = hu->oper_speed;
......@@ -700,7 +742,12 @@ static int ll_setup(struct hci_uart *hu)
speed = 0;
if (speed) {
struct sk_buff *skb = __hci_cmd_sync(hu->hdev, 0xff36, sizeof(speed), &speed, HCI_INIT_TIMEOUT);
__le32 speed_le = cpu_to_le32(speed);
struct sk_buff *skb;
skb = __hci_cmd_sync(hu->hdev, HCI_VS_UPDATE_UART_HCI_BAUDRATE,
sizeof(speed_le), &speed_le,
HCI_INIT_TIMEOUT);
if (!IS_ERR(skb)) {
kfree_skb(skb);
serdev_device_set_baudrate(serdev, speed);
......@@ -716,6 +763,7 @@ static int hci_ti_probe(struct serdev_device *serdev)
{
struct hci_uart *hu;
struct ll_device *lldev;
struct nvmem_cell *bdaddr_cell;
u32 max_speed = 3000000;
lldev = devm_kzalloc(&serdev->dev, sizeof(struct ll_device), GFP_KERNEL);
......@@ -737,6 +785,52 @@ static int hci_ti_probe(struct serdev_device *serdev)
of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed);
hci_uart_set_speeds(hu, 115200, max_speed);
/* optional BD address from nvram */
bdaddr_cell = nvmem_cell_get(&serdev->dev, "bd-address");
if (IS_ERR(bdaddr_cell)) {
int err = PTR_ERR(bdaddr_cell);
if (err == -EPROBE_DEFER)
return err;
/* ENOENT means there is no matching nvmem cell and ENOSYS
* means that nvmem is not enabled in the kernel configuration.
*/
if (err != -ENOENT && err != -ENOSYS) {
/* If there was some other error, give userspace a
* chance to fix the problem instead of failing to load
* the driver. Using BDADDR_NONE as a flag that is
* tested later in the setup function.
*/
dev_warn(&serdev->dev,
"Failed to get \"bd-address\" nvmem cell (%d)\n",
err);
bacpy(&lldev->bdaddr, BDADDR_NONE);
}
} else {
bdaddr_t *bdaddr;
size_t len;
bdaddr = nvmem_cell_read(bdaddr_cell, &len);
nvmem_cell_put(bdaddr_cell);
if (IS_ERR(bdaddr)) {
dev_err(&serdev->dev, "Failed to read nvmem bd-address\n");
return PTR_ERR(bdaddr);
}
if (len != sizeof(bdaddr_t)) {
dev_err(&serdev->dev, "Invalid nvmem bd-address length\n");
kfree(bdaddr);
return -EINVAL;
}
/* As per the device tree bindings, the value from nvmem is
* expected to be MSB first, but in the kernel it is expected
* that bdaddr_t is LSB first.
*/
baswap(&lldev->bdaddr, bdaddr);
kfree(bdaddr);
}
return hci_uart_register_device(hu, &llp);
}
......@@ -748,6 +842,7 @@ static void hci_ti_remove(struct serdev_device *serdev)
}
static const struct of_device_id hci_ti_of_match[] = {
{ .compatible = "ti,cc2560" },
{ .compatible = "ti,wl1271-st" },
{ .compatible = "ti,wl1273-st" },
{ .compatible = "ti,wl1281-st" },
......
......@@ -932,6 +932,9 @@ static int qca_setup(struct hci_uart *hu)
if (!ret) {
set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
qca_debugfs_init(hdev);
} else if (ret == -ENOENT) {
/* No patch/nvm-config found, run with original fw/config */
ret = 0;
}
/* Setup bdaddr */
......
......@@ -303,6 +303,7 @@ int hci_uart_register_device(struct hci_uart *hu,
hci_set_drvdata(hdev, hu);
INIT_WORK(&hu->write_work, hci_uart_write_work);
percpu_init_rwsem(&hu->proto_lock);
/* Only when vendor specific setup callback is provided, consider
* the manufacturer information valid. This avoids filling in the
......
......@@ -766,43 +766,39 @@ static int __init bt_init(void)
return err;
err = sock_register(&bt_sock_family_ops);
if (err < 0) {
bt_sysfs_cleanup();
return err;
}
if (err)
goto cleanup_sysfs;
BT_INFO("HCI device and connection manager initialized");
err = hci_sock_init();
if (err < 0)
goto error;
if (err)
goto unregister_socket;
err = l2cap_init();
if (err < 0)
goto sock_err;
if (err)
goto cleanup_socket;
err = sco_init();
if (err < 0) {
l2cap_exit();
goto sock_err;
}
if (err)
goto cleanup_cap;
err = mgmt_init();
if (err < 0) {
sco_exit();
l2cap_exit();
goto sock_err;
}
if (err)
goto cleanup_sco;
return 0;
sock_err:
cleanup_sco:
sco_exit();
cleanup_cap:
l2cap_exit();
cleanup_socket:
hci_sock_cleanup();
error:
unregister_socket:
sock_unregister(PF_BLUETOOTH);
cleanup_sysfs:
bt_sysfs_cleanup();
return err;
}
......
......@@ -88,6 +88,9 @@ static int __name ## _show(struct seq_file *f, void *ptr) \
return 0; \
} \
\
DEFINE_SHOW_ATTRIBUTE(__name)
#define DEFINE_SHOW_ATTRIBUTE(__name) \
static int __name ## _open(struct inode *inode, struct file *file) \
{ \
return single_open(file, __name ## _show, inode->i_private); \
......@@ -106,37 +109,16 @@ static int features_show(struct seq_file *f, void *ptr)
u8 p;
hci_dev_lock(hdev);
for (p = 0; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
seq_printf(f, "%2u: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
"0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", p,
hdev->features[p][0], hdev->features[p][1],
hdev->features[p][2], hdev->features[p][3],
hdev->features[p][4], hdev->features[p][5],
hdev->features[p][6], hdev->features[p][7]);
}
for (p = 0; p < HCI_MAX_PAGES && p <= hdev->max_page; p++)
seq_printf(f, "%2u: %8ph\n", p, hdev->features[p]);
if (lmp_le_capable(hdev))
seq_printf(f, "LE: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
"0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
hdev->le_features[0], hdev->le_features[1],
hdev->le_features[2], hdev->le_features[3],
hdev->le_features[4], hdev->le_features[5],
hdev->le_features[6], hdev->le_features[7]);
seq_printf(f, "LE: %8ph\n", hdev->le_features);
hci_dev_unlock(hdev);
return 0;
}
static int features_open(struct inode *inode, struct file *file)
{
return single_open(file, features_show, inode->i_private);
}
static const struct file_operations features_fops = {
.open = features_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(features);
static int device_id_show(struct seq_file *f, void *ptr)
{
......@@ -150,17 +132,7 @@ static int device_id_show(struct seq_file *f, void *ptr)
return 0;
}
static int device_id_open(struct inode *inode, struct file *file)
{
return single_open(file, device_id_show, inode->i_private);
}
static const struct file_operations device_id_fops = {
.open = device_id_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(device_id);
static int device_list_show(struct seq_file *f, void *ptr)
{
......@@ -180,17 +152,7 @@ static int device_list_show(struct seq_file *f, void *ptr)
return 0;
}
static int device_list_open(struct inode *inode, struct file *file)
{
return single_open(file, device_list_show, inode->i_private);
}
static const struct file_operations device_list_fops = {
.open = device_list_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(device_list);
static int blacklist_show(struct seq_file *f, void *p)
{
......@@ -205,17 +167,7 @@ static int blacklist_show(struct seq_file *f, void *p)
return 0;
}
static int blacklist_open(struct inode *inode, struct file *file)
{
return single_open(file, blacklist_show, inode->i_private);
}
static const struct file_operations blacklist_fops = {
.open = blacklist_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(blacklist);
static int uuids_show(struct seq_file *f, void *p)
{
......@@ -240,17 +192,7 @@ static int uuids_show(struct seq_file *f, void *p)
return 0;
}
static int uuids_open(struct inode *inode, struct file *file)
{
return single_open(file, uuids_show, inode->i_private);
}
static const struct file_operations uuids_fops = {
.open = uuids_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(uuids);
static int remote_oob_show(struct seq_file *f, void *ptr)
{
......@@ -269,17 +211,7 @@ static int remote_oob_show(struct seq_file *f, void *ptr)
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,
};
DEFINE_SHOW_ATTRIBUTE(remote_oob);
static int conn_info_min_age_set(void *data, u64 val)
{
......@@ -443,17 +375,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
return 0;
}
static int inquiry_cache_open(struct inode *inode, struct file *file)
{
return single_open(file, inquiry_cache_show, inode->i_private);
}
static const struct file_operations inquiry_cache_fops = {
.open = inquiry_cache_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(inquiry_cache);
static int link_keys_show(struct seq_file *f, void *ptr)
{
......@@ -469,17 +391,7 @@ static int link_keys_show(struct seq_file *f, void *ptr)
return 0;
}
static int link_keys_open(struct inode *inode, struct file *file)
{
return single_open(file, link_keys_show, inode->i_private);
}
static const struct file_operations link_keys_fops = {
.open = link_keys_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(link_keys);
static int dev_class_show(struct seq_file *f, void *ptr)
{
......@@ -493,17 +405,7 @@ static int dev_class_show(struct seq_file *f, void *ptr)
return 0;
}
static int dev_class_open(struct inode *inode, struct file *file)
{
return single_open(file, dev_class_show, inode->i_private);
}
static const struct file_operations dev_class_fops = {
.open = dev_class_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(dev_class);
static int voice_setting_get(void *data, u64 *val)
{
......@@ -692,17 +594,7 @@ static int identity_show(struct seq_file *f, void *p)
return 0;
}
static int identity_open(struct inode *inode, struct file *file)
{
return single_open(file, identity_show, inode->i_private);
}
static const struct file_operations identity_fops = {
.open = identity_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(identity);
static int rpa_timeout_set(void *data, u64 val)
{
......@@ -746,17 +638,7 @@ static int random_address_show(struct seq_file *f, void *p)
return 0;
}
static int random_address_open(struct inode *inode, struct file *file)
{
return single_open(file, random_address_show, inode->i_private);
}
static const struct file_operations random_address_fops = {
.open = random_address_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(random_address);
static int static_address_show(struct seq_file *f, void *p)
{
......@@ -769,17 +651,7 @@ static int static_address_show(struct seq_file *f, void *p)
return 0;
}
static int static_address_open(struct inode *inode, struct file *file)
{
return single_open(file, static_address_show, inode->i_private);
}
static const struct file_operations static_address_fops = {
.open = static_address_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(static_address);
static ssize_t force_static_address_read(struct file *file,
char __user *user_buf,
......@@ -841,17 +713,7 @@ static int white_list_show(struct seq_file *f, void *ptr)
return 0;
}
static int white_list_open(struct inode *inode, struct file *file)
{
return single_open(file, white_list_show, inode->i_private);
}
static const struct file_operations white_list_fops = {
.open = white_list_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(white_list);
static int identity_resolving_keys_show(struct seq_file *f, void *ptr)
{
......@@ -869,18 +731,7 @@ static int identity_resolving_keys_show(struct seq_file *f, void *ptr)
return 0;
}
static int identity_resolving_keys_open(struct inode *inode, struct file *file)
{
return single_open(file, identity_resolving_keys_show,
inode->i_private);
}
static const struct file_operations identity_resolving_keys_fops = {
.open = identity_resolving_keys_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(identity_resolving_keys);
static int long_term_keys_show(struct seq_file *f, void *ptr)
{
......@@ -898,17 +749,7 @@ static int long_term_keys_show(struct seq_file *f, void *ptr)
return 0;
}
static int long_term_keys_open(struct inode *inode, struct file *file)
{
return single_open(file, long_term_keys_show, inode->i_private);
}
static const struct file_operations long_term_keys_fops = {
.open = long_term_keys_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(long_term_keys);
static int conn_min_interval_set(void *data, u64 val)
{
......
......@@ -919,6 +919,43 @@ static bool adv_use_rpa(struct hci_dev *hdev, uint32_t flags)
return true;
}
static bool is_advertising_allowed(struct hci_dev *hdev, bool connectable)
{
/* If there is no connection we are OK to advertise. */
if (hci_conn_num(hdev, LE_LINK) == 0)
return true;
/* Check le_states if there is any connection in slave role. */
if (hdev->conn_hash.le_num_slave > 0) {
/* Slave connection state and non connectable mode bit 20. */
if (!connectable && !(hdev->le_states[2] & 0x10))
return false;
/* Slave connection state and connectable mode bit 38
* and scannable bit 21.
*/
if (connectable && (!(hdev->le_states[4] & 0x01) ||
!(hdev->le_states[2] & 0x40)))
return false;
}
/* Check le_states if there is any connection in master role. */
if (hci_conn_num(hdev, LE_LINK) != hdev->conn_hash.le_num_slave) {
/* Master connection state and non connectable mode bit 18. */
if (!connectable && !(hdev->le_states[2] & 0x02))
return false;
/* Master connection state and connectable mode bit 35 and
* scannable 19.
*/
if (connectable && (!(hdev->le_states[4] & 0x10) ||
!(hdev->le_states[2] & 0x08)))
return false;
}
return true;
}
void __hci_req_enable_advertising(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
......@@ -927,7 +964,15 @@ void __hci_req_enable_advertising(struct hci_request *req)
bool connectable;
u32 flags;
if (hci_conn_num(hdev, LE_LINK) > 0)
flags = get_adv_instance_flags(hdev, hdev->cur_adv_instance);
/* If the "connectable" instance flag was not set, then choose between
* ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
*/
connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
mgmt_get_connectable(hdev);
if (!is_advertising_allowed(hdev, connectable))
return;
if (hci_dev_test_flag(hdev, HCI_LE_ADV))
......@@ -940,14 +985,6 @@ void __hci_req_enable_advertising(struct hci_request *req)
*/
hci_dev_clear_flag(hdev, HCI_LE_ADV);
flags = get_adv_instance_flags(hdev, hdev->cur_adv_instance);
/* If the "connectable" instance flag was not set, then choose between
* ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
*/
connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
mgmt_get_connectable(hdev);
/* Set require_privacy to true only when non-connectable
* advertising is used. In that case it is fine to use a
* non-resolvable private address.
......@@ -1985,13 +2022,6 @@ static void le_scan_restart_work(struct work_struct *work)
hci_dev_unlock(hdev);
}
static void disable_advertising(struct hci_request *req)
{
u8 enable = 0x00;
hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
}
static int active_scan(struct hci_request *req, unsigned long opt)
{
uint16_t interval = opt;
......@@ -2017,7 +2047,7 @@ static int active_scan(struct hci_request *req, unsigned long opt)
cancel_adv_timeout(hdev);
hci_dev_unlock(hdev);
disable_advertising(req);
__hci_req_disable_advertising(req);
}
/* If controller is scanning, it means the background scanning is
......
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