You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== pull request: bluetooth-next 2016-09-19 Here's the main bluetooth-next pull request for the 4.9 kernel. - Added new messages for monitor sockets for better mgmt tracing - Added local name and appearance support in scan response - Added new Qualcomm WCNSS SMD based HCI driver - Minor fixes & cleanup to 802.15.4 code - New USB ID to btusb driver - Added Marvell support to HCI UART driver - Add combined LED trigger for controller power - Other minor fixes here and there 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:
@@ -180,6 +180,17 @@ config BT_HCIUART_AG6XX
|
||||
|
||||
Say Y here to compile support for Intel AG6XX protocol.
|
||||
|
||||
config BT_HCIUART_MRVL
|
||||
bool "Marvell protocol support"
|
||||
depends on BT_HCIUART
|
||||
select BT_HCIUART_H4
|
||||
help
|
||||
Marvell is serial protocol for communication between Bluetooth
|
||||
device and host. This protocol is required for most Marvell Bluetooth
|
||||
devices with UART interface.
|
||||
|
||||
Say Y here to compile support for HCI MRVL protocol.
|
||||
|
||||
config BT_HCIBCM203X
|
||||
tristate "HCI BCM203x USB driver"
|
||||
depends on USB
|
||||
@@ -331,4 +342,16 @@ config BT_WILINK
|
||||
Say Y here to compile support for Texas Instrument's WiLink7 driver
|
||||
into the kernel or say M to compile it as module (btwilink).
|
||||
|
||||
config BT_QCOMSMD
|
||||
tristate "Qualcomm SMD based HCI support"
|
||||
depends on QCOM_SMD && QCOM_WCNSS_CTRL
|
||||
select BT_QCA
|
||||
help
|
||||
Qualcomm SMD based HCI driver.
|
||||
This driver is used to bridge HCI data onto the shared memory
|
||||
channels to the WCNSS core.
|
||||
|
||||
Say Y here to compile support for HCI over Qualcomm SMD into the
|
||||
kernel or say M to compile as a module.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -20,6 +20,7 @@ obj-$(CONFIG_BT_ATH3K) += ath3k.o
|
||||
obj-$(CONFIG_BT_MRVL) += btmrvl.o
|
||||
obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o
|
||||
obj-$(CONFIG_BT_WILINK) += btwilink.o
|
||||
obj-$(CONFIG_BT_QCOMSMD) += btqcomsmd.o
|
||||
obj-$(CONFIG_BT_BCM) += btbcm.o
|
||||
obj-$(CONFIG_BT_RTL) += btrtl.o
|
||||
obj-$(CONFIG_BT_QCA) += btqca.o
|
||||
@@ -37,6 +38,7 @@ hci_uart-$(CONFIG_BT_HCIUART_INTEL) += hci_intel.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_BCM) += hci_bcm.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_QCA) += hci_qca.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_AG6XX) += hci_ag6xx.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_MRVL) += hci_mrvl.o
|
||||
hci_uart-objs := $(hci_uart-y)
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
||||
@@ -185,10 +185,8 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
data->state = BCM203X_LOAD_MINIDRV;
|
||||
|
||||
data->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!data->urb) {
|
||||
BT_ERR("Can't allocate URB");
|
||||
if (!data->urb)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
|
||||
BT_ERR("Mini driver request failed");
|
||||
|
||||
@@ -55,8 +55,8 @@ static int rome_patch_ver_req(struct hci_dev *hdev, u32 *rome_version)
|
||||
}
|
||||
|
||||
edl = (struct edl_event_hdr *)(skb->data);
|
||||
if (!edl || !edl->data) {
|
||||
BT_ERR("%s: TLV with no header or no data", hdev->name);
|
||||
if (!edl) {
|
||||
BT_ERR("%s: TLV with no header", hdev->name);
|
||||
err = -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
@@ -224,8 +224,8 @@ static int rome_tlv_send_segment(struct hci_dev *hdev, int idx, int seg_size,
|
||||
}
|
||||
|
||||
edl = (struct edl_event_hdr *)(skb->data);
|
||||
if (!edl || !edl->data) {
|
||||
BT_ERR("%s: TLV with no header or no data", hdev->name);
|
||||
if (!edl) {
|
||||
BT_ERR("%s: TLV with no header", hdev->name);
|
||||
err = -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Linaro Ltd.
|
||||
* Copyright (c) 2015, Sony Mobile Communications Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/smd.h>
|
||||
#include <linux/soc/qcom/wcnss_ctrl.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#include "btqca.h"
|
||||
|
||||
struct btqcomsmd {
|
||||
struct hci_dev *hdev;
|
||||
|
||||
struct qcom_smd_channel *acl_channel;
|
||||
struct qcom_smd_channel *cmd_channel;
|
||||
};
|
||||
|
||||
static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
|
||||
const void *data, size_t count)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* Use GFP_ATOMIC as we're in IRQ context */
|
||||
skb = bt_skb_alloc(count, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
hdev->stat.err_rx++;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hci_skb_pkt_type(skb) = type;
|
||||
memcpy(skb_put(skb, count), data, count);
|
||||
|
||||
return hci_recv_frame(hdev, skb);
|
||||
}
|
||||
|
||||
static int btqcomsmd_acl_callback(struct qcom_smd_channel *channel,
|
||||
const void *data, size_t count)
|
||||
{
|
||||
struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
|
||||
|
||||
btq->hdev->stat.byte_rx += count;
|
||||
return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
|
||||
}
|
||||
|
||||
static int btqcomsmd_cmd_callback(struct qcom_smd_channel *channel,
|
||||
const void *data, size_t count)
|
||||
{
|
||||
struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
|
||||
|
||||
return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
|
||||
}
|
||||
|
||||
static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct btqcomsmd *btq = hci_get_drvdata(hdev);
|
||||
int ret;
|
||||
|
||||
switch (hci_skb_pkt_type(skb)) {
|
||||
case HCI_ACLDATA_PKT:
|
||||
ret = qcom_smd_send(btq->acl_channel, skb->data, skb->len);
|
||||
hdev->stat.acl_tx++;
|
||||
hdev->stat.byte_tx += skb->len;
|
||||
break;
|
||||
case HCI_COMMAND_PKT:
|
||||
ret = qcom_smd_send(btq->cmd_channel, skb->data, skb->len);
|
||||
hdev->stat.cmd_tx++;
|
||||
break;
|
||||
default:
|
||||
ret = -EILSEQ;
|
||||
break;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btqcomsmd_open(struct hci_dev *hdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btqcomsmd_close(struct hci_dev *hdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btqcomsmd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct btqcomsmd *btq;
|
||||
struct hci_dev *hdev;
|
||||
void *wcnss;
|
||||
int ret;
|
||||
|
||||
btq = devm_kzalloc(&pdev->dev, sizeof(*btq), GFP_KERNEL);
|
||||
if (!btq)
|
||||
return -ENOMEM;
|
||||
|
||||
wcnss = dev_get_drvdata(pdev->dev.parent);
|
||||
|
||||
btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
|
||||
btqcomsmd_acl_callback);
|
||||
if (IS_ERR(btq->acl_channel))
|
||||
return PTR_ERR(btq->acl_channel);
|
||||
|
||||
btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
|
||||
btqcomsmd_cmd_callback);
|
||||
if (IS_ERR(btq->cmd_channel))
|
||||
return PTR_ERR(btq->cmd_channel);
|
||||
|
||||
qcom_smd_set_drvdata(btq->acl_channel, btq);
|
||||
qcom_smd_set_drvdata(btq->cmd_channel, btq);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
|
||||
hci_set_drvdata(hdev, btq);
|
||||
btq->hdev = hdev;
|
||||
SET_HCIDEV_DEV(hdev, &pdev->dev);
|
||||
|
||||
hdev->bus = HCI_SMD;
|
||||
hdev->open = btqcomsmd_open;
|
||||
hdev->close = btqcomsmd_close;
|
||||
hdev->send = btqcomsmd_send;
|
||||
hdev->set_bdaddr = qca_set_bdaddr_rome;
|
||||
|
||||
ret = hci_register_dev(hdev);
|
||||
if (ret < 0) {
|
||||
hci_free_dev(hdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, btq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btqcomsmd_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct btqcomsmd *btq = platform_get_drvdata(pdev);
|
||||
|
||||
hci_unregister_dev(btq->hdev);
|
||||
hci_free_dev(btq->hdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id btqcomsmd_of_match[] = {
|
||||
{ .compatible = "qcom,wcnss-bt", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver btqcomsmd_driver = {
|
||||
.probe = btqcomsmd_probe,
|
||||
.remove = btqcomsmd_remove,
|
||||
.driver = {
|
||||
.name = "btqcomsmd",
|
||||
.of_match_table = btqcomsmd_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(btqcomsmd_driver);
|
||||
|
||||
MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
|
||||
MODULE_DESCRIPTION("Qualcomm SMD HCI driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
+95
-12
@@ -33,6 +33,7 @@
|
||||
#define RTL_ROM_LMP_8723B 0x8723
|
||||
#define RTL_ROM_LMP_8821A 0x8821
|
||||
#define RTL_ROM_LMP_8761A 0x8761
|
||||
#define RTL_ROM_LMP_8822B 0x8822
|
||||
|
||||
static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version)
|
||||
{
|
||||
@@ -78,11 +79,15 @@ static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver,
|
||||
const unsigned char *patch_length_base, *patch_offset_base;
|
||||
u32 patch_offset = 0;
|
||||
u16 patch_length, num_patches;
|
||||
const u16 project_id_to_lmp_subver[] = {
|
||||
RTL_ROM_LMP_8723A,
|
||||
RTL_ROM_LMP_8723B,
|
||||
RTL_ROM_LMP_8821A,
|
||||
RTL_ROM_LMP_8761A
|
||||
static const struct {
|
||||
__u16 lmp_subver;
|
||||
__u8 id;
|
||||
} project_id_to_lmp_subver[] = {
|
||||
{ RTL_ROM_LMP_8723A, 0 },
|
||||
{ RTL_ROM_LMP_8723B, 1 },
|
||||
{ RTL_ROM_LMP_8821A, 2 },
|
||||
{ RTL_ROM_LMP_8761A, 3 },
|
||||
{ RTL_ROM_LMP_8822B, 8 },
|
||||
};
|
||||
|
||||
ret = rtl_read_rom_version(hdev, &rom_version);
|
||||
@@ -134,14 +139,20 @@ static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (project_id >= ARRAY_SIZE(project_id_to_lmp_subver)) {
|
||||
/* Find project_id in table */
|
||||
for (i = 0; i < ARRAY_SIZE(project_id_to_lmp_subver); i++) {
|
||||
if (project_id == project_id_to_lmp_subver[i].id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(project_id_to_lmp_subver)) {
|
||||
BT_ERR("%s: unknown project id %d", hdev->name, project_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (lmp_subver != project_id_to_lmp_subver[project_id]) {
|
||||
if (lmp_subver != project_id_to_lmp_subver[i].lmp_subver) {
|
||||
BT_ERR("%s: firmware is for %x but this is a %x", hdev->name,
|
||||
project_id_to_lmp_subver[project_id], lmp_subver);
|
||||
project_id_to_lmp_subver[i].lmp_subver, lmp_subver);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -257,6 +268,26 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtl_load_config(struct hci_dev *hdev, const char *name, u8 **buff)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
BT_INFO("%s: rtl: loading %s", hdev->name, name);
|
||||
ret = request_firmware(&fw, name, &hdev->dev);
|
||||
if (ret < 0) {
|
||||
BT_ERR("%s: Failed to load %s", hdev->name, name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fw->size;
|
||||
*buff = kmemdup(fw->data, ret, GFP_KERNEL);
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btrtl_setup_rtl8723a(struct hci_dev *hdev)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
@@ -296,25 +327,74 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
|
||||
unsigned char *fw_data = NULL;
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
int cfg_sz;
|
||||
u8 *cfg_buff = NULL;
|
||||
u8 *tbuff;
|
||||
char *cfg_name = NULL;
|
||||
|
||||
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";
|
||||
break;
|
||||
default:
|
||||
BT_ERR("%s: rtl: no config according to lmp_subver %04x",
|
||||
hdev->name, lmp_subver);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cfg_name) {
|
||||
cfg_sz = rtl_load_config(hdev, cfg_name, &cfg_buff);
|
||||
if (cfg_sz < 0)
|
||||
cfg_sz = 0;
|
||||
} else
|
||||
cfg_sz = 0;
|
||||
|
||||
BT_INFO("%s: rtl: loading %s", hdev->name, fw_name);
|
||||
ret = request_firmware(&fw, fw_name, &hdev->dev);
|
||||
if (ret < 0) {
|
||||
BT_ERR("%s: Failed to load %s", hdev->name, fw_name);
|
||||
return ret;
|
||||
goto err_req_fw;
|
||||
}
|
||||
|
||||
ret = rtl8723b_parse_firmware(hdev, lmp_subver, fw, &fw_data);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (cfg_sz) {
|
||||
tbuff = kzalloc(ret + cfg_sz, GFP_KERNEL);
|
||||
if (!tbuff) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(tbuff, fw_data, ret);
|
||||
kfree(fw_data);
|
||||
|
||||
memcpy(tbuff + ret, cfg_buff, cfg_sz);
|
||||
ret += cfg_sz;
|
||||
|
||||
fw_data = tbuff;
|
||||
}
|
||||
|
||||
BT_INFO("cfg_sz %d, total size %d", cfg_sz, ret);
|
||||
|
||||
ret = rtl_download_firmware(hdev, fw_data, ret);
|
||||
kfree(fw_data);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
kfree(fw_data);
|
||||
err_req_fw:
|
||||
if (cfg_sz)
|
||||
kfree(cfg_buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -377,6 +457,9 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
|
||||
case RTL_ROM_LMP_8761A:
|
||||
return btrtl_setup_rtl8723b(hdev, lmp_subver,
|
||||
"rtl_bt/rtl8761a_fw.bin");
|
||||
case RTL_ROM_LMP_8822B:
|
||||
return btrtl_setup_rtl8723b(hdev, lmp_subver,
|
||||
"rtl_bt/rtl8822b_fw.bin");
|
||||
default:
|
||||
BT_INFO("rtl: assuming no firmware upload needed.");
|
||||
return 0;
|
||||
|
||||
@@ -62,6 +62,7 @@ static struct usb_driver btusb_driver;
|
||||
#define BTUSB_REALTEK 0x20000
|
||||
#define BTUSB_BCM2045 0x40000
|
||||
#define BTUSB_IFNUM_2 0x80000
|
||||
#define BTUSB_CW6622 0x100000
|
||||
|
||||
static const struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
@@ -248,6 +249,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
|
||||
/* QCA ROME chipset */
|
||||
{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME },
|
||||
@@ -290,7 +292,8 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x0400, 0x080a), .driver_info = BTUSB_BROKEN_ISOC },
|
||||
|
||||
/* CONWISE Technology based adapters with buggy SCO support */
|
||||
{ USB_DEVICE(0x0e5e, 0x6622), .driver_info = BTUSB_BROKEN_ISOC },
|
||||
{ USB_DEVICE(0x0e5e, 0x6622),
|
||||
.driver_info = BTUSB_BROKEN_ISOC | BTUSB_CW6622},
|
||||
|
||||
/* Roper Class 1 Bluetooth Dongle (Silicon Wave based) */
|
||||
{ USB_DEVICE(0x1310, 0x0001), .driver_info = BTUSB_SWAVE },
|
||||
@@ -2221,9 +2224,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
err = wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING,
|
||||
TASK_INTERRUPTIBLE,
|
||||
msecs_to_jiffies(5000));
|
||||
if (err == 1) {
|
||||
if (err == -EINTR) {
|
||||
BT_ERR("%s: Firmware loading interrupted", hdev->name);
|
||||
err = -EINTR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -2275,7 +2277,7 @@ done:
|
||||
TASK_INTERRUPTIBLE,
|
||||
msecs_to_jiffies(1000));
|
||||
|
||||
if (err == 1) {
|
||||
if (err == -EINTR) {
|
||||
BT_ERR("%s: Device boot interrupted", hdev->name);
|
||||
return -EINTR;
|
||||
}
|
||||
@@ -2845,6 +2847,9 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
hdev->send = btusb_send_frame;
|
||||
hdev->notify = btusb_notify;
|
||||
|
||||
if (id->driver_info & BTUSB_CW6622)
|
||||
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
|
||||
|
||||
if (id->driver_info & BTUSB_BCM2045)
|
||||
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
|
||||
|
||||
|
||||
@@ -798,7 +798,7 @@ static int bcm_remove(struct platform_device *pdev)
|
||||
|
||||
static const struct hci_uart_proto bcm_proto = {
|
||||
.id = HCI_UART_BCM,
|
||||
.name = "BCM",
|
||||
.name = "Broadcom",
|
||||
.manufacturer = 15,
|
||||
.init_speed = 115200,
|
||||
.oper_speed = 4000000,
|
||||
|
||||
@@ -128,7 +128,7 @@ static int intel_wait_booting(struct hci_uart *hu)
|
||||
TASK_INTERRUPTIBLE,
|
||||
msecs_to_jiffies(1000));
|
||||
|
||||
if (err == 1) {
|
||||
if (err == -EINTR) {
|
||||
bt_dev_err(hu->hdev, "Device boot interrupted");
|
||||
return -EINTR;
|
||||
}
|
||||
@@ -151,7 +151,7 @@ static int intel_wait_lpm_transaction(struct hci_uart *hu)
|
||||
TASK_INTERRUPTIBLE,
|
||||
msecs_to_jiffies(1000));
|
||||
|
||||
if (err == 1) {
|
||||
if (err == -EINTR) {
|
||||
bt_dev_err(hu->hdev, "LPM transaction interrupted");
|
||||
return -EINTR;
|
||||
}
|
||||
@@ -813,7 +813,7 @@ static int intel_setup(struct hci_uart *hu)
|
||||
err = wait_on_bit_timeout(&intel->flags, STATE_DOWNLOADING,
|
||||
TASK_INTERRUPTIBLE,
|
||||
msecs_to_jiffies(5000));
|
||||
if (err == 1) {
|
||||
if (err == -EINTR) {
|
||||
bt_dev_err(hdev, "Firmware loading interrupted");
|
||||
err = -EINTR;
|
||||
goto done;
|
||||
|
||||
@@ -810,6 +810,9 @@ static int __init hci_uart_init(void)
|
||||
#ifdef CONFIG_BT_HCIUART_AG6XX
|
||||
ag6xx_init();
|
||||
#endif
|
||||
#ifdef CONFIG_BT_HCIUART_MRVL
|
||||
mrvl_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -845,6 +848,9 @@ static void __exit hci_uart_exit(void)
|
||||
#ifdef CONFIG_BT_HCIUART_AG6XX
|
||||
ag6xx_deinit();
|
||||
#endif
|
||||
#ifdef CONFIG_BT_HCIUART_MRVL
|
||||
mrvl_deinit();
|
||||
#endif
|
||||
|
||||
/* Release tty registration of line discipline */
|
||||
err = tty_unregister_ldisc(N_HCI);
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
*
|
||||
* Bluetooth HCI UART driver for marvell devices
|
||||
*
|
||||
* Copyright (C) 2016 Marvell International Ltd.
|
||||
* Copyright (C) 2016 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/tty.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#include "hci_uart.h"
|
||||
|
||||
#define HCI_FW_REQ_PKT 0xA5
|
||||
#define HCI_CHIP_VER_PKT 0xAA
|
||||
|
||||
#define MRVL_ACK 0x5A
|
||||
#define MRVL_NAK 0xBF
|
||||
#define MRVL_RAW_DATA 0x1F
|
||||
|
||||
enum {
|
||||
STATE_CHIP_VER_PENDING,
|
||||
STATE_FW_REQ_PENDING,
|
||||
};
|
||||
|
||||
struct mrvl_data {
|
||||
struct sk_buff *rx_skb;
|
||||
struct sk_buff_head txq;
|
||||
struct sk_buff_head rawq;
|
||||
unsigned long flags;
|
||||
unsigned int tx_len;
|
||||
u8 id, rev;
|
||||
};
|
||||
|
||||
struct hci_mrvl_pkt {
|
||||
__le16 lhs;
|
||||
__le16 rhs;
|
||||
} __packed;
|
||||
#define HCI_MRVL_PKT_SIZE 4
|
||||
|
||||
static int mrvl_open(struct hci_uart *hu)
|
||||
{
|
||||
struct mrvl_data *mrvl;
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
mrvl = kzalloc(sizeof(*mrvl), GFP_KERNEL);
|
||||
if (!mrvl)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_queue_head_init(&mrvl->txq);
|
||||
skb_queue_head_init(&mrvl->rawq);
|
||||
|
||||
set_bit(STATE_CHIP_VER_PENDING, &mrvl->flags);
|
||||
|
||||
hu->priv = mrvl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mrvl_close(struct hci_uart *hu)
|
||||
{
|
||||
struct mrvl_data *mrvl = hu->priv;
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
skb_queue_purge(&mrvl->txq);
|
||||
skb_queue_purge(&mrvl->rawq);
|
||||
kfree_skb(mrvl->rx_skb);
|
||||
kfree(mrvl);
|
||||
|
||||
hu->priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mrvl_flush(struct hci_uart *hu)
|
||||
{
|
||||
struct mrvl_data *mrvl = hu->priv;
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
skb_queue_purge(&mrvl->txq);
|
||||
skb_queue_purge(&mrvl->rawq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sk_buff *mrvl_dequeue(struct hci_uart *hu)
|
||||
{
|
||||
struct mrvl_data *mrvl = hu->priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = skb_dequeue(&mrvl->txq);
|
||||
if (!skb) {
|
||||
/* Any raw data ? */
|
||||
skb = skb_dequeue(&mrvl->rawq);
|
||||
} else {
|
||||
/* Prepend skb with frame type */
|
||||
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int mrvl_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
{
|
||||
struct mrvl_data *mrvl = hu->priv;
|
||||
|
||||
skb_queue_tail(&mrvl->txq, skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mrvl_send_ack(struct hci_uart *hu, unsigned char type)
|
||||
{
|
||||
struct mrvl_data *mrvl = hu->priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* No H4 payload, only 1 byte header */
|
||||
skb = bt_skb_alloc(0, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
bt_dev_err(hu->hdev, "Unable to alloc ack/nak packet");
|
||||
return;
|
||||
}
|
||||
hci_skb_pkt_type(skb) = type;
|
||||
|
||||
skb_queue_tail(&mrvl->txq, skb);
|
||||
hci_uart_tx_wakeup(hu);
|
||||
}
|
||||
|
||||
static int mrvl_recv_fw_req(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_mrvl_pkt *pkt = (void *)skb->data;
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
struct mrvl_data *mrvl = hu->priv;
|
||||
int ret = 0;
|
||||
|
||||
if ((pkt->lhs ^ pkt->rhs) != 0xffff) {
|
||||
bt_dev_err(hdev, "Corrupted mrvl header");
|
||||
mrvl_send_ack(hu, MRVL_NAK);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
mrvl_send_ack(hu, MRVL_ACK);
|
||||
|
||||
if (!test_bit(STATE_FW_REQ_PENDING, &mrvl->flags)) {
|
||||
bt_dev_err(hdev, "Received unexpected firmware request");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
mrvl->tx_len = le16_to_cpu(pkt->lhs);
|
||||
|
||||
clear_bit(STATE_FW_REQ_PENDING, &mrvl->flags);
|
||||
smp_mb__after_atomic();
|
||||
wake_up_bit(&mrvl->flags, STATE_FW_REQ_PENDING);
|
||||
|
||||
done:
|
||||
kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mrvl_recv_chip_ver(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_mrvl_pkt *pkt = (void *)skb->data;
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
struct mrvl_data *mrvl = hu->priv;
|
||||
u16 version = le16_to_cpu(pkt->lhs);
|
||||
int ret = 0;
|
||||
|
||||
if ((pkt->lhs ^ pkt->rhs) != 0xffff) {
|
||||
bt_dev_err(hdev, "Corrupted mrvl header");
|
||||
mrvl_send_ack(hu, MRVL_NAK);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
mrvl_send_ack(hu, MRVL_ACK);
|
||||
|
||||
if (!test_bit(STATE_CHIP_VER_PENDING, &mrvl->flags)) {
|
||||
bt_dev_err(hdev, "Received unexpected chip version");
|
||||
goto done;
|
||||
}
|
||||
|
||||
mrvl->id = version;
|
||||
mrvl->rev = version >> 8;
|
||||
|
||||
bt_dev_info(hdev, "Controller id = %x, rev = %x", mrvl->id, mrvl->rev);
|
||||
|
||||
clear_bit(STATE_CHIP_VER_PENDING, &mrvl->flags);
|
||||
smp_mb__after_atomic();
|
||||
wake_up_bit(&mrvl->flags, STATE_CHIP_VER_PENDING);
|
||||
|
||||
done:
|
||||
kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define HCI_RECV_CHIP_VER \
|
||||
.type = HCI_CHIP_VER_PKT, \
|
||||
.hlen = HCI_MRVL_PKT_SIZE, \
|
||||
.loff = 0, \
|
||||
.lsize = 0, \
|
||||
.maxlen = HCI_MRVL_PKT_SIZE
|
||||
|
||||
#define HCI_RECV_FW_REQ \
|
||||
.type = HCI_FW_REQ_PKT, \
|
||||
.hlen = HCI_MRVL_PKT_SIZE, \
|
||||
.loff = 0, \
|
||||
.lsize = 0, \
|
||||
.maxlen = HCI_MRVL_PKT_SIZE
|
||||
|
||||
static const struct h4_recv_pkt mrvl_recv_pkts[] = {
|
||||
{ H4_RECV_ACL, .recv = hci_recv_frame },
|
||||
{ H4_RECV_SCO, .recv = hci_recv_frame },
|
||||
{ H4_RECV_EVENT, .recv = hci_recv_frame },
|
||||
{ HCI_RECV_FW_REQ, .recv = mrvl_recv_fw_req },
|
||||
{ HCI_RECV_CHIP_VER, .recv = mrvl_recv_chip_ver },
|
||||
};
|
||||
|
||||
static int mrvl_recv(struct hci_uart *hu, const void *data, int count)
|
||||
{
|
||||
struct mrvl_data *mrvl = hu->priv;
|
||||
|
||||
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
return -EUNATCH;
|
||||
|
||||
mrvl->rx_skb = h4_recv_buf(hu->hdev, mrvl->rx_skb, data, count,
|
||||
mrvl_recv_pkts,
|
||||
ARRAY_SIZE(mrvl_recv_pkts));
|
||||
if (IS_ERR(mrvl->rx_skb)) {
|
||||
int err = PTR_ERR(mrvl->rx_skb);
|
||||
bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
|
||||
mrvl->rx_skb = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int mrvl_load_firmware(struct hci_dev *hdev, const char *name)
|
||||
{
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
struct mrvl_data *mrvl = hu->priv;
|
||||
const struct firmware *fw = NULL;
|
||||
const u8 *fw_ptr, *fw_max;
|
||||
int err;
|
||||
|
||||
err = request_firmware(&fw, name, &hdev->dev);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to load firmware file %s", name);
|
||||
return err;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data;
|
||||
fw_max = fw->data + fw->size;
|
||||
|
||||
bt_dev_info(hdev, "Loading %s", name);
|
||||
|
||||
set_bit(STATE_FW_REQ_PENDING, &mrvl->flags);
|
||||
|
||||
while (fw_ptr <= fw_max) {
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* Controller drives the firmware load by sending firmware
|
||||
* request packets containing the expected fragment size.
|
||||
*/
|
||||
err = wait_on_bit_timeout(&mrvl->flags, STATE_FW_REQ_PENDING,
|
||||
TASK_INTERRUPTIBLE,
|
||||
msecs_to_jiffies(2000));
|
||||
if (err == 1) {
|
||||
bt_dev_err(hdev, "Firmware load interrupted");
|
||||
err = -EINTR;
|
||||
break;
|
||||
} else if (err) {
|
||||
bt_dev_err(hdev, "Firmware request timeout");
|
||||
err = -ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
bt_dev_dbg(hdev, "Firmware request, expecting %d bytes",
|
||||
mrvl->tx_len);
|
||||
|
||||
if (fw_ptr == fw_max) {
|
||||
/* Controller requests a null size once firmware is
|
||||
* fully loaded. If controller expects more data, there
|
||||
* is an issue.
|
||||
*/
|
||||
if (!mrvl->tx_len) {
|
||||
bt_dev_info(hdev, "Firmware loading complete");
|
||||
} else {
|
||||
bt_dev_err(hdev, "Firmware loading failure");
|
||||
err = -EINVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (fw_ptr + mrvl->tx_len > fw_max) {
|
||||
mrvl->tx_len = fw_max - fw_ptr;
|
||||
bt_dev_dbg(hdev, "Adjusting tx_len to %d",
|
||||
mrvl->tx_len);
|
||||
}
|
||||
|
||||
skb = bt_skb_alloc(mrvl->tx_len, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
bt_dev_err(hdev, "Failed to alloc mem for FW packet");
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
bt_cb(skb)->pkt_type = MRVL_RAW_DATA;
|
||||
|
||||
memcpy(skb_put(skb, mrvl->tx_len), fw_ptr, mrvl->tx_len);
|
||||
fw_ptr += mrvl->tx_len;
|
||||
|
||||
set_bit(STATE_FW_REQ_PENDING, &mrvl->flags);
|
||||
|
||||
skb_queue_tail(&mrvl->rawq, skb);
|
||||
hci_uart_tx_wakeup(hu);
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mrvl_setup(struct hci_uart *hu)
|
||||
{
|
||||
int err;
|
||||
|
||||
hci_uart_set_flow_control(hu, true);
|
||||
|
||||
err = mrvl_load_firmware(hu->hdev, "mrvl/helper_uart_3000000.bin");
|
||||
if (err) {
|
||||
bt_dev_err(hu->hdev, "Unable to download firmware helper");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hci_uart_set_baudrate(hu, 3000000);
|
||||
hci_uart_set_flow_control(hu, false);
|
||||
|
||||
err = mrvl_load_firmware(hu->hdev, "mrvl/uart8897_bt.bin");
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hci_uart_proto mrvl_proto = {
|
||||
.id = HCI_UART_MRVL,
|
||||
.name = "Marvell",
|
||||
.init_speed = 115200,
|
||||
.open = mrvl_open,
|
||||
.close = mrvl_close,
|
||||
.flush = mrvl_flush,
|
||||
.setup = mrvl_setup,
|
||||
.recv = mrvl_recv,
|
||||
.enqueue = mrvl_enqueue,
|
||||
.dequeue = mrvl_dequeue,
|
||||
};
|
||||
|
||||
int __init mrvl_init(void)
|
||||
{
|
||||
return hci_uart_register_proto(&mrvl_proto);
|
||||
}
|
||||
|
||||
int __exit mrvl_deinit(void)
|
||||
{
|
||||
return hci_uart_unregister_proto(&mrvl_proto);
|
||||
}
|
||||
@@ -397,7 +397,7 @@ static int qca_open(struct hci_uart *hu)
|
||||
skb_queue_head_init(&qca->txq);
|
||||
skb_queue_head_init(&qca->tx_wait_q);
|
||||
spin_lock_init(&qca->hci_ibs_lock);
|
||||
qca->workqueue = create_singlethread_workqueue("qca_wq");
|
||||
qca->workqueue = alloc_ordered_workqueue("qca_wq", 0);
|
||||
if (!qca->workqueue) {
|
||||
BT_ERR("QCA Workqueue not initialized properly");
|
||||
kfree(qca);
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#define HCIUARTGETFLAGS _IOR('U', 204, int)
|
||||
|
||||
/* UART protocols */
|
||||
#define HCI_UART_MAX_PROTO 10
|
||||
#define HCI_UART_MAX_PROTO 12
|
||||
|
||||
#define HCI_UART_H4 0
|
||||
#define HCI_UART_BCSP 1
|
||||
@@ -47,6 +47,8 @@
|
||||
#define HCI_UART_BCM 7
|
||||
#define HCI_UART_QCA 8
|
||||
#define HCI_UART_AG6XX 9
|
||||
#define HCI_UART_NOKIA 10
|
||||
#define HCI_UART_MRVL 11
|
||||
|
||||
#define HCI_UART_RAW_DEVICE 0
|
||||
#define HCI_UART_RESET_ON_INIT 1
|
||||
@@ -189,3 +191,8 @@ int qca_deinit(void);
|
||||
int ag6xx_init(void);
|
||||
int ag6xx_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_MRVL
|
||||
int mrvl_init(void);
|
||||
int mrvl_deinit(void);
|
||||
#endif
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
static int numlbs = 2;
|
||||
|
||||
static LIST_HEAD(fakelb_phys);
|
||||
static DEFINE_SPINLOCK(fakelb_phys_lock);
|
||||
static DEFINE_MUTEX(fakelb_phys_lock);
|
||||
|
||||
static LIST_HEAD(fakelb_ifup_phys);
|
||||
static DEFINE_RWLOCK(fakelb_ifup_phys_lock);
|
||||
@@ -188,9 +188,9 @@ static int fakelb_add_one(struct device *dev)
|
||||
if (err)
|
||||
goto err_reg;
|
||||
|
||||
spin_lock(&fakelb_phys_lock);
|
||||
mutex_lock(&fakelb_phys_lock);
|
||||
list_add_tail(&phy->list, &fakelb_phys);
|
||||
spin_unlock(&fakelb_phys_lock);
|
||||
mutex_unlock(&fakelb_phys_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -222,10 +222,10 @@ static int fakelb_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
err_slave:
|
||||
spin_lock(&fakelb_phys_lock);
|
||||
mutex_lock(&fakelb_phys_lock);
|
||||
list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)
|
||||
fakelb_del(phy);
|
||||
spin_unlock(&fakelb_phys_lock);
|
||||
mutex_unlock(&fakelb_phys_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -233,10 +233,10 @@ static int fakelb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct fakelb_phy *phy, *tmp;
|
||||
|
||||
spin_lock(&fakelb_phys_lock);
|
||||
mutex_lock(&fakelb_phys_lock);
|
||||
list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)
|
||||
fakelb_del(phy);
|
||||
spin_unlock(&fakelb_phys_lock);
|
||||
mutex_unlock(&fakelb_phys_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
#include <net/sock.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#define BT_SUBSYS_VERSION "2.21"
|
||||
#define BT_SUBSYS_VERSION 2
|
||||
#define BT_SUBSYS_REVISION 22
|
||||
|
||||
#ifndef AF_BLUETOOTH
|
||||
#define AF_BLUETOOTH 31
|
||||
@@ -371,6 +372,7 @@ 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);
|
||||
u32 hci_sock_get_cookie(struct sock *sk);
|
||||
|
||||
int hci_sock_init(void);
|
||||
void hci_sock_cleanup(void);
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#define HCI_SDIO 6
|
||||
#define HCI_SPI 7
|
||||
#define HCI_I2C 8
|
||||
#define HCI_SMD 9
|
||||
|
||||
/* HCI controller types */
|
||||
#define HCI_PRIMARY 0x00
|
||||
@@ -207,7 +208,11 @@ enum {
|
||||
HCI_MGMT_INDEX_EVENTS,
|
||||
HCI_MGMT_UNCONF_INDEX_EVENTS,
|
||||
HCI_MGMT_EXT_INDEX_EVENTS,
|
||||
HCI_MGMT_GENERIC_EVENTS,
|
||||
HCI_MGMT_EXT_INFO_EVENTS,
|
||||
HCI_MGMT_OPTION_EVENTS,
|
||||
HCI_MGMT_SETTING_EVENTS,
|
||||
HCI_MGMT_DEV_CLASS_EVENTS,
|
||||
HCI_MGMT_LOCAL_NAME_EVENTS,
|
||||
HCI_MGMT_OOB_DATA_EVENTS,
|
||||
};
|
||||
|
||||
|
||||
@@ -211,6 +211,7 @@ struct hci_dev {
|
||||
__u8 dev_name[HCI_MAX_NAME_LENGTH];
|
||||
__u8 short_name[HCI_MAX_SHORT_NAME_LENGTH];
|
||||
__u8 eir[HCI_MAX_EIR_LENGTH];
|
||||
__u16 appearance;
|
||||
__u8 dev_class[3];
|
||||
__u8 major_class;
|
||||
__u8 minor_class;
|
||||
@@ -399,7 +400,9 @@ struct hci_dev {
|
||||
struct delayed_work rpa_expired;
|
||||
bdaddr_t rpa;
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_LEDS)
|
||||
struct led_trigger *power_led;
|
||||
#endif
|
||||
|
||||
int (*open)(struct hci_dev *hdev);
|
||||
int (*close)(struct hci_dev *hdev);
|
||||
@@ -1026,8 +1029,8 @@ int hci_resume_dev(struct hci_dev *hdev);
|
||||
int hci_reset_dev(struct hci_dev *hdev);
|
||||
int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
void hci_set_hw_info(struct hci_dev *hdev, const char *fmt, ...);
|
||||
void hci_set_fw_info(struct hci_dev *hdev, const char *fmt, ...);
|
||||
__printf(2, 3) void hci_set_hw_info(struct hci_dev *hdev, const char *fmt, ...);
|
||||
__printf(2, 3) void hci_set_fw_info(struct hci_dev *hdev, const char *fmt, ...);
|
||||
int hci_dev_open(__u16 dev);
|
||||
int hci_dev_close(__u16 dev);
|
||||
int hci_dev_do_close(struct hci_dev *hdev);
|
||||
@@ -1404,6 +1407,9 @@ 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,
|
||||
int flag, struct sock *skip_sk);
|
||||
void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
void hci_send_monitor_ctrl_event(struct hci_dev *hdev, u16 event,
|
||||
void *data, u16 data_len, ktime_t tstamp,
|
||||
int flag, struct sock *skip_sk);
|
||||
|
||||
void hci_sock_dev_event(struct hci_dev *hdev, int event);
|
||||
|
||||
@@ -1449,6 +1455,7 @@ 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 */
|
||||
|
||||
void mgmt_fill_version_info(void *ver);
|
||||
int mgmt_new_settings(struct hci_dev *hdev);
|
||||
void mgmt_index_added(struct hci_dev *hdev);
|
||||
void mgmt_index_removed(struct hci_dev *hdev);
|
||||
|
||||
@@ -45,6 +45,10 @@ struct hci_mon_hdr {
|
||||
#define HCI_MON_VENDOR_DIAG 11
|
||||
#define HCI_MON_SYSTEM_NOTE 12
|
||||
#define HCI_MON_USER_LOGGING 13
|
||||
#define HCI_MON_CTRL_OPEN 14
|
||||
#define HCI_MON_CTRL_CLOSE 15
|
||||
#define HCI_MON_CTRL_COMMAND 16
|
||||
#define HCI_MON_CTRL_EVENT 17
|
||||
|
||||
struct hci_mon_new_index {
|
||||
__u8 type;
|
||||
|
||||
@@ -586,6 +586,24 @@ struct mgmt_rp_get_adv_size_info {
|
||||
|
||||
#define MGMT_OP_START_LIMITED_DISCOVERY 0x0041
|
||||
|
||||
#define MGMT_OP_READ_EXT_INFO 0x0042
|
||||
#define MGMT_READ_EXT_INFO_SIZE 0
|
||||
struct mgmt_rp_read_ext_info {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 version;
|
||||
__le16 manufacturer;
|
||||
__le32 supported_settings;
|
||||
__le32 current_settings;
|
||||
__le16 eir_len;
|
||||
__u8 eir[0];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_SET_APPEARANCE 0x0043
|
||||
struct mgmt_cp_set_appearance {
|
||||
__u16 appearance;
|
||||
} __packed;
|
||||
#define MGMT_SET_APPEARANCE_SIZE 2
|
||||
|
||||
#define MGMT_EV_CMD_COMPLETE 0x0001
|
||||
struct mgmt_ev_cmd_complete {
|
||||
__le16 opcode;
|
||||
@@ -800,3 +818,9 @@ struct mgmt_ev_advertising_added {
|
||||
struct mgmt_ev_advertising_removed {
|
||||
__u8 instance;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_EXT_INFO_CHANGED 0x0025
|
||||
struct mgmt_ev_ext_info_changed {
|
||||
__le16 eir_len;
|
||||
__u8 eir[0];
|
||||
} __packed;
|
||||
|
||||
@@ -101,8 +101,6 @@ static void lowpan_ndisc_802154_update(struct neighbour *n, u32 flags,
|
||||
ieee802154_be16_to_le16(&neigh->short_addr, lladdr_short);
|
||||
if (!lowpan_802154_is_valid_src_short_addr(neigh->short_addr))
|
||||
neigh->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
|
||||
} else {
|
||||
neigh->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
|
||||
}
|
||||
write_unlock_bh(&n->lock);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user