diff options
| author | David S. Miller <davem@davemloft.net> | 2015-03-19 15:18:04 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-03-19 15:18:04 -0400 |
| commit | 970282d0e1404b23f9d7ec6a676fa76ff15b3376 (patch) | |
| tree | 15b7398383f5158cd19ba5fcbf17d46509e80a86 | |
| parent | c9bdc0dde187e5f6b481989b4084c1b7cbe2726f (diff) | |
| parent | ea6edfbcefec1fcfdb826a1d5a054f402dfbfb24 (diff) | |
| download | linux-970282d0e1404b23f9d7ec6a676fa76ff15b3376.tar.gz linux-970282d0e1404b23f9d7ec6a676fa76ff15b3376.tar.bz2 linux-970282d0e1404b23f9d7ec6a676fa76ff15b3376.zip | |
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-03-19
This wont the last 4.1 bluetooth-next pull request, but we've piled up
enough patches in less than a week that I wanted to save you from a
single huge "last-minute" pull somewhere closer to the merge window.
The main changes are:
- Simultaneous LE & BR/EDR discovery support for HW that can do it
- Complete LE OOB pairing support
- More fine-grained mgmt-command access control (normal user can now do
harmless read-only operations).
- Added RF power amplifier support in cc2520 ieee802154 driver
- Some cleanups/fixes in ieee802154 code
Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | Documentation/devicetree/bindings/net/ieee802154/cc2520.txt | 4 | ||||
| -rw-r--r-- | drivers/bluetooth/btusb.c | 8 | ||||
| -rw-r--r-- | drivers/net/ieee802154/at86rf230.c | 2 | ||||
| -rw-r--r-- | drivers/net/ieee802154/cc2520.c | 150 | ||||
| -rw-r--r-- | include/linux/spi/cc2520.h | 1 | ||||
| -rw-r--r-- | include/net/bluetooth/bluetooth.h | 5 | ||||
| -rw-r--r-- | include/net/bluetooth/hci.h | 22 | ||||
| -rw-r--r-- | include/net/bluetooth/hci_core.h | 14 | ||||
| -rw-r--r-- | include/net/bluetooth/mgmt.h | 50 | ||||
| -rw-r--r-- | net/bluetooth/Makefile | 2 | ||||
| -rw-r--r-- | net/bluetooth/hci_core.c | 24 | ||||
| -rw-r--r-- | net/bluetooth/hci_debugfs.c | 2 | ||||
| -rw-r--r-- | net/bluetooth/hci_event.c | 78 | ||||
| -rw-r--r-- | net/bluetooth/hci_sock.c | 180 | ||||
| -rw-r--r-- | net/bluetooth/mgmt.c | 1037 | ||||
| -rw-r--r-- | net/bluetooth/mgmt_util.c | 210 | ||||
| -rw-r--r-- | net/bluetooth/mgmt_util.h | 53 | ||||
| -rw-r--r-- | net/bluetooth/smp.c | 278 | ||||
| -rw-r--r-- | net/bluetooth/smp.h | 1 | ||||
| -rw-r--r-- | net/mac802154/driver-ops.h | 4 |
20 files changed, 1485 insertions, 640 deletions
diff --git a/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt b/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt index 0071883c08d8..fb6d49f184ed 100644 --- a/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt +++ b/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt @@ -13,11 +13,15 @@ Required properties: - cca-gpio: GPIO spec for the CCA pin - vreg-gpio: GPIO spec for the VREG pin - reset-gpio: GPIO spec for the RESET pin +Optional properties: + - amplified: include if the CC2520 is connected to a CC2591 amplifier + Example: cc2520@0 { compatible = "ti,cc2520"; reg = <0>; spi-max-frequency = <4000000>; + amplified; pinctrl-names = "default"; pinctrl-0 = <&cc2520_cape_pins>; fifo-gpio = <&gpio1 18 0>; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 6fa9338745cf..708b6574d805 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -215,8 +215,8 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, /* QCA ROME chipset */ - { USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME}, - { USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME}, + { USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME }, + { USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME }, /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 }, @@ -3019,6 +3019,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->shutdown = btusb_shutdown_intel; hdev->set_bdaddr = btusb_set_bdaddr_intel; set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); } if (id->driver_info & BTUSB_INTEL_NEW) { @@ -3042,6 +3043,7 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_ATH3012) { hdev->set_bdaddr = btusb_set_bdaddr_ath3012; + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); } @@ -3085,6 +3087,8 @@ static int btusb_probe(struct usb_interface *intf, /* Fake CSR devices with broken commands */ if (bcdDevice <= 0x100) hdev->setup = btusb_setup_csr; + + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); } if (id->driver_info & BTUSB_SNIFFER) { diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index b64c5c7b2a50..cc5efa149da1 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -325,7 +325,7 @@ at86rf230_read_subreg(struct at86rf230_local *lp, int rc; rc = __at86rf230_read(lp, addr, data); - if (rc > 0) + if (!rc) *data = (*data & mask) >> shift; return rc; diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c index 181b349b060e..f833b8bb6663 100644 --- a/drivers/net/ieee802154/cc2520.c +++ b/drivers/net/ieee802154/cc2520.c @@ -714,11 +714,45 @@ static irqreturn_t cc2520_sfd_isr(int irq, void *data) return IRQ_HANDLED; } +static int cc2520_get_platform_data(struct spi_device *spi, + struct cc2520_platform_data *pdata) +{ + struct device_node *np = spi->dev.of_node; + struct cc2520_private *priv = spi_get_drvdata(spi); + + if (!np) { + struct cc2520_platform_data *spi_pdata = spi->dev.platform_data; + if (!spi_pdata) + return -ENOENT; + *pdata = *spi_pdata; + return 0; + } + + pdata->fifo = of_get_named_gpio(np, "fifo-gpio", 0); + priv->fifo_pin = pdata->fifo; + + pdata->fifop = of_get_named_gpio(np, "fifop-gpio", 0); + + pdata->sfd = of_get_named_gpio(np, "sfd-gpio", 0); + pdata->cca = of_get_named_gpio(np, "cca-gpio", 0); + pdata->vreg = of_get_named_gpio(np, "vreg-gpio", 0); + pdata->reset = of_get_named_gpio(np, "reset-gpio", 0); + + pdata->amplified = of_property_read_bool(np, "amplified"); + + return 0; +} + static int cc2520_hw_init(struct cc2520_private *priv) { u8 status = 0, state = 0xff; int ret; int timeout = 100; + struct cc2520_platform_data pdata; + + ret = cc2520_get_platform_data(priv->spi, &pdata); + if (ret) + goto err_ret; ret = cc2520_read_register(priv, CC2520_FSMSTAT1, &state); if (ret) @@ -741,11 +775,47 @@ static int cc2520_hw_init(struct cc2520_private *priv) dev_vdbg(&priv->spi->dev, "oscillator brought up\n"); - /* Registers default value: section 28.1 in Datasheet */ - ret = cc2520_write_register(priv, CC2520_TXPOWER, 0xF7); - if (ret) - goto err_ret; + /* If the CC2520 is connected to a CC2591 amplifier, we must both + * configure GPIOs on the CC2520 to correctly configure the CC2591 + * and change a couple settings of the CC2520 to work with the + * amplifier. See section 8 page 17 of TI application note AN065. + * http://www.ti.com/lit/an/swra229a/swra229a.pdf + */ + if (pdata.amplified) { + ret = cc2520_write_register(priv, CC2520_TXPOWER, 0xF9); + if (ret) + goto err_ret; + + ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x16); + if (ret) + goto err_ret; + + ret = cc2520_write_register(priv, CC2520_GPIOCTRL0, 0x46); + if (ret) + goto err_ret; + + ret = cc2520_write_register(priv, CC2520_GPIOCTRL5, 0x47); + if (ret) + goto err_ret; + + ret = cc2520_write_register(priv, CC2520_GPIOPOLARITY, 0x1e); + if (ret) + goto err_ret; + + ret = cc2520_write_register(priv, CC2520_TXCTRL, 0xc1); + if (ret) + goto err_ret; + } else { + ret = cc2520_write_register(priv, CC2520_TXPOWER, 0xF7); + if (ret) + goto err_ret; + ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x11); + if (ret) + goto err_ret; + } + + /* Registers default value: section 28.1 in Datasheet */ ret = cc2520_write_register(priv, CC2520_CCACTRL0, 0x1A); if (ret) goto err_ret; @@ -770,10 +840,6 @@ static int cc2520_hw_init(struct cc2520_private *priv) if (ret) goto err_ret; - ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x11); - if (ret) - goto err_ret; - ret = cc2520_write_register(priv, CC2520_ADCTEST0, 0x10); if (ret) goto err_ret; @@ -808,40 +874,10 @@ err_ret: return ret; } -static struct cc2520_platform_data * -cc2520_get_platform_data(struct spi_device *spi) -{ - struct cc2520_platform_data *pdata; - struct device_node *np = spi->dev.of_node; - struct cc2520_private *priv = spi_get_drvdata(spi); - - if (!np) - return spi->dev.platform_data; - - pdata = devm_kzalloc(&spi->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - goto done; - - pdata->fifo = of_get_named_gpio(np, "fifo-gpio", 0); - priv->fifo_pin = pdata->fifo; - - pdata->fifop = of_get_named_gpio(np, "fifop-gpio", 0); - - pdata->sfd = of_get_named_gpio(np, "sfd-gpio", 0); - pdata->cca = of_get_named_gpio(np, "cca-gpio", 0); - pdata->vreg = of_get_named_gpio(np, "vreg-gpio", 0); - pdata->reset = of_get_named_gpio(np, "reset-gpio", 0); - - spi->dev.platform_data = pdata; - -done: - return pdata; -} - static int cc2520_probe(struct spi_device *spi) { struct cc2520_private *priv; - struct cc2520_platform_data *pdata; + struct cc2520_platform_data pdata; int ret; priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); @@ -850,8 +886,8 @@ static int cc2520_probe(struct spi_device *spi) spi_set_drvdata(spi, priv); - pdata = cc2520_get_platform_data(spi); - if (!pdata) { + ret = cc2520_get_platform_data(spi, &pdata); + if (ret < 0) { dev_err(&spi->dev, "no platform data\n"); return -EINVAL; } @@ -869,76 +905,76 @@ static int cc2520_probe(struct spi_device *spi) init_completion(&priv->tx_complete); /* Request all the gpio's */ - if (!gpio_is_valid(pdata->fifo)) { + if (!gpio_is_valid(pdata.fifo)) { dev_err(&spi->dev, "fifo gpio is not valid\n"); ret = -EINVAL; goto err_hw_init; } - ret = devm_gpio_request_one(&spi->dev, pdata->fifo, + ret = devm_gpio_request_one(&spi->dev, pdata.fifo, GPIOF_IN, "fifo"); if (ret) goto err_hw_init; - if (!gpio_is_valid(pdata->cca)) { + if (!gpio_is_valid(pdata.cca)) { dev_err(&spi->dev, "cca gpio is not valid\n"); ret = -EINVAL; goto err_hw_init; } - ret = devm_gpio_request_one(&spi->dev, pdata->cca, + ret = devm_gpio_request_one(&spi->dev, pdata.cca, GPIOF_IN, "cca"); if (ret) goto err_hw_init; - if (!gpio_is_valid(pdata->fifop)) { + if (!gpio_is_valid(pdata.fifop)) { dev_err(&spi->dev, "fifop gpio is not valid\n"); ret = -EINVAL; goto err_hw_init; } - ret = devm_gpio_request_one(&spi->dev, pdata->fifop, + ret = devm_gpio_request_one(&spi->dev, pdata.fifop, GPIOF_IN, "fifop"); if (ret) goto err_hw_init; - if (!gpio_is_valid(pdata->sfd)) { + if (!gpio_is_valid(pdata.sfd)) { dev_err(&spi->dev, "sfd gpio is not valid\n"); ret = -EINVAL; goto err_hw_init; } - ret = devm_gpio_request_one(&spi->dev, pdata->sfd, + ret = devm_gpio_request_one(&spi->dev, pdata.sfd, GPIOF_IN, "sfd"); if (ret) goto err_hw_init; - if (!gpio_is_valid(pdata->reset)) { + if (!gpio_is_valid(pdata.reset)) { dev_err(&spi->dev, "reset gpio is not valid\n"); ret = -EINVAL; goto err_hw_init; } - ret = devm_gpio_request_one(&spi->dev, pdata->reset, + ret = devm_gpio_request_one(&spi->dev, pdata.reset, GPIOF_OUT_INIT_LOW, "reset"); if (ret) goto err_hw_init; - if (!gpio_is_valid(pdata->vreg)) { + if (!gpio_is_valid(pdata.vreg)) { dev_err(&spi->dev, "vreg gpio is not valid\n"); ret = -EINVAL; goto err_hw_init; } - ret = devm_gpio_request_one(&spi->dev, pdata->vreg, + ret = devm_gpio_request_one(&spi->dev, pdata.vreg, GPIOF_OUT_INIT_LOW, "vreg"); if (ret) goto err_hw_init; - gpio_set_value(pdata->vreg, HIGH); + gpio_set_value(pdata.vreg, HIGH); usleep_range(100, 150); - gpio_set_value(pdata->reset, HIGH); + gpio_set_value(pdata.reset, HIGH); usleep_range(200, 250); ret = cc2520_hw_init(priv); @@ -947,7 +983,7 @@ static int cc2520_probe(struct spi_device *spi) /* Set up fifop interrupt */ ret = devm_request_irq(&spi->dev, - gpio_to_irq(pdata->fifop), + gpio_to_irq(pdata.fifop), cc2520_fifop_isr, IRQF_TRIGGER_RISING, dev_name(&spi->dev), @@ -959,7 +995,7 @@ static int cc2520_probe(struct spi_device *spi) /* Set up sfd interrupt */ ret = devm_request_irq(&spi->dev, - gpio_to_irq(pdata->sfd), + gpio_to_irq(pdata.sfd), cc2520_sfd_isr, IRQF_TRIGGER_FALLING, dev_name(&spi->dev), diff --git a/include/linux/spi/cc2520.h b/include/linux/spi/cc2520.h index 85b8ee67e937..e741e8baad92 100644 --- a/include/linux/spi/cc2520.h +++ b/include/linux/spi/cc2520.h @@ -21,6 +21,7 @@ struct cc2520_platform_data { int sfd; int reset; int vreg; + bool amplified; }; #endif diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index e598ca096ec9..33a5e00025aa 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -335,6 +335,11 @@ out: int bt_to_errno(__u16 code); +void hci_sock_set_flag(struct sock *sk, int nr); +void hci_sock_clear_flag(struct sock *sk, int nr); +int hci_sock_test_flag(struct sock *sk, int nr); +unsigned short hci_sock_get_channel(struct sock *sk); + int hci_sock_init(void); void hci_sock_cleanup(void); diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index d942fedbaedd..06e7eee31ce4 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -160,6 +160,14 @@ enum { * during the hdev->setup vendor callback. */ HCI_QUIRK_STRICT_DUPLICATE_FILTER, + + /* When this quirk is set, LE scan and BR/EDR inquiry is done + * simultaneously, otherwise it's interleaved. + * + * This quirk can be set before hci_register_dev is called or + * during the hdev->setup vendor callback. + */ + HCI_QUIRK_SIMULTANEOUS_DISCOVERY, }; /* HCI device flags */ @@ -179,6 +187,16 @@ enum { HCI_RESET, }; +/* HCI socket flags */ +enum { + HCI_SOCK_TRUSTED, + HCI_MGMT_INDEX_EVENTS, + HCI_MGMT_UNCONF_INDEX_EVENTS, + HCI_MGMT_EXT_INDEX_EVENTS, + HCI_MGMT_GENERIC_EVENTS, + HCI_MGMT_OOB_DATA_EVENTS, +}; + /* * BR/EDR and/or LE controller flags: the flags defined here should represent * states from the controller. @@ -447,6 +465,10 @@ enum { #define EIR_SSP_HASH_C 0x0E /* Simple Pairing Hash C */ #define EIR_SSP_RAND_R 0x0F /* Simple Pairing Randomizer R */ #define EIR_DEVICE_ID 0x10 /* device ID */ +#define EIR_LE_BDADDR 0x1B /* LE Bluetooth device address */ +#define EIR_LE_ROLE 0x1C /* LE role */ +#define EIR_LE_SC_CONFIRM 0x22 /* LE SC Confirmation Value */ +#define EIR_LE_SC_RANDOM 0x23 /* LE SC Random Value */ /* Low Energy Advertising Flags */ #define LE_AD_LIMITED 0x01 /* Limited Discoverable */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 6afbf5b014a1..b65c53de6a69 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -596,7 +596,6 @@ enum { HCI_CONN_SC_ENABLED, HCI_CONN_AES_CCM, HCI_CONN_POWER_SAVE, - HCI_CONN_REMOTE_OOB, HCI_CONN_FLUSH_KEY, HCI_CONN_ENCRYPT, HCI_CONN_AUTH, @@ -1284,14 +1283,15 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); /* ----- HCI Sockets ----- */ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, - struct sock *skip_sk); + int flag, struct sock *skip_sk); void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb); void hci_sock_dev_event(struct hci_dev *hdev, int event); -#define HCI_MGMT_VAR_LEN (1 << 0) -#define HCI_MGMT_NO_HDEV (1 << 1) -#define HCI_MGMT_UNCONFIGURED (1 << 2) +#define HCI_MGMT_VAR_LEN BIT(0) +#define HCI_MGMT_NO_HDEV BIT(1) +#define HCI_MGMT_UNTRUSTED BIT(2) +#define HCI_MGMT_UNCONFIGURED BIT(3) struct hci_mgmt_handler { int (*func) (struct sock *sk, struct hci_dev *hdev, void *data, @@ -1305,6 +1305,7 @@ struct hci_mgmt_chan { unsigned short channel; size_t handler_count; const struct hci_mgmt_handler *handlers; + void (*hdev_init) (struct sock *sk, struct hci_dev *hdev); }; int hci_mgmt_chan_register(struct hci_mgmt_chan *c); @@ -1329,9 +1330,6 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c); #define DISCOV_BREDR_INQUIRY_LEN 0x08 #define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ -int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk, - struct msghdr *msg, size_t msglen); - int mgmt_new_settings(struct hci_dev *hdev); void mgmt_index_added(struct hci_dev *hdev); void mgmt_index_removed(struct hci_dev *hdev); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 5bf6af9cee78..a1a68671bf88 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -44,6 +44,7 @@ #define MGMT_STATUS_INVALID_INDEX 0x11 #define MGMT_STATUS_RFKILLED 0x12 #define MGMT_STATUS_ALREADY_PAIRED 0x13 +#define MGMT_STATUS_PERMISSION_DENIED 0x14 struct mgmt_hdr { __le16 opcode; @@ -505,6 +506,39 @@ struct mgmt_cp_start_service_discovery { } __packed; #define MGMT_START_SERVICE_DISCOVERY_SIZE 4 +#define MGMT_OP_READ_LOCAL_OOB_EXT_DATA 0x003B +struct mgmt_cp_read_local_oob_ext_data { + __u8 type; +} __packed; +#define MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE 1 +struct mgmt_rp_read_local_oob_ext_data { + __u8 type; + __le16 eir_len; + __u8 eir[0]; +} __packed; + +#define MGMT_OP_READ_EXT_INDEX_LIST 0x003C +#define MGMT_READ_EXT_INDEX_LIST_SIZE 0 +struct mgmt_rp_read_ext_index_list { + __le16 num_controllers; + struct { + __le16 index; + __u8 type; + __u8 bus; + } entry[0]; +} __packed; + +#define MGMT_OP_READ_ADV_FEATURES 0x0003D +#define MGMT_READ_ADV_FEATURES_SIZE 0 +struct mgmt_rp_read_adv_features { + __le32 supported_flags; + __u8 max_adv_data_len; + __u8 max_scan_rsp_len; + __u8 max_instances; + __u8 num_instances; + __u8 instance[0]; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -692,3 +726,19 @@ struct mgmt_ev_new_conn_param { #define MGMT_EV_UNCONF_INDEX_REMOVED 0x001e #define MGMT_EV_NEW_CONFIG_OPTIONS 0x001f + +struct mgmt_ev_ext_index { + __u8 type; + __u8 bus; +} __packed; + +#define MGMT_EV_EXT_INDEX_ADDED 0x0020 + +#define MGMT_EV_EXT_INDEX_REMOVED 0x0021 + +#define MGMT_EV_LOCAL_OOB_DATA_UPDATED 0x0022 +struct mgmt_ev_local_oob_data_updated { + __u8 type; + __le16 eir_len; + __u8 eir[0]; +} __packed; diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index 5d608799717e..9a8ea232d28f 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile @@ -13,7 +13,7 @@ bluetooth_6lowpan-y := 6lowpan.o bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ - a2mp.o amp.o ecc.o hci_request.o + a2mp.o amp.o ecc.o hci_request.o mgmt_util.o bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 750d3445f2d2..773f2164d9a1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2902,12 +2902,26 @@ static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status, hci_dev_lock(hdev); - hci_inquiry_cache_flush(hdev); + if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, + &hdev->quirks)) { + /* If we were running LE only scan, change discovery + * state. If we were running both LE and BR/EDR inquiry + * simultaneously, and BR/EDR inquiry is already + * finished, stop discovery, otherwise BR/EDR inquiry + * will stop discovery when finished. + */ + if (!test_bit(HCI_INQUIRY, &hdev->flags)) + hci_discovery_set_state(hdev, + DISCOVERY_STOPPED); + } else { + hci_inquiry_cache_flush(hdev); - err = hci_req_run(&req, inquiry_complete); - if (err) { - BT_ERR("Inquiry request failed: err %d", err); - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + err = hci_req_run(&req, inquiry_complete); + if (err) { + BT_ERR("Inquiry request failed: err %d", err); + hci_discovery_set_state(hdev, + DISCOVERY_STOPPED); + } } hci_dev_unlock(hdev); diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index bc801e9db834..0818fabf346a 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c @@ -166,7 +166,7 @@ static int remote_oob_show(struct seq_file *f, void *ptr) 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); + 16, data->hash256, 16, data->rand256); } hci_dev_unlock(hdev); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index c7376cd42b1c..62f92a508961 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2126,7 +2126,16 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) goto unlock; if (list_empty(&discov->resolve)) { - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + /* When BR/EDR inquiry is active and no LE scanning is in + * progress, then change discovery state to indicate completion. + * + * When running LE scanning and BR/EDR inquiry simultaneously + * and the LE scan already finished, then change the discovery + * state to indicate completion. + */ + if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || + !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) + hci_discovery_set_state(hdev, DISCOVERY_STOPPED); goto unlock; } @@ -2135,7 +2144,16 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) e->name_state = NAME_PENDING; hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); } else { - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + /* When BR/EDR inquiry is active and no LE scanning is in + * progress, then change discovery state to indicate completion. + * + * When running LE scanning and BR/EDR inquiry simultaneously + * and the LE scan already finished, then change the discovery + * state to indicate completion. + */ + if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || + !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) + hci_discovery_set_state(hdev, DISCOVERY_STOPPED); } unlock: @@ -3889,41 +3907,37 @@ static u8 bredr_oob_data_present(struct hci_conn *conn) 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 (!hci_dev_test_flag(hdev, HCI_SC_ONLY)) - 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; - } + 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 (!hci_dev_test_flag(hdev, HCI_SC_ONLY)) + return data->present; - /* When Secure Connections is not enabled or actually - * not supported by the hardware, then check that if - * P-192 data values are 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->rand192, ZERO_KEY, 16) || - !memcmp(data->hash192, ZERO_KEY, 16)) + if (!memcmp(data->rand256, ZERO_KEY, 16) || + !memcmp(data->hash256, ZERO_KEY, 16)) return 0x00; - return 0x01; + return 0x02; } - return 0x00; + /* 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; } static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) @@ -4010,8 +4024,6 @@ static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) conn->remote_cap = ev->capability; conn->remote_auth = ev->authentication; - if (ev->oob_data) - set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); unlock: hci_dev_unlock(hdev); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index b614543b4fe3..85a44a7dc150 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -30,6 +30,9 @@ #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_mon.h> +#include <net/bluetooth/mgmt.h> + +#include "mgmt_util.h" static LIST_HEAD(mgmt_chan_list); static DEFINE_MUTEX(mgmt_chan_list_lock); @@ -47,8 +50,29 @@ struct hci_pinfo { struct hci_filter filter; __u32 cmsg_mask; unsigned short channel; + unsigned long flags; }; +void hci_sock_set_flag(struct sock *sk, int nr) +{ + set_bit(nr, &hci_pi(sk)->flags); +} + +void hci_sock_clear_flag(struct sock *sk, int nr) +{ + clear_bit(nr, &hci_pi(sk)->flags); +} + +int hci_sock_test_flag(struct sock *sk, int nr) +{ + return test_bit(nr, &hci_pi(sk)->flags); +} + +unsigned short hci_sock_get_channel(struct sock *sk) +{ + return hci_pi(sk)->channel; +} + static inline int hci_test_bit(int nr, const void *addr) { return *((const __u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); @@ -188,7 +212,7 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) /* Send frame to sockets with specific channel */ void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, - struct sock *skip_sk) + int flag, struct sock *skip_sk) { struct sock *sk; @@ -199,6 +223,10 @@ void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, sk_for_each(sk, &hci_sk_list.head) { struct sk_buff *nskb; + /* Ignore socket without the flag set */ + if (!hci_sock_test_flag(sk, flag)) + continue; + /* Skip the original socket */ if (sk == skip_sk) continue; @@ -266,7 +294,8 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) hdr->index = cpu_to_le16(hdev->id); hdr->len = cpu_to_le16(skb->len); - hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy, NULL); + hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy, + HCI_SOCK_TRUSTED, NULL); kfree_skb(skb_copy); } @@ -373,7 +402,8 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event) skb = create_monitor_event(hdev, event); if (skb) { - hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, NULL); + hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, + HCI_SOCK_TRUSTED, NULL); kfree_skb(skb); } } @@ -752,6 +782,11 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, goto done; } + /* The monitor interface is restricted to CAP_NET_RAW + * capabilities and with that implicitly trusted. + */ + hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); + send_monitor_replay(sk); atomic_inc(&monitor_promisc); @@ -768,11 +803,29 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, goto done; } - if (!capable(CAP_NET_ADMIN)) { - err = -EPERM; - goto done; + /* Users with CAP_NET_ADMIN capabilities are allowed + * access to all management commands and events. For + * untrusted users the interface is restricted and + * also only untrusted events are sent. + */ + if (capable(CAP_NET_ADMIN)) + hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); + + /* At the moment the index and unconfigured index events + * are enabled unconditionally. Setting them on each + * socket when binding keeps this functionality. They + * however might be cleared later and then sending of these + * events will be disabled, but that is then intentional. + * + * This also enables generic events that are safe to be + * received by untrusted users. Example for such events + * are changes to settings, class of device, name etc. + */ + if (haddr.hci_channel == HCI_CHANNEL_CONTROL) { + hci_sock_set_flag(sk, HCI_MGMT_INDEX_EVENTS); + hci_sock_set_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS); + hci_sock_set_flag(sk, HCI_MGMT_GENERIC_EVENTS); } - break; } @@ -901,6 +954,117 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, return err ? : copied; } +static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk, |
