mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -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 2018-08-05 Here's the main bluetooth-next pull request for the 4.19 kernel. - Added support for Bluetooth Advertising Extensions - Added vendor driver support to hci_h5 HCI driver - Added serdev support to hci_h5 driver - Added support for Qualcomm wcn3990 controller - Added support for RTL8723BS and RTL8723DS controllers - btusb: Added new ID for Realtek 8723DE - Several other smaller fixes & cleanups Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
6277547f33
29 files changed
+3247
-585
No files matched your search
@@ -10,12 +10,25 @@ device the slave device is attached to.
|
||||
Required properties:
|
||||
- compatible: should contain one of the following:
|
||||
* "qcom,qca6174-bt"
|
||||
* "qcom,wcn3990-bt"
|
||||
|
||||
Optional properties for compatible string qcom,qca6174-bt:
|
||||
|
||||
Optional properties:
|
||||
- enable-gpios: gpio specifier used to enable chip
|
||||
- clocks: clock provided to the controller (SUSCLK_32KHZ)
|
||||
|
||||
Example:
|
||||
Required properties for compatible string qcom,wcn3990-bt:
|
||||
|
||||
- vddio-supply: VDD_IO supply regulator handle.
|
||||
- vddxo-supply: VDD_XO supply regulator handle.
|
||||
- vddrf-supply: VDD_RF supply regulator handle.
|
||||
- vddch0-supply: VDD_CH0 supply regulator handle.
|
||||
|
||||
Optional properties for compatible string qcom,wcn3990-bt:
|
||||
|
||||
- max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt
|
||||
|
||||
Examples:
|
||||
|
||||
serial@7570000 {
|
||||
label = "BT-UART";
|
||||
@@ -28,3 +41,15 @@ serial@7570000 {
|
||||
clocks = <&divclk4>;
|
||||
};
|
||||
};
|
||||
|
||||
serial@898000 {
|
||||
bluetooth {
|
||||
compatible = "qcom,wcn3990-bt";
|
||||
|
||||
vddio-supply = <&vreg_s4a_1p8>;
|
||||
vddxo-supply = <&vreg_l7a_1p8>;
|
||||
vddrf-supply = <&vreg_l17a_1p3>;
|
||||
vddch0-supply = <&vreg_l25a_3p3>;
|
||||
max-speed = <3200000>;
|
||||
};
|
||||
};
|
||||
@@ -159,6 +159,7 @@ config BT_HCIUART_LL
|
||||
config BT_HCIUART_3WIRE
|
||||
bool "Three-wire UART (H5) protocol support"
|
||||
depends on BT_HCIUART
|
||||
depends on BT_HCIUART_SERDEV
|
||||
help
|
||||
The HCI Three-wire UART Transport Layer makes it possible to
|
||||
user the Bluetooth HCI over a serial port interface. The HCI
|
||||
|
||||
@@ -490,7 +490,7 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
count = skb->len;
|
||||
|
||||
/* Max HCI frame size seems to be 1511 + 1 */
|
||||
nskb = bt_skb_alloc(count + 32, GFP_ATOMIC);
|
||||
nskb = bt_skb_alloc(count + 32, GFP_KERNEL);
|
||||
if (!nskb) {
|
||||
BT_ERR("Can't allocate memory for new packet");
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -565,7 +565,7 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
|
||||
/* Ericsson baud rate command */
|
||||
unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 };
|
||||
|
||||
skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
return -1;
|
||||
|
||||
@@ -289,7 +289,7 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
skb->dev = (void *) hdev;
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -298,7 +298,7 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
switch (hci_skb_pkt_type(skb)) {
|
||||
case HCI_COMMAND_PKT:
|
||||
dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
|
||||
dr = kmalloc(sizeof(*dr), GFP_KERNEL);
|
||||
if (!dr) {
|
||||
usb_free_urb(urb);
|
||||
return -ENOMEM;
|
||||
@@ -343,7 +343,7 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
usb_anchor_urb(urb, &data->tx_anchor);
|
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
err = usb_submit_urb(urb, GFP_KERNEL);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "urb %p submission failed", urb);
|
||||
kfree(urb->setup_packet);
|
||||
|
||||
@@ -718,7 +718,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
|
||||
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
BT_ERR("No free skb");
|
||||
ret = -ENOMEM;
|
||||
|
||||
+64
-53
@@ -27,7 +27,7 @@
|
||||
|
||||
#define VERSION "0.1"
|
||||
|
||||
static int rome_patch_ver_req(struct hci_dev *hdev, u32 *rome_version)
|
||||
int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct edl_event_hdr *edl;
|
||||
@@ -35,36 +35,35 @@ static int rome_patch_ver_req(struct hci_dev *hdev, u32 *rome_version)
|
||||
char cmd;
|
||||
int err = 0;
|
||||
|
||||
BT_DBG("%s: ROME Patch Version Request", hdev->name);
|
||||
bt_dev_dbg(hdev, "QCA Version Request");
|
||||
|
||||
cmd = EDL_PATCH_VER_REQ_CMD;
|
||||
skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN,
|
||||
&cmd, HCI_VENDOR_PKT, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
BT_ERR("%s: Failed to read version of ROME (%d)", hdev->name,
|
||||
err);
|
||||
bt_dev_err(hdev, "Reading QCA version information failed (%d)",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*edl) + sizeof(*ver)) {
|
||||
BT_ERR("%s: Version size mismatch len %d", hdev->name,
|
||||
skb->len);
|
||||
bt_dev_err(hdev, "QCA Version size mismatch len %d", skb->len);
|
||||
err = -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
|
||||
edl = (struct edl_event_hdr *)(skb->data);
|
||||
if (!edl) {
|
||||
BT_ERR("%s: TLV with no header", hdev->name);
|
||||
bt_dev_err(hdev, "QCA TLV with no header");
|
||||
err = -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
|
||||
edl->rtype != EDL_APP_VER_RES_EVT) {
|
||||
BT_ERR("%s: Wrong packet received %d %d", hdev->name,
|
||||
edl->cresp, edl->rtype);
|
||||
bt_dev_err(hdev, "QCA Wrong packet received %d %d", edl->cresp,
|
||||
edl->rtype);
|
||||
err = -EIO;
|
||||
goto out;
|
||||
}
|
||||
@@ -76,30 +75,35 @@ static int rome_patch_ver_req(struct hci_dev *hdev, u32 *rome_version)
|
||||
BT_DBG("%s: ROM :0x%08x", hdev->name, le16_to_cpu(ver->rome_ver));
|
||||
BT_DBG("%s: SOC :0x%08x", hdev->name, le32_to_cpu(ver->soc_id));
|
||||
|
||||
/* ROME chipset version can be decided by patch and SoC
|
||||
/* QCA chipset version can be decided by patch and SoC
|
||||
* version, combination with upper 2 bytes from SoC
|
||||
* and lower 2 bytes from patch will be used.
|
||||
*/
|
||||
*rome_version = (le32_to_cpu(ver->soc_id) << 16) |
|
||||
*soc_version = (le32_to_cpu(ver->soc_id) << 16) |
|
||||
(le16_to_cpu(ver->rome_ver) & 0x0000ffff);
|
||||
if (*soc_version == 0)
|
||||
err = -EILSEQ;
|
||||
|
||||
out:
|
||||
kfree_skb(skb);
|
||||
if (err)
|
||||
bt_dev_err(hdev, "QCA Failed to get version (%d)", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qca_read_soc_version);
|
||||
|
||||
static int rome_reset(struct hci_dev *hdev)
|
||||
static int qca_send_reset(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
BT_DBG("%s: ROME HCI_RESET", hdev->name);
|
||||
bt_dev_dbg(hdev, "QCA HCI_RESET");
|
||||
|
||||
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
BT_ERR("%s: Reset failed (%d)", hdev->name, err);
|
||||
bt_dev_err(hdev, "QCA Reset failed (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -108,7 +112,7 @@ static int rome_reset(struct hci_dev *hdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rome_tlv_check_data(struct rome_config *config,
|
||||
static void qca_tlv_check_data(struct rome_config *config,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
const u8 *data;
|
||||
@@ -207,7 +211,7 @@ static void rome_tlv_check_data(struct rome_config *config,
|
||||
}
|
||||
}
|
||||
|
||||
static int rome_tlv_send_segment(struct hci_dev *hdev, int seg_size,
|
||||
static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,
|
||||
const u8 *data, enum rome_tlv_dnld_mode mode)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
@@ -228,19 +232,19 @@ static int rome_tlv_send_segment(struct hci_dev *hdev, int seg_size,
|
||||
HCI_VENDOR_PKT, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
BT_ERR("%s: Failed to send TLV segment (%d)", hdev->name, err);
|
||||
bt_dev_err(hdev, "QCA Failed to send TLV segment (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*edl) + sizeof(*tlv_resp)) {
|
||||
BT_ERR("%s: TLV response size mismatch", hdev->name);
|
||||
bt_dev_err(hdev, "QCA TLV response size mismatch");
|
||||
err = -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
|
||||
edl = (struct edl_event_hdr *)(skb->data);
|
||||
if (!edl) {
|
||||
BT_ERR("%s: TLV with no header", hdev->name);
|
||||
bt_dev_err(hdev, "TLV with no header");
|
||||
err = -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
@@ -249,8 +253,8 @@ static int rome_tlv_send_segment(struct hci_dev *hdev, int seg_size,
|
||||
|
||||
if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
|
||||
edl->rtype != EDL_TVL_DNLD_RES_EVT || tlv_resp->result != 0x00) {
|
||||
BT_ERR("%s: TLV with error stat 0x%x rtype 0x%x (0x%x)",
|
||||
hdev->name, edl->cresp, edl->rtype, tlv_resp->result);
|
||||
bt_dev_err(hdev, "QCA TLV with error stat 0x%x rtype 0x%x (0x%x)",
|
||||
edl->cresp, edl->rtype, tlv_resp->result);
|
||||
err = -EIO;
|
||||
}
|
||||
|
||||
@@ -260,23 +264,23 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rome_download_firmware(struct hci_dev *hdev,
|
||||
static int qca_download_firmware(struct hci_dev *hdev,
|
||||
struct rome_config *config)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
const u8 *segment;
|
||||
int ret, remain, i = 0;
|
||||
|
||||
bt_dev_info(hdev, "ROME Downloading %s", config->fwname);
|
||||
bt_dev_info(hdev, "QCA Downloading %s", config->fwname);
|
||||
|
||||
ret = request_firmware(&fw, config->fwname, &hdev->dev);
|
||||
if (ret) {
|
||||
BT_ERR("%s: Failed to request file: %s (%d)", hdev->name,
|
||||
config->fwname, ret);
|
||||
bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
|
||||
config->fwname, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rome_tlv_check_data(config, fw);
|
||||
qca_tlv_check_data(config, fw);
|
||||
|
||||
segment = fw->data;
|
||||
remain = fw->size;
|
||||
@@ -290,7 +294,7 @@ static int rome_download_firmware(struct hci_dev *hdev,
|
||||
if (!remain || segsize < MAX_SIZE_PER_TLV_SEGMENT)
|
||||
config->dnld_mode = ROME_SKIP_EVT_NONE;
|
||||
|
||||
ret = rome_tlv_send_segment(hdev, segsize, segment,
|
||||
ret = qca_tlv_send_segment(hdev, segsize, segment,
|
||||
config->dnld_mode);
|
||||
if (ret)
|
||||
break;
|
||||
@@ -317,8 +321,7 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||
HCI_VENDOR_PKT, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
BT_ERR("%s: Change address command failed (%d)",
|
||||
hdev->name, err);
|
||||
bt_dev_err(hdev, "QCA Change address command failed (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -328,57 +331,65 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
|
||||
|
||||
int qca_uart_setup_rome(struct hci_dev *hdev, uint8_t baudrate)
|
||||
int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
||||
enum qca_btsoc_type soc_type, u32 soc_ver)
|
||||
{
|
||||
u32 rome_ver = 0;
|
||||
struct rome_config config;
|
||||
int err;
|
||||
u8 rom_ver;
|
||||
|
||||
BT_DBG("%s: ROME setup on UART", hdev->name);
|
||||
bt_dev_dbg(hdev, "QCA setup on UART");
|
||||
|
||||
config.user_baud_rate = baudrate;
|
||||
|
||||
/* Get ROME version information */
|
||||
err = rome_patch_ver_req(hdev, &rome_ver);
|
||||
if (err < 0 || rome_ver == 0) {
|
||||
BT_ERR("%s: Failed to get version 0x%x", hdev->name, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "ROME controller version 0x%08x", rome_ver);
|
||||
|
||||
/* Download rampatch file */
|
||||
config.type = TLV_TYPE_PATCH;
|
||||
snprintf(config.fwname, sizeof(config.fwname), "qca/rampatch_%08x.bin",
|
||||
rome_ver);
|
||||
err = rome_download_firmware(hdev, &config);
|
||||
if (soc_type == QCA_WCN3990) {
|
||||
/* Firmware files to download are based on ROM version.
|
||||
* ROM version is derived from last two bytes of soc_ver.
|
||||
*/
|
||||
rom_ver = ((soc_ver & 0x00000f00) >> 0x04) |
|
||||
(soc_ver & 0x0000000f);
|
||||
snprintf(config.fwname, sizeof(config.fwname),
|
||||
"qca/crbtfw%02x.tlv", rom_ver);
|
||||
} else {
|
||||
snprintf(config.fwname, sizeof(config.fwname),
|
||||
"qca/rampatch_%08x.bin", soc_ver);
|
||||
}
|
||||
|
||||
err = qca_download_firmware(hdev, &config);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to download patch (%d)", hdev->name, err);
|
||||
bt_dev_err(hdev, "QCA Failed to download patch (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Download NVM configuration */
|
||||
config.type = TLV_TYPE_NVM;
|
||||
snprintf(config.fwname, sizeof(config.fwname), "qca/nvm_%08x.bin",
|
||||
rome_ver);
|
||||
err = rome_download_firmware(hdev, &config);
|
||||
if (soc_type == QCA_WCN3990)
|
||||
snprintf(config.fwname, sizeof(config.fwname),
|
||||
"qca/crnv%02x.bin", rom_ver);
|
||||
else
|
||||
snprintf(config.fwname, sizeof(config.fwname),
|
||||
"qca/nvm_%08x.bin", soc_ver);
|
||||
|
||||
err = qca_download_firmware(hdev, &config);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to download NVM (%d)", hdev->name, err);
|
||||
bt_dev_err(hdev, "QCA Failed to download NVM (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Perform HCI reset */
|
||||
err = rome_reset(hdev);
|
||||
err = qca_send_reset(hdev);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to run HCI_RESET (%d)", hdev->name, err);
|
||||
bt_dev_err(hdev, "QCA Failed to run HCI_RESET (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "ROME setup on UART is completed");
|
||||
bt_dev_info(hdev, "QCA setup on UART is completed");
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qca_uart_setup_rome);
|
||||
EXPORT_SYMBOL_GPL(qca_uart_setup);
|
||||
|
||||
MODULE_AUTHOR("Ben Young Tae Kim <ytkim@qca.qualcomm.com>");
|
||||
MODULE_DESCRIPTION("Bluetooth support for Qualcomm Atheros family ver " VERSION);
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
#define EDL_TAG_ID_HCI (17)
|
||||
#define EDL_TAG_ID_DEEP_SLEEP (27)
|
||||
|
||||
#define QCA_WCN3990_POWERON_PULSE 0xFC
|
||||
#define QCA_WCN3990_POWEROFF_PULSE 0xC0
|
||||
|
||||
enum qca_bardrate {
|
||||
QCA_BAUDRATE_115200 = 0,
|
||||
QCA_BAUDRATE_57600,
|
||||
@@ -124,10 +127,19 @@ struct tlv_type_hdr {
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
enum qca_btsoc_type {
|
||||
QCA_INVALID = -1,
|
||||
QCA_AR3002,
|
||||
QCA_ROME,
|
||||
QCA_WCN3990
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_QCA)
|
||||
|
||||
int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr);
|
||||
int qca_uart_setup_rome(struct hci_dev *hdev, uint8_t baudrate);
|
||||
int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
||||
enum qca_btsoc_type soc_type, u32 soc_ver);
|
||||
int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version);
|
||||
|
||||
#else
|
||||
|
||||
@@ -136,7 +148,13 @@ static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdad
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int qca_uart_setup_rome(struct hci_dev *hdev, int speed)
|
||||
static inline int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
||||
enum qca_btsoc_type soc_type, u32 soc_ver)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
+376
-144
File diff suppressed because it is too large.
Load diff
@@ -17,6 +17,13 @@
|
||||
|
||||
#define RTL_FRAG_LEN 252
|
||||
|
||||
#define rtl_dev_err(dev, fmt, ...) bt_dev_err(dev, "RTL: " fmt, ##__VA_ARGS__)
|
||||
#define rtl_dev_warn(dev, fmt, ...) bt_dev_warn(dev, "RTL: " fmt, ##__VA_ARGS__)
|
||||
#define rtl_dev_info(dev, fmt, ...) bt_dev_info(dev, "RTL: " fmt, ##__VA_ARGS__)
|
||||
#define rtl_dev_dbg(dev, fmt, ...) bt_dev_dbg(dev, "RTL: " fmt, ##__VA_ARGS__)
|
||||
|
||||
struct btrtl_device_info;
|
||||
|
||||
struct rtl_download_cmd {
|
||||
__u8 index;
|
||||
__u8 data[RTL_FRAG_LEN];
|
||||
@@ -38,15 +45,61 @@ struct rtl_epatch_header {
|
||||
__le16 num_patches;
|
||||
} __packed;
|
||||
|
||||
struct rtl_vendor_config_entry {
|
||||
__le16 offset;
|
||||
__u8 len;
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct rtl_vendor_config {
|
||||
__le32 signature;
|
||||
__le16 total_len;
|
||||
struct rtl_vendor_config_entry entry[0];
|
||||
} __packed;
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_RTL)
|
||||
|
||||
struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
||||
const char *postfix);
|
||||
void btrtl_free(struct btrtl_device_info *btrtl_dev);
|
||||
int btrtl_download_firmware(struct hci_dev *hdev,
|
||||
struct btrtl_device_info *btrtl_dev);
|
||||
int btrtl_setup_realtek(struct hci_dev *hdev);
|
||||
int btrtl_get_uart_settings(struct hci_dev *hdev,
|
||||
struct btrtl_device_info *btrtl_dev,
|
||||
unsigned int *controller_baudrate,
|
||||
u32 *device_baudrate, bool *flow_control);
|
||||
|
||||
#else
|
||||
|
||||
static inline struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
||||
const char *postfix)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void btrtl_free(struct btrtl_device_info *btrtl_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int btrtl_download_firmware(struct hci_dev *hdev,
|
||||
struct btrtl_device_info *btrtl_dev)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int btrtl_setup_realtek(struct hci_dev *hdev)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int btrtl_get_uart_settings(struct hci_dev *hdev,
|
||||
struct btrtl_device_info *btrtl_dev,
|
||||
unsigned int *controller_baudrate,
|
||||
u32 *device_baudrate,
|
||||
bool *flow_control)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
#endif
|
||||
+67
-49
@@ -374,6 +374,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
|
||||
|
||||
/* Additional Realtek 8723DE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
|
||||
{ USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK },
|
||||
|
||||
/* Additional Realtek 8821AE Bluetooth devices */
|
||||
@@ -509,9 +510,10 @@ static inline void btusb_free_frags(struct btusb_data *data)
|
||||
static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
int err = 0;
|
||||
|
||||
spin_lock(&data->rxlock);
|
||||
spin_lock_irqsave(&data->rxlock, flags);
|
||||
skb = data->evt_skb;
|
||||
|
||||
while (count) {
|
||||
@@ -556,7 +558,7 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
|
||||
}
|
||||
|
||||
data->evt_skb = skb;
|
||||
spin_unlock(&data->rxlock);
|
||||
spin_unlock_irqrestore(&data->rxlock, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -564,9 +566,10 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
|
||||
static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
int err = 0;
|
||||
|
||||
spin_lock(&data->rxlock);
|
||||
spin_lock_irqsave(&data->rxlock, flags);
|
||||
skb = data->acl_skb;
|
||||
|
||||
while (count) {
|
||||
@@ -613,7 +616,7 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
|
||||
}
|
||||
|
||||
data->acl_skb = skb;
|
||||
spin_unlock(&data->rxlock);
|
||||
spin_unlock_irqrestore(&data->rxlock, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -621,9 +624,10 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
|
||||
static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
int err = 0;
|
||||
|
||||
spin_lock(&data->rxlock);
|
||||
spin_lock_irqsave(&data->rxlock, flags);
|
||||
skb = data->sco_skb;
|
||||
|
||||
while (count) {
|
||||
@@ -668,7 +672,7 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
|
||||
}
|
||||
|
||||
data->sco_skb = skb;
|
||||
spin_unlock(&data->rxlock);
|
||||
spin_unlock_irqrestore(&data->rxlock, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1066,6 +1070,7 @@ static void btusb_tx_complete(struct urb *urb)
|
||||
struct sk_buff *skb = urb->context;
|
||||
struct hci_dev *hdev = (struct hci_dev *)skb->dev;
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
unsigned long flags;
|
||||
|
||||
BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
|
||||
urb->actual_length);
|
||||
@@ -1079,9 +1084,9 @@ static void btusb_tx_complete(struct urb *urb)
|
||||
hdev->stat.err_tx++;
|
||||
|
||||
done:
|
||||
spin_lock(&data->txlock);
|
||||
spin_lock_irqsave(&data->txlock, flags);
|
||||
data->tx_in_flight--;
|
||||
spin_unlock(&data->txlock);
|
||||
spin_unlock_irqrestore(&data->txlock, flags);
|
||||
|
||||
kfree(urb->setup_packet);
|
||||
|
||||
@@ -1593,13 +1598,13 @@ static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
|
||||
ret = request_firmware(&fw, fwname, &hdev->dev);
|
||||
if (ret < 0) {
|
||||
if (ret == -EINVAL) {
|
||||
BT_ERR("%s Intel firmware file request failed (%d)",
|
||||
hdev->name, ret);
|
||||
bt_dev_err(hdev, "Intel firmware file request failed (%d)",
|
||||
ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BT_ERR("%s failed to open Intel firmware file: %s(%d)",
|
||||
hdev->name, fwname, ret);
|
||||
bt_dev_err(hdev, "failed to open Intel firmware file: %s (%d)",
|
||||
fwname, ret);
|
||||
|
||||
/* If the correct firmware patch file is not found, use the
|
||||
* default firmware patch file instead
|
||||
@@ -1607,8 +1612,8 @@ static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq",
|
||||
ver->hw_platform, ver->hw_variant);
|
||||
if (request_firmware(&fw, fwname, &hdev->dev) < 0) {
|
||||
BT_ERR("%s failed to open default Intel fw file: %s",
|
||||
hdev->name, fwname);
|
||||
bt_dev_err(hdev, "failed to open default fw file: %s",
|
||||
fwname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1637,7 +1642,7 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
|
||||
* process.
|
||||
*/
|
||||
if (remain > HCI_COMMAND_HDR_SIZE && *fw_ptr[0] != 0x01) {
|
||||
BT_ERR("%s Intel fw corrupted: invalid cmd read", hdev->name);
|
||||
bt_dev_err(hdev, "Intel fw corrupted: invalid cmd read");
|
||||
return -EINVAL;
|
||||
}
|
||||
(*fw_ptr)++;
|
||||
@@ -1651,7 +1656,7 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
|
||||
* of command parameter. If not, the firmware file is corrupted.
|
||||
*/
|
||||
if (remain < cmd->plen) {
|
||||
BT_ERR("%s Intel fw corrupted: invalid cmd len", hdev->name);
|
||||
bt_dev_err(hdev, "Intel fw corrupted: invalid cmd len");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@@ -1684,8 +1689,7 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
|
||||
remain -= sizeof(*evt);
|
||||
|
||||
if (remain < evt->plen) {
|
||||
BT_ERR("%s Intel fw corrupted: invalid evt len",
|
||||
hdev->name);
|
||||
bt_dev_err(hdev, "Intel fw corrupted: invalid evt len");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@@ -1699,15 +1703,15 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
|
||||
* file is corrupted.
|
||||
*/
|
||||
if (!evt || !evt_param || remain < 0) {
|
||||
BT_ERR("%s Intel fw corrupted: invalid evt read", hdev->name);
|
||||
bt_dev_err(hdev, "Intel fw corrupted: invalid evt read");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
skb = __hci_cmd_sync_ev(hdev, le16_to_cpu(cmd->opcode), cmd->plen,
|
||||
cmd_param, evt->evt, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s sending Intel patch command (0x%4.4x) failed (%ld)",
|
||||
hdev->name, cmd->opcode, PTR_ERR(skb));
|
||||
bt_dev_err(hdev, "sending Intel patch command (0x%4.4x) failed (%ld)",
|
||||
cmd->opcode, PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
@@ -1716,15 +1720,15 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
|
||||
* the contents of the event.
|
||||
*/
|
||||
if (skb->len != evt->plen) {
|
||||
BT_ERR("%s mismatch event length (opcode 0x%4.4x)", hdev->name,
|
||||
le16_to_cpu(cmd->opcode));
|
||||
bt_dev_err(hdev, "mismatch event length (opcode 0x%4.4x)",
|
||||
le16_to_cpu(cmd->opcode));
|
||||
kfree_skb(skb);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (memcmp(skb->data, evt_param, evt->plen)) {
|
||||
BT_ERR("%s mismatch event parameter (opcode 0x%4.4x)",
|
||||
hdev->name, le16_to_cpu(cmd->opcode));
|
||||
bt_dev_err(hdev, "mismatch event parameter (opcode 0x%4.4x)",
|
||||
le16_to_cpu(cmd->opcode));
|
||||
kfree_skb(skb);
|
||||
return -EFAULT;
|
||||
}
|
||||
@@ -1753,8 +1757,8 @@ static int btusb_setup_intel(struct hci_dev *hdev)
|
||||
*/
|
||||
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s sending initial HCI reset command failed (%ld)",
|
||||
hdev->name, PTR_ERR(skb));
|
||||
bt_dev_err(hdev, "sending initial HCI reset command failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
kfree_skb(skb);
|
||||
@@ -1890,7 +1894,7 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)
|
||||
struct hci_event_hdr *hdr;
|
||||
struct hci_ev_cmd_complete *evt;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_ATOMIC);
|
||||
skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -2084,8 +2088,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
* for now only accept this single value.
|
||||
*/
|
||||
if (ver.hw_platform != 0x37) {
|
||||
BT_ERR("%s: Unsupported Intel hardware platform (%u)",
|
||||
hdev->name, ver.hw_platform);
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)",
|
||||
ver.hw_platform);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -2104,8 +2108,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
case 0x14: /* QnJ, IcP */
|
||||
break;
|
||||
default:
|
||||
BT_ERR("%s: Unsupported Intel hardware variant (%u)",
|
||||
hdev->name, ver.hw_variant);
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
|
||||
ver.hw_variant);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -2134,8 +2138,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
* choice is to return an error and abort the device initialization.
|
||||
*/
|
||||
if (ver.fw_variant != 0x06) {
|
||||
BT_ERR("%s: Unsupported Intel firmware variant (%u)",
|
||||
hdev->name, ver.fw_variant);
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)",
|
||||
ver.fw_variant);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -2151,8 +2155,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
* that this bootloader does not send them, then abort the setup.
|
||||
*/
|
||||
if (params.limited_cce != 0x00) {
|
||||
BT_ERR("%s: Unsupported Intel firmware loading method (%u)",
|
||||
hdev->name, params.limited_cce);
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)",
|
||||
params.limited_cce);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -2202,14 +2206,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
break;
|
||||
default:
|
||||
BT_ERR("%s: Unsupported Intel firmware naming", hdev->name);
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware naming");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = request_firmware(&fw, fwname, &hdev->dev);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to load Intel firmware file (%d)",
|
||||
hdev->name, err);
|
||||
bt_dev_err(hdev, "Failed to load Intel firmware file (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -2235,13 +2238,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
break;
|
||||
default:
|
||||
BT_ERR("%s: Unsupported Intel firmware naming", hdev->name);
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware naming");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fw->size < 644) {
|
||||
BT_ERR("%s: Invalid size of firmware file (%zu)",
|
||||
hdev->name, fw->size);
|
||||
bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
|
||||
fw->size);
|
||||
err = -EBADF;
|
||||
goto done;
|
||||
}
|
||||
@@ -2272,18 +2275,18 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
TASK_INTERRUPTIBLE,
|
||||
msecs_to_jiffies(5000));
|
||||
if (err == -EINTR) {
|
||||
BT_ERR("%s: Firmware loading interrupted", hdev->name);
|
||||
bt_dev_err(hdev, "Firmware loading interrupted");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
BT_ERR("%s: Firmware loading timeout", hdev->name);
|
||||
bt_dev_err(hdev, "Firmware loading timeout");
|
||||
err = -ETIMEDOUT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) {
|
||||
BT_ERR("%s: Firmware loading failed", hdev->name);
|
||||
bt_dev_err(hdev, "Firmware loading failed");
|
||||
err = -ENOEXEC;
|
||||
goto done;
|
||||
}
|
||||
@@ -2322,12 +2325,12 @@ done:
|
||||
msecs_to_jiffies(1000));
|
||||
|
||||
if (err == -EINTR) {
|
||||
BT_ERR("%s: Device boot interrupted", hdev->name);
|
||||
bt_dev_err(hdev, "Device boot interrupted");
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
BT_ERR("%s: Device boot timeout", hdev->name);
|
||||
bt_dev_err(hdev, "Device boot timeout");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@@ -2364,6 +2367,22 @@ static int btusb_shutdown_intel(struct hci_dev *hdev)
|
||||
struct sk_buff *skb;
|
||||
long ret;
|
||||
|
||||
/* In the shutdown sequence where Bluetooth is turned off followed
|
||||
* by WiFi being turned off, turning WiFi back on causes issue with
|
||||
* the RF calibration.
|
||||
*
|
||||
* To ensure that any RF activity has been stopped, issue HCI Reset
|
||||
* command to clear all ongoing activity including advertising,
|
||||
* scanning etc.
|
||||
*/
|
||||
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
ret = PTR_ERR(skb);
|
||||
bt_dev_err(hdev, "HCI reset during shutdown failed");
|
||||
return ret;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Some platforms have an issue with BT LED when the interface is
|
||||
* down or BT radio is turned off, which takes 5 seconds to BT LED
|
||||
* goes off. This command turns off the BT LED immediately.
|
||||
@@ -2371,8 +2390,7 @@ static int btusb_shutdown_intel(struct hci_dev *hdev)
|
||||
skb = __hci_cmd_sync(hdev, 0xfc3f, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
ret = PTR_ERR(skb);
|
||||
BT_ERR("%s: turning off Intel device LED failed (%ld)",
|
||||
hdev->name, ret);
|
||||
bt_dev_err(hdev, "turning off Intel device LED failed");
|
||||
return ret;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
|
||||
+197
-5
@@ -21,13 +21,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/serdev.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#include "btrtl.h"
|
||||
#include "hci_uart.h"
|
||||
|
||||
#define HCI_3WIRE_ACK_PKT 0
|
||||
@@ -65,6 +70,9 @@ enum {
|
||||
};
|
||||
|
||||
struct h5 {
|
||||
/* Must be the first member, hci_serdev.c expects this. */
|
||||
struct hci_uart serdev_hu;
|
||||
|
||||
struct sk_buff_head unack; /* Unack'ed packets queue */
|
||||
struct sk_buff_head rel; /* Reliable packets queue */
|
||||
struct sk_buff_head unrel; /* Unreliable packets queue */
|
||||
@@ -95,6 +103,19 @@ struct h5 {
|
||||
H5_SLEEPING,
|
||||
H5_WAKING_UP,
|
||||
} sleep;
|
||||
|
||||
const struct h5_vnd *vnd;
|
||||
const char *id;
|
||||
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct gpio_desc *device_wake_gpio;
|
||||
};
|
||||
|
||||
struct h5_vnd {
|
||||
int (*setup)(struct h5 *h5);
|
||||
void (*open)(struct h5 *h5);
|
||||
void (*close)(struct h5 *h5);
|
||||
const struct acpi_gpio_mapping *acpi_gpio_map;
|
||||
};
|
||||
|
||||
static void h5_reset_rx(struct h5 *h5);
|
||||
@@ -193,9 +214,13 @@ static int h5_open(struct hci_uart *hu)
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
h5 = kzalloc(sizeof(*h5), GFP_KERNEL);
|
||||
if (!h5)
|
||||
return -ENOMEM;
|
||||
if (hu->serdev) {
|
||||
h5 = serdev_device_get_drvdata(hu->serdev);
|
||||
} else {
|
||||
h5 = kzalloc(sizeof(*h5), GFP_KERNEL);
|
||||
if (!h5)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hu->priv = h5;
|
||||
h5->hu = hu;
|
||||
@@ -210,6 +235,9 @@ static int h5_open(struct hci_uart *hu)
|
||||
|
||||
h5->tx_win = H5_TX_WIN_MAX;
|
||||
|
||||
if (h5->vnd && h5->vnd->open)
|
||||
h5->vnd->open(h5);
|
||||
|
||||
set_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags);
|
||||
|
||||
/* Send initial sync request */
|
||||
@@ -229,7 +257,21 @@ static int h5_close(struct hci_uart *hu)
|
||||
skb_queue_purge(&h5->rel);
|
||||
skb_queue_purge(&h5->unrel);
|
||||
|
||||
kfree(h5);
|
||||
if (h5->vnd && h5->vnd->close)
|
||||
h5->vnd->close(h5);
|
||||
|
||||
if (!hu->serdev)
|
||||
kfree(h5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h5_setup(struct hci_uart *hu)
|
||||
{
|
||||
struct h5 *h5 = hu->priv;
|
||||
|
||||
if (h5->vnd && h5->vnd->setup)
|
||||
return h5->vnd->setup(h5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -744,18 +786,168 @@ static const struct hci_uart_proto h5p = {
|
||||
.name = "Three-wire (H5)",
|
||||
.open = h5_open,
|
||||
.close = h5_close,
|
||||
.setup = h5_setup,
|
||||
.recv = h5_recv,
|
||||
.enqueue = h5_enqueue,
|
||||
.dequeue = h5_dequeue,
|
||||
.flush = h5_flush,
|
||||
};
|
||||
|
||||
static int h5_serdev_probe(struct serdev_device *serdev)
|
||||
{
|
||||
const struct acpi_device_id *match;
|
||||
struct device *dev = &serdev->dev;
|
||||
struct h5 *h5;
|
||||
|
||||
h5 = devm_kzalloc(dev, sizeof(*h5), GFP_KERNEL);
|
||||
if (!h5)
|
||||
return -ENOMEM;
|
||||
|
||||
set_bit(HCI_UART_RESET_ON_INIT, &h5->serdev_hu.flags);
|
||||
|
||||
h5->hu = &h5->serdev_hu;
|
||||
h5->serdev_hu.serdev = serdev;
|
||||
serdev_device_set_drvdata(serdev, h5);
|
||||
|
||||
if (has_acpi_companion(dev)) {
|
||||
match = acpi_match_device(dev->driver->acpi_match_table, dev);
|
||||
if (!match)
|
||||
return -ENODEV;
|
||||
|
||||
h5->vnd = (const struct h5_vnd *)match->driver_data;
|
||||
h5->id = (char *)match->id;
|
||||
|
||||
if (h5->vnd->acpi_gpio_map)
|
||||
devm_acpi_dev_add_driver_gpios(dev,
|
||||
h5->vnd->acpi_gpio_map);
|
||||
}
|
||||
|
||||
h5->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(h5->enable_gpio))
|
||||
return PTR_ERR(h5->enable_gpio);
|
||||
|
||||
h5->device_wake_gpio = devm_gpiod_get_optional(dev, "device-wake",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(h5->device_wake_gpio))
|
||||
return PTR_ERR(h5->device_wake_gpio);
|
||||
|
||||
return hci_uart_register_device(&h5->serdev_hu, &h5p);
|
||||
}
|
||||
|
||||
static void h5_serdev_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct h5 *h5 = serdev_device_get_drvdata(serdev);
|
||||
|
||||
hci_uart_unregister_device(&h5->serdev_hu);
|
||||
}
|
||||
|
||||
static int h5_btrtl_setup(struct h5 *h5)
|
||||
{
|
||||
struct btrtl_device_info *btrtl_dev;
|
||||
struct sk_buff *skb;
|
||||
__le32 baudrate_data;
|
||||
u32 device_baudrate;
|
||||
unsigned int controller_baudrate;
|
||||
bool flow_control;
|
||||
int err;
|
||||
|
||||
btrtl_dev = btrtl_initialize(h5->hu->hdev, h5->id);
|
||||
if (IS_ERR(btrtl_dev))
|
||||
return PTR_ERR(btrtl_dev);
|
||||
|
||||
err = btrtl_get_uart_settings(h5->hu->hdev, btrtl_dev,
|
||||
&controller_baudrate, &device_baudrate,
|
||||
&flow_control);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
baudrate_data = cpu_to_le32(device_baudrate);
|
||||
skb = __hci_cmd_sync(h5->hu->hdev, 0xfc17, sizeof(baudrate_data),
|
||||
&baudrate_data, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
rtl_dev_err(h5->hu->hdev, "set baud rate command failed\n");
|
||||
err = PTR_ERR(skb);
|
||||
goto out_free;
|
||||
} else {
|
||||
kfree_skb(skb);
|
||||
}
|
||||
/* Give the device some time to set up the new baudrate. */
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
serdev_device_set_baudrate(h5->hu->serdev, controller_baudrate);
|
||||
serdev_device_set_flow_control(h5->hu->serdev, flow_control);
|
||||
|
||||
err = btrtl_download_firmware(h5->hu->hdev, btrtl_dev);
|
||||
/* Give the device some time before the hci-core sends it a reset */
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
out_free:
|
||||
btrtl_free(btrtl_dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void h5_btrtl_open(struct h5 *h5)
|
||||
{
|
||||
/* Devices always start with these fixed parameters */
|
||||
serdev_device_set_flow_control(h5->hu->serdev, false);
|
||||
serdev_device_set_parity(h5->hu->serdev, SERDEV_PARITY_EVEN);
|
||||
serdev_device_set_baudrate(h5->hu->serdev, 115200);
|
||||
|
||||
/* The controller needs up to 500ms to wakeup */
|
||||
gpiod_set_value_cansleep(h5->enable_gpio, 1);
|
||||
gpiod_set_value_cansleep(h5->device_wake_gpio, 1);
|
||||
msleep(500);
|
||||
}
|
||||
|
||||
static void h5_btrtl_close(struct h5 *h5)
|
||||
{
|
||||
gpiod_set_value_cansleep(h5->device_wake_gpio, 0);
|
||||
gpiod_set_value_cansleep(h5->enable_gpio, 0);
|
||||
}
|
||||
|
||||
static const struct acpi_gpio_params btrtl_device_wake_gpios = { 0, 0, false };
|
||||
static const struct acpi_gpio_params btrtl_enable_gpios = { 1, 0, false };
|
||||
static const struct acpi_gpio_params btrtl_host_wake_gpios = { 2, 0, false };
|
||||
static const struct acpi_gpio_mapping acpi_btrtl_gpios[] = {
|
||||
{ "device-wake-gpios", &btrtl_device_wake_gpios, 1 },
|
||||
{ "enable-gpios", &btrtl_enable_gpios, 1 },
|
||||
{ "host-wake-gpios", &btrtl_host_wake_gpios, 1 },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct h5_vnd rtl_vnd = {
|
||||
.setup = h5_btrtl_setup,
|
||||
.open = h5_btrtl_open,
|
||||
.close = h5_btrtl_close,
|
||||
.acpi_gpio_map = acpi_btrtl_gpios,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id h5_acpi_match[] = {
|
||||
{ "OBDA8723", (kernel_ulong_t)&rtl_vnd },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, h5_acpi_match);
|
||||
#endif
|
||||
|
||||
static struct serdev_device_driver h5_serdev_driver = {
|
||||
.probe = h5_serdev_probe,
|
||||
.remove = h5_serdev_remove,
|
||||
.driver = {
|
||||
.name = "hci_uart_h5",
|
||||
.acpi_match_table = ACPI_PTR(h5_acpi_match),
|
||||
},
|
||||
};
|
||||
|
||||
int __init h5_init(void)
|
||||
{
|
||||
serdev_device_driver_register(&h5_serdev_driver);
|
||||
return hci_uart_register_proto(&h5p);
|
||||
}
|
||||
|
||||
int __exit h5_deinit(void)
|
||||
{
|
||||
serdev_device_driver_unregister(&h5_serdev_driver);
|
||||
return hci_uart_unregister_proto(&h5p);
|
||||
}
|
||||
@@ -458,7 +458,7 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)
|
||||
struct hci_event_hdr *hdr;
|
||||
struct hci_ev_cmd_complete *evt;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_ATOMIC);
|
||||
skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
+438
-68
File diff suppressed because it is too large.
Load diff
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* This file is part of Nokia H4P bluetooth driver
|
||||
*
|
||||
* Copyright (C) 2010 Nokia Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* 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.
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* struct hci_h4p_platform data - hci_h4p Platform data structure
|
||||
*/
|
||||
struct hci_h4p_platform_data {
|
||||
int chip_type;
|
||||
int bt_sysclk;
|
||||
unsigned int bt_wakeup_gpio;
|
||||
unsigned int host_wakeup_gpio;
|
||||
unsigned int reset_gpio;
|
||||
int reset_gpio_shared;
|
||||
unsigned int uart_irq;
|
||||
phys_addr_t uart_base;
|
||||
const char *uart_iclk;
|
||||
const char *uart_fclk;
|
||||
void (*set_pm_limits)(struct device *dev, bool set);
|
||||
};
|
||||
@@ -183,6 +183,15 @@ enum {
|
||||
* during the hdev->setup vendor callback.
|
||||
*/
|
||||
HCI_QUIRK_NON_PERSISTENT_DIAG,
|
||||
|
||||
/* When this quirk is set, setup() would be run after every
|
||||
* open() and not just after the first open().
|
||||
*
|
||||
* This quirk can be set before hci_register_dev is called or
|
||||
* during the hdev->setup vendor callback.
|
||||
*
|
||||
*/
|
||||
HCI_QUIRK_NON_PERSISTENT_SETUP,
|
||||
};
|
||||
|
||||
/* HCI device flags */
|
||||
@@ -291,6 +300,14 @@ enum {
|
||||
#define HCI_DH3 0x0800
|
||||
#define HCI_DH5 0x8000
|
||||
|
||||
/* HCI packet types inverted masks */
|
||||
#define HCI_2DH1 0x0002
|
||||
#define HCI_3DH1 0x0004
|
||||
#define HCI_2DH3 0x0100
|
||||
#define HCI_3DH3 0x0200
|
||||
#define HCI_2DH5 0x1000
|
||||
#define HCI_3DH5 0x2000
|
||||
|
||||
#define HCI_HV1 0x0020
|
||||
#define HCI_HV2 0x0040
|
||||
#define HCI_HV3 0x0080
|
||||
@@ -354,6 +371,8 @@ enum {
|
||||
#define LMP_PCONTROL 0x04
|
||||
#define LMP_TRANSPARENT 0x08
|
||||
|
||||
#define LMP_EDR_2M 0x02
|
||||
#define LMP_EDR_3M 0x04
|
||||
#define LMP_RSSI_INQ 0x40
|
||||
#define LMP_ESCO 0x80
|
||||
|
||||
@@ -361,7 +380,9 @@ enum {
|
||||
#define LMP_EV5 0x02
|
||||
#define LMP_NO_BREDR 0x20
|
||||
#define LMP_LE 0x40
|
||||
#define LMP_EDR_3SLOT 0x80
|
||||
|
||||
#define LMP_EDR_5SLOT 0x01
|
||||
#define LMP_SNIFF_SUBR 0x02
|
||||
#define LMP_PAUSE_ENC 0x04
|
||||
#define LMP_EDR_ESCO_2M 0x20
|
||||
@@ -398,7 +419,12 @@ enum {
|
||||
#define HCI_LE_SLAVE_FEATURES 0x08
|
||||
#define HCI_LE_PING 0x10
|
||||
#define HCI_LE_DATA_LEN_EXT 0x20
|
||||
#define HCI_LE_PHY_2M 0x01
|
||||
#define HCI_LE_PHY_CODED 0x08
|
||||
#define HCI_LE_EXT_ADV 0x10
|
||||
#define HCI_LE_EXT_SCAN_POLICY 0x80
|
||||
#define HCI_LE_PHY_2M 0x01
|
||||
#define HCI_LE_PHY_CODED 0x08
|
||||
#define HCI_LE_CHAN_SEL_ALG2 0x40
|
||||
|
||||
/* Connection modes */
|
||||
@@ -1490,6 +1516,14 @@ struct hci_cp_le_write_def_data_len {
|
||||
__le16 tx_time;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_CLEAR_RESOLV_LIST 0x2029
|
||||
|
||||
#define HCI_OP_LE_READ_RESOLV_LIST_SIZE 0x202a
|
||||
struct hci_rp_le_read_resolv_list_size {
|
||||
__u8 status;
|
||||
__u8 size;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_READ_MAX_DATA_LEN 0x202f
|
||||
struct hci_rp_le_read_max_data_len {
|
||||
__u8 status;
|
||||
@@ -1506,6 +1540,134 @@ struct hci_cp_le_set_default_phy {
|
||||
__u8 rx_phys;
|
||||
} __packed;
|
||||
|
||||
#define HCI_LE_SET_PHY_1M 0x01
|
||||
#define HCI_LE_SET_PHY_2M 0x02
|
||||
#define HCI_LE_SET_PHY_CODED 0x04
|
||||
|
||||
#define HCI_OP_LE_SET_EXT_SCAN_PARAMS 0x2041
|
||||
struct hci_cp_le_set_ext_scan_params {
|
||||
__u8 own_addr_type;
|
||||
__u8 filter_policy;
|
||||
__u8 scanning_phys;
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
#define LE_SCAN_PHY_1M 0x01
|
||||
#define LE_SCAN_PHY_2M 0x02
|
||||
#define LE_SCAN_PHY_CODED 0x04
|
||||
|
||||
struct hci_cp_le_scan_phy_params {
|
||||
__u8 type;
|
||||
__le16 interval;
|
||||
__le16 window;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_SET_EXT_SCAN_ENABLE 0x2042
|
||||
struct hci_cp_le_set_ext_scan_enable {
|
||||
__u8 enable;
|
||||
__u8 filter_dup;
|
||||
__le16 duration;
|
||||
__le16 period;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_EXT_CREATE_CONN 0x2043
|
||||
struct hci_cp_le_ext_create_conn {
|
||||
__u8 filter_policy;
|
||||
__u8 own_addr_type;
|
||||
__u8 peer_addr_type;
|
||||
bdaddr_t peer_addr;
|
||||
__u8 phys;
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct hci_cp_le_ext_conn_param {
|
||||
__le16 scan_interval;
|
||||
__le16 scan_window;
|
||||
__le16 conn_interval_min;
|
||||
__le16 conn_interval_max;
|
||||
__le16 conn_latency;
|
||||
__le16 supervision_timeout;
|
||||
__le16 min_ce_len;
|
||||
__le16 max_ce_len;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS 0x203b
|
||||
struct hci_rp_le_read_num_supported_adv_sets {
|
||||
__u8 status;
|
||||
__u8 num_of_sets;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_SET_EXT_ADV_PARAMS 0x2036
|
||||
struct hci_cp_le_set_ext_adv_params {
|
||||
__u8 handle;
|
||||
__le16 evt_properties;
|
||||
__u8 min_interval[3];
|
||||
__u8 max_interval[3];
|
||||
__u8 channel_map;
|
||||
__u8 own_addr_type;
|
||||
__u8 peer_addr_type;
|
||||
bdaddr_t peer_addr;
|
||||
__u8 filter_policy;
|
||||
__u8 tx_power;
|
||||
__u8 primary_phy;
|
||||
__u8 secondary_max_skip;
|
||||
__u8 secondary_phy;
|
||||
__u8 sid;
|
||||
__u8 notif_enable;
|
||||
} __packed;
|
||||
|
||||
#define HCI_ADV_PHY_1M 0X01
|
||||
#define HCI_ADV_PHY_2M 0x02
|
||||
#define HCI_ADV_PHY_CODED 0x03
|
||||
|
||||
struct hci_rp_le_set_ext_adv_params {
|
||||
__u8 status;
|
||||
__u8 tx_power;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_SET_EXT_ADV_ENABLE 0x2039
|
||||
struct hci_cp_le_set_ext_adv_enable {
|
||||
__u8 enable;
|
||||
__u8 num_of_sets;
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct hci_cp_ext_adv_set {
|
||||
__u8 handle;
|
||||
__le16 duration;
|
||||
__u8 max_events;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_SET_EXT_ADV_DATA 0x2037
|
||||
struct hci_cp_le_set_ext_adv_data {
|
||||
__u8 handle;
|
||||
__u8 operation;
|
||||
__u8 frag_pref;
|
||||
__u8 length;
|
||||
__u8 data[HCI_MAX_AD_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LE_SET_EXT_SCAN_RSP_DATA 0x2038
|
||||
struct hci_cp_le_set_ext_scan_rsp_data {
|
||||
__u8 handle;
|
||||
__u8 operation;
|
||||
__u8 frag_pref;
|
||||
__u8 length;
|
||||
__u8 data[HCI_MAX_AD_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define LE_SET_ADV_DATA_OP_COMPLETE 0x03
|
||||
|
||||
#define LE_SET_ADV_DATA_NO_FRAG 0x01
|
||||
|
||||
#define HCI_OP_LE_CLEAR_ADV_SETS 0x203d
|
||||
|
||||
#define HCI_OP_LE_SET_ADV_SET_RAND_ADDR 0x2035
|
||||
struct hci_cp_le_set_adv_set_rand_addr {
|
||||
__u8 handle;
|
||||
bdaddr_t bdaddr;
|
||||
} __packed;
|
||||
|
||||
/* ---- HCI Events ---- */
|
||||
#define HCI_EV_INQUIRY_COMPLETE 0x01
|
||||
|
||||
@@ -1893,6 +2055,23 @@ struct hci_ev_le_conn_complete {
|
||||
#define LE_ADV_SCAN_IND 0x02
|
||||
#define LE_ADV_NONCONN_IND 0x03
|
||||
#define LE_ADV_SCAN_RSP 0x04
|
||||
#define LE_ADV_INVALID 0x05
|
||||
|
||||
/* Legacy event types in extended adv report */
|
||||
#define LE_LEGACY_ADV_IND 0x0013
|
||||
#define LE_LEGACY_ADV_DIRECT_IND 0x0015
|
||||
#define LE_LEGACY_ADV_SCAN_IND 0x0012
|
||||
#define LE_LEGACY_NONCONN_IND 0x0010
|
||||
#define LE_LEGACY_SCAN_RSP_ADV 0x001b
|
||||
#define LE_LEGACY_SCAN_RSP_ADV_SCAN 0x001a
|
||||
|
||||
/* Extended Advertising event types */
|
||||
#define LE_EXT_ADV_NON_CONN_IND 0x0000
|
||||
#define LE_EXT_ADV_CONN_IND 0x0001
|
||||
#define LE_EXT_ADV_SCAN_IND 0x0002
|
||||
#define LE_EXT_ADV_DIRECT_IND 0x0004
|
||||
#define LE_EXT_ADV_SCAN_RSP 0x0008
|
||||
#define LE_EXT_ADV_LEGACY_PDU 0x0010
|
||||
|
||||
#define ADDR_LE_DEV_PUBLIC 0x00
|
||||
#define ADDR_LE_DEV_RANDOM 0x01
|
||||
@@ -1957,6 +2136,46 @@ struct hci_ev_le_direct_adv_info {
|
||||
__s8 rssi;
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_LE_EXT_ADV_REPORT 0x0d
|
||||
struct hci_ev_le_ext_adv_report {
|
||||
__le16 evt_type;
|
||||
__u8 bdaddr_type;
|
||||
bdaddr_t bdaddr;
|
||||
__u8 primary_phy;
|
||||
__u8 secondary_phy;
|
||||
__u8 sid;
|
||||
__u8 tx_power;
|
||||
__s8 rssi;
|
||||
__le16 interval;
|
||||
__u8 direct_addr_type;
|
||||
bdaddr_t direct_addr;
|
||||
__u8 length;
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_LE_ENHANCED_CONN_COMPLETE 0x0a
|
||||
struct hci_ev_le_enh_conn_complete {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
__u8 role;
|
||||
__u8 bdaddr_type;
|
||||
bdaddr_t bdaddr;
|
||||
bdaddr_t local_rpa;
|
||||
bdaddr_t peer_rpa;
|
||||
__le16 interval;
|
||||
__le16 latency;
|
||||
__le16 supervision_timeout;
|
||||
__u8 clk_accurancy;
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_LE_EXT_ADV_SET_TERM 0x12
|
||||
struct hci_evt_le_ext_adv_set_term {
|
||||
__u8 status;
|
||||
__u8 handle;
|
||||
__le16 conn_handle;
|
||||
__u8 num_evts;
|
||||
} __packed;
|
||||
|
||||
/* Internal events generated by Bluetooth stack */
|
||||
#define HCI_EV_STACK_INTERNAL 0xfd
|
||||
struct hci_ev_stack_internal {
|
||||
|
||||
@@ -171,6 +171,10 @@ struct adv_info {
|
||||
__u8 adv_data[HCI_MAX_AD_LENGTH];
|
||||
__u16 scan_rsp_len;
|
||||
__u8 scan_rsp_data[HCI_MAX_AD_LENGTH];
|
||||
__s8 tx_power;
|
||||
bdaddr_t random_addr;
|
||||
bool rpa_expired;
|
||||
struct delayed_work rpa_expired_cb;
|
||||
};
|
||||
|
||||
#define HCI_MAX_ADV_INSTANCES 5
|
||||
@@ -221,6 +225,8 @@ struct hci_dev {
|
||||
__u8 features[HCI_MAX_PAGES][8];
|
||||
__u8 le_features[8];
|
||||
__u8 le_white_list_size;
|
||||
__u8 le_resolv_list_size;
|
||||
__u8 le_num_of_adv_sets;
|
||||
__u8 le_states[8];
|
||||
__u8 commands[64];
|
||||
__u8 hci_ver;
|
||||
@@ -314,6 +320,9 @@ struct hci_dev {
|
||||
unsigned long sco_last_tx;
|
||||
unsigned long le_last_tx;
|
||||
|
||||
__u8 le_tx_def_phys;
|
||||
__u8 le_rx_def_phys;
|
||||
|
||||
struct workqueue_struct *workqueue;
|
||||
struct workqueue_struct *req_workqueue;
|
||||
|
||||
@@ -367,6 +376,7 @@ struct hci_dev {
|
||||
struct list_head identity_resolving_keys;
|
||||
struct list_head remote_oob_data;
|
||||
struct list_head le_white_list;
|
||||
struct list_head le_resolv_list;
|
||||
struct list_head le_conn_params;
|
||||
struct list_head pend_le_conns;
|
||||
struct list_head pend_le_reports;
|
||||
@@ -1106,6 +1116,7 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
|
||||
u16 scan_rsp_len, u8 *scan_rsp_data,
|
||||
u16 timeout, u16 duration);
|
||||
int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance);
|
||||
void hci_adv_instances_set_rpa_expired(struct hci_dev *hdev, bool rpa_expired);
|
||||
|
||||
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
|
||||
@@ -1136,6 +1147,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
|
||||
#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_TX_PWR)
|
||||
#define lmp_ext_feat_capable(dev) ((dev)->features[0][7] & LMP_EXTFEATURES)
|
||||
#define lmp_transp_capable(dev) ((dev)->features[0][2] & LMP_TRANSPARENT)
|
||||
#define lmp_edr_2m_capable(dev) ((dev)->features[0][3] & LMP_EDR_2M)
|
||||
#define lmp_edr_3m_capable(dev) ((dev)->features[0][3] & LMP_EDR_3M)
|
||||
#define lmp_edr_3slot_capable(dev) ((dev)->features[0][4] & LMP_EDR_3SLOT)
|
||||
#define lmp_edr_5slot_capable(dev) ((dev)->features[0][5] & LMP_EDR_5SLOT)
|
||||
|
||||
/* ----- Extended LMP capabilities ----- */
|
||||
#define lmp_csb_master_capable(dev) ((dev)->features[2][0] & LMP_CSB_MASTER)
|
||||
@@ -1156,6 +1171,24 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
|
||||
#define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \
|
||||
hci_dev_test_flag(dev, HCI_SC_ENABLED))
|
||||
|
||||
#define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \
|
||||
((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M))
|
||||
|
||||
#define scan_2m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_2M) || \
|
||||
((dev)->le_rx_def_phys & HCI_LE_SET_PHY_2M))
|
||||
|
||||
#define scan_coded(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_CODED) || \
|
||||
((dev)->le_rx_def_phys & HCI_LE_SET_PHY_CODED))
|
||||
|
||||
/* Use ext scanning if set ext scan param and ext scan enable is supported */
|
||||
#define use_ext_scan(dev) (((dev)->commands[37] & 0x20) && \
|
||||
((dev)->commands[37] & 0x40))
|
||||
/* Use ext create connection if command is supported */
|
||||
#define use_ext_conn(dev) ((dev)->commands[37] & 0x80)
|
||||
|
||||
/* Extended advertising support */
|
||||
#define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV))
|
||||
|
||||
/* ----- HCI protocols ----- */
|
||||
#define HCI_PROTO_DEFER 0x01
|
||||
|
||||
@@ -1529,6 +1562,7 @@ void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev,
|
||||
u8 instance);
|
||||
void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
|
||||
u8 instance);
|
||||
int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
|
||||
|
||||
u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
|
||||
u16 to_multiplier);
|
||||
|
||||
@@ -101,6 +101,7 @@ struct mgmt_rp_read_index_list {
|
||||
#define MGMT_SETTING_PRIVACY 0x00002000
|
||||
#define MGMT_SETTING_CONFIGURATION 0x00004000
|
||||
#define MGMT_SETTING_STATIC_ADDRESS 0x00008000
|
||||
#define MGMT_SETTING_PHY_CONFIGURATION 0x00010000
|
||||
|
||||
#define MGMT_OP_READ_INFO 0x0004
|
||||
#define MGMT_READ_INFO_SIZE 0
|
||||
@@ -561,6 +562,12 @@ struct mgmt_rp_add_advertising {
|
||||
#define MGMT_ADV_FLAG_TX_POWER BIT(4)
|
||||
#define MGMT_ADV_FLAG_APPEARANCE BIT(5)
|
||||
#define MGMT_ADV_FLAG_LOCAL_NAME BIT(6)
|
||||
#define MGMT_ADV_FLAG_SEC_1M BIT(7)
|
||||
#define MGMT_ADV_FLAG_SEC_2M BIT(8)
|
||||
#define MGMT_ADV_FLAG_SEC_CODED BIT(9)
|
||||
|
||||
#define MGMT_ADV_FLAG_SEC_MASK (MGMT_ADV_FLAG_SEC_1M | MGMT_ADV_FLAG_SEC_2M | \
|
||||
MGMT_ADV_FLAG_SEC_CODED)
|
||||
|
||||
#define MGMT_OP_REMOVE_ADVERTISING 0x003F
|
||||
struct mgmt_cp_remove_advertising {
|
||||
@@ -604,6 +611,49 @@ struct mgmt_cp_set_appearance {
|
||||
} __packed;
|
||||
#define MGMT_SET_APPEARANCE_SIZE 2
|
||||
|
||||
#define MGMT_OP_GET_PHY_CONFIGURATION 0x0044
|
||||
struct mgmt_rp_get_phy_confguration {
|
||||
__le32 supported_phys;
|
||||
__le32 configurable_phys;
|
||||
__le32 selected_phys;
|
||||
} __packed;
|
||||
#define MGMT_GET_PHY_CONFIGURATION_SIZE 0
|
||||
|
||||
#define MGMT_PHY_BR_1M_1SLOT 0x00000001
|
||||
#define MGMT_PHY_BR_1M_3SLOT 0x00000002
|
||||
#define MGMT_PHY_BR_1M_5SLOT 0x00000004
|
||||
#define MGMT_PHY_EDR_2M_1SLOT 0x00000008
|
||||
#define MGMT_PHY_EDR_2M_3SLOT 0x00000010
|
||||
#define MGMT_PHY_EDR_2M_5SLOT 0x00000020
|
||||
#define MGMT_PHY_EDR_3M_1SLOT 0x00000040
|
||||
#define MGMT_PHY_EDR_3M_3SLOT 0x00000080
|
||||
#define MGMT_PHY_EDR_3M_5SLOT 0x00000100
|
||||
#define MGMT_PHY_LE_1M_TX 0x00000200
|
||||
#define MGMT_PHY_LE_1M_RX 0x00000400
|
||||
#define MGMT_PHY_LE_2M_TX 0x00000800
|
||||
#define MGMT_PHY_LE_2M_RX 0x00001000
|
||||
#define MGMT_PHY_LE_CODED_TX 0x00002000
|
||||
#define MGMT_PHY_LE_CODED_RX 0x00004000
|
||||
|
||||
#define MGMT_PHY_BREDR_MASK (MGMT_PHY_BR_1M_1SLOT | MGMT_PHY_BR_1M_3SLOT | \
|
||||
MGMT_PHY_BR_1M_5SLOT | MGMT_PHY_EDR_2M_1SLOT | \
|
||||
MGMT_PHY_EDR_2M_3SLOT | MGMT_PHY_EDR_2M_5SLOT | \
|
||||
MGMT_PHY_EDR_3M_1SLOT | MGMT_PHY_EDR_3M_3SLOT | \
|
||||
MGMT_PHY_EDR_3M_5SLOT)
|
||||
#define MGMT_PHY_LE_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_1M_RX | \
|
||||
MGMT_PHY_LE_2M_TX | MGMT_PHY_LE_2M_RX | \
|
||||
MGMT_PHY_LE_CODED_TX | MGMT_PHY_LE_CODED_RX)
|
||||
#define MGMT_PHY_LE_TX_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_2M_TX | \
|
||||
MGMT_PHY_LE_CODED_TX)
|
||||
#define MGMT_PHY_LE_RX_MASK (MGMT_PHY_LE_1M_RX | MGMT_PHY_LE_2M_RX | \
|
||||
MGMT_PHY_LE_CODED_RX)
|
||||
|
||||
#define MGMT_OP_SET_PHY_CONFIGURATION 0x0045
|
||||
struct mgmt_cp_set_phy_confguration {
|
||||
__le32 selected_phys;
|
||||
} __packed;
|
||||
#define MGMT_SET_PHY_CONFIGURATION_SIZE 4
|
||||
|
||||
#define MGMT_EV_CMD_COMPLETE 0x0001
|
||||
struct mgmt_ev_cmd_complete {
|
||||
__le16 opcode;
|
||||
@@ -824,3 +874,8 @@ struct mgmt_ev_ext_info_changed {
|
||||
__le16 eir_len;
|
||||
__u8 eir[0];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_PHY_CONFIGURATION_CHANGED 0x0026
|
||||
struct mgmt_ev_phy_configuration_changed {
|
||||
__le32 selected_phys;
|
||||
} __packed;
|
||||
@@ -770,6 +770,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev,
|
||||
hdr.hop_limit, &hdr.daddr);
|
||||
|
||||
skb_push(skb, sizeof(hdr));
|
||||
skb_reset_mac_header(skb);
|
||||
skb_reset_network_header(skb);
|
||||
skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ void bt_accept_enqueue(struct sock *parent, struct sock *sk)
|
||||
BT_DBG("parent %p, sk %p", parent, sk);
|
||||
|
||||
sock_hold(sk);
|
||||
lock_sock(sk);
|
||||
lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
|
||||
list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
|
||||
bt_sk(sk)->parent = parent;
|
||||
release_sock(sk);
|
||||
|
||||
Loaded 20 of 29 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user