Commit ca424b20 authored by John W. Linville's avatar John W. Linville

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents 5c4d5e81 6fea7ad1
...@@ -30,8 +30,8 @@ config BT_HCIUART ...@@ -30,8 +30,8 @@ config BT_HCIUART
help help
Bluetooth HCI UART driver. Bluetooth HCI UART driver.
This driver is required if you want to use Bluetooth devices with This driver is required if you want to use Bluetooth devices with
serial port interface. You will also need this driver if you have serial port interface. You will also need this driver if you have
UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card
adapter and BrainBoxes Bluetooth PC Card. adapter and BrainBoxes Bluetooth PC Card.
Say Y here to compile support for Bluetooth UART devices into the Say Y here to compile support for Bluetooth UART devices into the
...@@ -41,9 +41,9 @@ config BT_HCIUART_H4 ...@@ -41,9 +41,9 @@ config BT_HCIUART_H4
bool "UART (H4) protocol support" bool "UART (H4) protocol support"
depends on BT_HCIUART depends on BT_HCIUART
help help
UART (H4) is serial protocol for communication between Bluetooth UART (H4) is serial protocol for communication between Bluetooth
device and host. This protocol is required for most Bluetooth devices device and host. This protocol is required for most Bluetooth devices
with UART interface, including PCMCIA and CF cards. with UART interface, including PCMCIA and CF cards.
Say Y here to compile support for HCI UART (H4) protocol. Say Y here to compile support for HCI UART (H4) protocol.
...@@ -52,7 +52,7 @@ config BT_HCIUART_BCSP ...@@ -52,7 +52,7 @@ config BT_HCIUART_BCSP
depends on BT_HCIUART depends on BT_HCIUART
select BITREVERSE select BITREVERSE
help help
BCSP (BlueCore Serial Protocol) is serial protocol for communication BCSP (BlueCore Serial Protocol) is serial protocol for communication
between Bluetooth device and host. This protocol is required for non between Bluetooth device and host. This protocol is required for non
USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and
CF cards. CF cards.
......
...@@ -103,6 +103,7 @@ static const struct usb_device_id ath3k_table[] = { ...@@ -103,6 +103,7 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x13d3, 0x3393) }, { USB_DEVICE(0x13d3, 0x3393) },
{ USB_DEVICE(0x13d3, 0x3402) }, { USB_DEVICE(0x13d3, 0x3402) },
{ USB_DEVICE(0x13d3, 0x3432) },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) }, { USB_DEVICE(0x0489, 0xE02C) },
...@@ -152,6 +153,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { ...@@ -152,6 +153,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU22 with sflash firmware */ /* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
...@@ -288,10 +290,10 @@ static int ath3k_load_fwfile(struct usb_device *udev, ...@@ -288,10 +290,10 @@ static int ath3k_load_fwfile(struct usb_device *udev,
sent += size; sent += size;
count -= size; count -= size;
pipe = usb_sndbulkpipe(udev, 0x02);
while (count) { while (count) {
size = min_t(uint, count, BULK_SIZE); size = min_t(uint, count, BULK_SIZE);
pipe = usb_sndbulkpipe(udev, 0x02);
memcpy(send_buf, firmware->data + sent, size); memcpy(send_buf, firmware->data + sent, size);
err = usb_bulk_msg(udev, pipe, send_buf, size, err = usb_bulk_msg(udev, pipe, send_buf, size,
......
...@@ -68,6 +68,7 @@ struct btmrvl_adapter { ...@@ -68,6 +68,7 @@ struct btmrvl_adapter {
u8 hs_state; u8 hs_state;
u8 wakeup_tries; u8 wakeup_tries;
wait_queue_head_t cmd_wait_q; wait_queue_head_t cmd_wait_q;
wait_queue_head_t event_hs_wait_q;
u8 cmd_complete; u8 cmd_complete;
bool is_suspended; bool is_suspended;
}; };
...@@ -89,6 +90,7 @@ struct btmrvl_private { ...@@ -89,6 +90,7 @@ struct btmrvl_private {
#define MRVL_VENDOR_PKT 0xFE #define MRVL_VENDOR_PKT 0xFE
/* Vendor specific Bluetooth commands */ /* Vendor specific Bluetooth commands */
#define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03
#define BT_CMD_AUTO_SLEEP_MODE 0xFC23 #define BT_CMD_AUTO_SLEEP_MODE 0xFC23
#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59 #define BT_CMD_HOST_SLEEP_CONFIG 0xFC59
#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A #define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A
...@@ -143,6 +145,7 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb); ...@@ -143,6 +145,7 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd); int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd);
int btmrvl_pscan_window_reporting(struct btmrvl_private *priv, u8 subcmd);
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv); int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
int btmrvl_enable_ps(struct btmrvl_private *priv); int btmrvl_enable_ps(struct btmrvl_private *priv);
int btmrvl_prepare_command(struct btmrvl_private *priv); int btmrvl_prepare_command(struct btmrvl_private *priv);
......
...@@ -114,6 +114,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) ...@@ -114,6 +114,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
adapter->hs_state = HS_ACTIVATED; adapter->hs_state = HS_ACTIVATED;
if (adapter->psmode) if (adapter->psmode)
adapter->ps_state = PS_SLEEP; adapter->ps_state = PS_SLEEP;
wake_up_interruptible(&adapter->event_hs_wait_q);
BT_DBG("HS ACTIVATED!"); BT_DBG("HS ACTIVATED!");
} else { } else {
BT_DBG("HS Enable failed"); BT_DBG("HS Enable failed");
...@@ -214,6 +215,23 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd) ...@@ -214,6 +215,23 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd)
} }
EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
int btmrvl_pscan_window_reporting(struct btmrvl_private *priv, u8 subcmd)
{
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
int ret;
if (!card->support_pscan_win_report)
return 0;
ret = btmrvl_send_sync_cmd(priv, BT_CMD_PSCAN_WIN_REPORT_ENABLE,
&subcmd, 1);
if (ret)
BT_ERR("PSCAN_WIN_REPORT_ENABLE command failed: %#x", ret);
return ret;
}
EXPORT_SYMBOL_GPL(btmrvl_pscan_window_reporting);
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv) int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)
{ {
int ret; int ret;
...@@ -253,11 +271,31 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps); ...@@ -253,11 +271,31 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
int btmrvl_enable_hs(struct btmrvl_private *priv) int btmrvl_enable_hs(struct btmrvl_private *priv)
{ {
struct btmrvl_adapter *adapter = priv->adapter;
int ret; int ret;
ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0); ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
if (ret) if (ret) {
BT_ERR("Host sleep enable command failed\n"); BT_ERR("Host sleep enable command failed\n");
return ret;
}
ret = wait_event_interruptible_timeout(adapter->event_hs_wait_q,
adapter->hs_state,
msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED));
if (ret < 0) {
BT_ERR("event_hs_wait_q terminated (%d): %d,%d,%d",
ret, adapter->hs_state, adapter->ps_state,
adapter->wakeup_tries);
} else if (!ret) {
BT_ERR("hs_enable timeout: %d,%d,%d", adapter->hs_state,
adapter->ps_state, adapter->wakeup_tries);
ret = -ETIMEDOUT;
} else {
BT_DBG("host sleep enabled: %d,%d,%d", adapter->hs_state,
adapter->ps_state, adapter->wakeup_tries);
ret = 0;
}
return ret; return ret;
} }
...@@ -358,6 +396,7 @@ static void btmrvl_init_adapter(struct btmrvl_private *priv) ...@@ -358,6 +396,7 @@ static void btmrvl_init_adapter(struct btmrvl_private *priv)
} }
init_waitqueue_head(&priv->adapter->cmd_wait_q); init_waitqueue_head(&priv->adapter->cmd_wait_q);
init_waitqueue_head(&priv->adapter->event_hs_wait_q);
} }
static void btmrvl_free_adapter(struct btmrvl_private *priv) static void btmrvl_free_adapter(struct btmrvl_private *priv)
...@@ -489,6 +528,8 @@ static int btmrvl_setup(struct hci_dev *hdev) ...@@ -489,6 +528,8 @@ static int btmrvl_setup(struct hci_dev *hdev)
btmrvl_cal_data_dt(priv); btmrvl_cal_data_dt(priv);
btmrvl_pscan_window_reporting(priv, 0x01);
priv->btmrvl_dev.psmode = 1; priv->btmrvl_dev.psmode = 1;
btmrvl_enable_ps(priv); btmrvl_enable_ps(priv);
...@@ -666,6 +707,7 @@ int btmrvl_remove_card(struct btmrvl_private *priv) ...@@ -666,6 +707,7 @@ int btmrvl_remove_card(struct btmrvl_private *priv)
hdev = priv->btmrvl_dev.hcidev; hdev = priv->btmrvl_dev.hcidev;
wake_up_interruptible(&priv->adapter->cmd_wait_q); wake_up_interruptible(&priv->adapter->cmd_wait_q);
wake_up_interruptible(&priv->adapter->event_hs_wait_q);
kthread_stop(priv->main_thread.task); kthread_stop(priv->main_thread.task);
......
...@@ -108,6 +108,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { ...@@ -108,6 +108,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin", .helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin", .firmware = "mrvl/sd8688.bin",
.reg = &btmrvl_reg_8688, .reg = &btmrvl_reg_8688,
.support_pscan_win_report = false,
.sd_blksz_fw_dl = 64, .sd_blksz_fw_dl = 64,
}; };
...@@ -115,6 +116,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { ...@@ -115,6 +116,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8787_uapsta.bin", .firmware = "mrvl/sd8787_uapsta.bin",
.reg = &btmrvl_reg_87xx, .reg = &btmrvl_reg_87xx,
.support_pscan_win_report = false,
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
...@@ -122,6 +124,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { ...@@ -122,6 +124,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8797_uapsta.bin", .firmware = "mrvl/sd8797_uapsta.bin",
.reg = &btmrvl_reg_87xx, .reg = &btmrvl_reg_87xx,
.support_pscan_win_report = false,
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
...@@ -129,6 +132,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { ...@@ -129,6 +132,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8897_uapsta.bin", .firmware = "mrvl/sd8897_uapsta.bin",
.reg = &btmrvl_reg_88xx, .reg = &btmrvl_reg_88xx,
.support_pscan_win_report = true,
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
...@@ -1067,6 +1071,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func, ...@@ -1067,6 +1071,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
card->firmware = data->firmware; card->firmware = data->firmware;
card->reg = data->reg; card->reg = data->reg;
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl; card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
card->support_pscan_win_report = data->support_pscan_win_report;
} }
if (btmrvl_sdio_register_dev(card) < 0) { if (btmrvl_sdio_register_dev(card) < 0) {
......
...@@ -89,6 +89,7 @@ struct btmrvl_sdio_card { ...@@ -89,6 +89,7 @@ struct btmrvl_sdio_card {
const char *helper; const char *helper;
const char *firmware; const char *firmware;
const struct btmrvl_sdio_card_reg *reg; const struct btmrvl_sdio_card_reg *reg;
bool support_pscan_win_report;
u16 sd_blksz_fw_dl; u16 sd_blksz_fw_dl;
u8 rx_unit; u8 rx_unit;
struct btmrvl_private *priv; struct btmrvl_private *priv;
...@@ -98,6 +99,7 @@ struct btmrvl_sdio_device { ...@@ -98,6 +99,7 @@ struct btmrvl_sdio_device {
const char *helper; const char *helper;
const char *firmware; const char *firmware;
const struct btmrvl_sdio_card_reg *reg; const struct btmrvl_sdio_card_reg *reg;
const bool support_pscan_win_report;
u16 sd_blksz_fw_dl; u16 sd_blksz_fw_dl;
}; };
......
...@@ -30,9 +30,6 @@ ...@@ -30,9 +30,6 @@
#define VERSION "0.6" #define VERSION "0.6"
static bool ignore_dga;
static bool ignore_csr;
static bool ignore_sniffer;
static bool disable_scofix; static bool disable_scofix;
static bool force_scofix; static bool force_scofix;
...@@ -49,7 +46,8 @@ static struct usb_driver btusb_driver; ...@@ -49,7 +46,8 @@ static struct usb_driver btusb_driver;
#define BTUSB_WRONG_SCO_MTU 0x40 #define BTUSB_WRONG_SCO_MTU 0x40
#define BTUSB_ATH3012 0x80 #define BTUSB_ATH3012 0x80
#define BTUSB_INTEL 0x100 #define BTUSB_INTEL 0x100
#define BTUSB_BCM_PATCHRAM 0x200 #define BTUSB_INTEL_BOOT 0x200
#define BTUSB_BCM_PATCHRAM 0x400
static const struct usb_device_id btusb_table[] = { static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */ /* Generic Bluetooth USB device */
...@@ -121,6 +119,10 @@ static const struct usb_device_id btusb_table[] = { ...@@ -121,6 +119,10 @@ static const struct usb_device_id btusb_table[] = {
/* IMC Networks - Broadcom based */ /* IMC Networks - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) }, { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
/* Intel Bluetooth USB Bootloader (RAM module) */
{ USB_DEVICE(0x8087, 0x0a5a),
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -175,6 +177,7 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -175,6 +177,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
...@@ -228,10 +231,12 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -228,10 +231,12 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
/* CSR BlueCore Bluetooth Sniffer */ /* CSR BlueCore Bluetooth Sniffer */
{ USB_DEVICE(0x0a12, 0x0002), .driver_info = BTUSB_SNIFFER }, { USB_DEVICE(0x0a12, 0x0002),
.driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
/* Frontline ComProbe Bluetooth Sniffer */ /* Frontline ComProbe Bluetooth Sniffer */
{ USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER }, { USB_DEVICE(0x16d3, 0x0002),
.driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
/* Intel Bluetooth device */ /* Intel Bluetooth device */
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
...@@ -1182,6 +1187,51 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev, ...@@ -1182,6 +1187,51 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
return 0; return 0;
} }
#define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
static int btusb_check_bdaddr_intel(struct hci_dev *hdev)
{
struct sk_buff *skb;
struct hci_rp_read_bd_addr *rp;
skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s reading Intel device address failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*rp)) {
BT_ERR("%s Intel device address length mismatch", hdev->name);
kfree_skb(skb);
return -EIO;
}
rp = (struct hci_rp_read_bd_addr *) skb->data;
if (rp->status) {
BT_ERR("%s Intel device address result failed (%02x)",
hdev->name, rp->status);
kfree_skb(skb);
return -bt_to_errno(rp->status);
}
/* For some Intel based controllers, the default Bluetooth device
* address 00:03:19:9E:8B:00 can be found. These controllers are
* fully operational, but have the danger of duplicate addresses
* and that in turn can cause problems with Bluetooth operation.
*/
if (!bacmp(&rp->bdaddr, BDADDR_INTEL)) {
BT_ERR("%s found Intel default device address (%pMR)",
hdev->name, &rp->bdaddr);
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
}
kfree_skb(skb);
return 0;
}
static int btusb_setup_intel(struct hci_dev *hdev) static int btusb_setup_intel(struct hci_dev *hdev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1254,6 +1304,7 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1254,6 +1304,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel device is already patched. patch num: %02x", BT_INFO("%s: Intel device is already patched. patch num: %02x",
hdev->name, ver->fw_patch_num); hdev->name, ver->fw_patch_num);
kfree_skb(skb); kfree_skb(skb);
btusb_check_bdaddr_intel(hdev);
return 0; return 0;
} }
...@@ -1266,6 +1317,7 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1266,6 +1317,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
fw = btusb_setup_intel_get_fw(hdev, ver); fw = btusb_setup_intel_get_fw(hdev, ver);
if (!fw) { if (!fw) {
kfree_skb(skb); kfree_skb(skb);
btusb_check_bdaddr_intel(hdev);
return 0; return 0;
} }
fw_ptr = fw->data; fw_ptr = fw->data;
...@@ -1345,6 +1397,7 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1345,6 +1397,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel Bluetooth firmware patch completed and activated", BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
hdev->name); hdev->name);
btusb_check_bdaddr_intel(hdev);
return 0; return 0;
exit_mfg_disable: exit_mfg_disable:
...@@ -1359,6 +1412,8 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1359,6 +1412,8 @@ static int btusb_setup_intel(struct hci_dev *hdev)
kfree_skb(skb); kfree_skb(skb);
BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name); BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
btusb_check_bdaddr_intel(hdev);
return 0; return 0;
exit_mfg_deactivate: exit_mfg_deactivate:
...@@ -1379,9 +1434,29 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1379,9 +1434,29 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated", BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
hdev->name); hdev->name);
btusb_check_bdaddr_intel(hdev);
return 0;
}
static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
struct sk_buff *skb;
long ret;
skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
BT_ERR("%s: changing Intel device address failed (%ld)",
hdev->name, ret);
return ret;
}
kfree_skb(skb);
return 0; return 0;
} }
#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
static int btusb_setup_bcm_patchram(struct hci_dev *hdev) static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
{ {
struct btusb_data *data = hci_get_drvdata(hdev); struct btusb_data *data = hci_get_drvdata(hdev);
...@@ -1395,6 +1470,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) ...@@ -1395,6 +1470,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
u16 opcode; u16 opcode;
struct sk_buff *skb; struct sk_buff *skb;
struct hci_rp_read_local_version *ver; struct hci_rp_read_local_version *ver;
struct hci_rp_read_bd_addr *bda;
long ret; long ret;
snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd", snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd",
...@@ -1404,8 +1480,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) ...@@ -1404,8 +1480,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
ret = request_firmware(&fw, fw_name, &hdev->dev); ret = request_firmware(&fw, fw_name, &hdev->dev);
if (ret < 0) { if (ret < 0) {
BT_INFO("%s: BCM: patch %s not found", hdev->name, BT_INFO("%s: BCM: patch %s not found", hdev->name, fw_name);
fw_name);
return 0; return 0;
} }
...@@ -1524,12 +1599,67 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) ...@@ -1524,12 +1599,67 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
ver->lmp_ver, ver->lmp_subver); ver->lmp_ver, ver->lmp_subver);
kfree_skb(skb); kfree_skb(skb);
/* Read BD Address */
skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
BT_ERR("%s: HCI_OP_READ_BD_ADDR failed (%ld)",
hdev->name, ret);
goto done;
}
if (skb->len != sizeof(*bda)) {
BT_ERR("%s: HCI_OP_READ_BD_ADDR event length mismatch",
hdev->name);
kfree_skb(skb);
ret = -EIO;
goto done;
}
bda = (struct hci_rp_read_bd_addr *) skb->data;
if (bda->status) {
BT_ERR("%s: HCI_OP_READ_BD_ADDR error status (%02x)",
hdev->name, bda->status);
kfree_skb(skb);
ret = -bt_to_errno(bda->status);
goto done;
}
/* The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller
* with no configured address.
*/
if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0)) {
BT_INFO("%s: BCM: using default device address (%pMR)",
hdev->name, &bda->bdaddr);
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
}
kfree_skb(skb);
done: done:
release_firmware(fw); release_firmware(fw);
return ret; return ret;
} }
static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
struct sk_buff *skb;
long ret;
skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
BT_ERR("%s: BCM: Change address command failed (%ld)",
hdev->name, ret);
return ret;
}
kfree_skb(skb);
return 0;
}
static int btusb_probe(struct usb_interface *intf, static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
...@@ -1554,15 +1684,6 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -1554,15 +1684,6 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info == BTUSB_IGNORE) if (id->driver_info == BTUSB_IGNORE)
return -ENODEV; return -ENODEV;
if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
return -ENODEV;
if (ignore_csr && id->driver_info & BTUSB_CSR)
return -ENODEV;
if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
return -ENODEV;
if (id->driver_info & BTUSB_ATH3012) { if (id->driver_info & BTUSB_ATH3012) {
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
...@@ -1635,11 +1756,18 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -1635,11 +1756,18 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info & BTUSB_BCM92035) if (id->driver_info & BTUSB_BCM92035)
hdev->setup = btusb_setup_bcm92035; hdev->setup = btusb_setup_bcm92035;
if (id->driver_info & BTUSB_BCM_PATCHRAM) if (id->driver_info & BTUSB_BCM_PATCHRAM) {
hdev->setup = btusb_setup_bcm_patchram; hdev->setup = btusb_setup_bcm_patchram;
hdev->set_bdaddr = btusb_set_bdaddr_bcm;
}
if (id->driver_info & BTUSB_INTEL) if (id->driver_info & BTUSB_INTEL) {
hdev->setup = btusb_setup_intel; hdev->setup = btusb_setup_intel;
hdev->set_bdaddr = btusb_set_bdaddr_intel;
}
if (id->driver_info & BTUSB_INTEL_BOOT)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
/* Interface numbers are hardcoded in the specification */ /* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1); data->isoc = usb_ifnum_to_if(data->udev, 1);
...@@ -1679,8 +1807,18 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -1679,8 +1807,18 @@ static int btusb_probe(struct usb_interface *intf,
/* New sniffer firmware has crippled HCI interface */ /* New sniffer firmware has crippled HCI interface */
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
}
data->isoc = NULL; if (id->driver_info & BTUSB_INTEL_BOOT) {
/* A bug in the bootloader causes that interrupt interface is
* only enabled after receiving SetInterface(0, AltSetting=0).
*/
err = usb_set_interface(data->udev, 0, 0);
if (err < 0) {
BT_ERR("failed to set interface 0, alt 0 %d", err);
hci_free_dev(hdev);
return err;
}
} }
if (data->isoc) { if (data->isoc) {
...@@ -1845,15 +1983,6 @@ static struct usb_driver btusb_driver = { ...@@ -1845,15 +1983,6 @@ static struct usb_driver btusb_driver = {
module_usb_driver(btusb_driver); module_usb_driver(btusb_driver);
module_param(ignore_dga, bool, 0644);
MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
module_param(ignore_csr, bool, 0644);
MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
module_param(ignore_sniffer, bool, 0644);
MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
module_param(disable_scofix, bool, 0644); module_param(disable_scofix, bool, 0644);
MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size"); MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
......
...@@ -355,10 +355,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu) ...@@ -355,10 +355,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu)
static int h5_rx_crc(struct hci_uart *hu, unsigned char c) static int h5_rx_crc(struct hci_uart *hu, unsigned char c)
{ {
struct h5 *h5 = hu->priv;
h5_complete_rx_pkt(hu); h5_complete_rx_pkt(hu);
h5_reset_rx(h5);
return 0; return 0;
} }
...@@ -373,7 +370,6 @@ static int h5_rx_payload(struct hci_uart *hu, unsigned char c) ...@@ -373,7 +370,6 @@ static int h5_rx_payload(struct hci_uart *hu, unsigned char c)
h5->rx_pending = 2; h5->rx_pending = 2;
} else { } else {
h5_complete_rx_pkt(hu); h5_complete_rx_pkt(hu);
h5_reset_rx(h5);
} }
return 0; return 0;
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#define VERSION "1.4" #define VERSION "1.5"
static bool amp; static bool amp;
...@@ -95,10 +95,21 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -95,10 +95,21 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0; return 0;
} }
static int vhci_create_device(struct vhci_data *data, __u8 dev_type) static int vhci_create_device(struct vhci_data *data, __u8 opcode)
{ {
struct hci_dev *hdev; struct hci_dev *hdev;
struct sk_buff *skb; struct sk_buff *skb;
__u8 dev_type;
/* bits 0-1 are dev_type (BR/EDR or AMP) */
dev_type = opcode & 0x03;
if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
return -EINVAL;
/* bits 2-5 are reserved (must be zero) */
if (opcode & 0x3c)
return -EINVAL;
skb = bt_skb_alloc(4, GFP_KERNEL); skb = bt_skb_alloc(4, GFP_KERNEL);
if (!skb) if (!skb)
...@@ -121,6 +132,14 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type) ...@@ -121,6 +132,14 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
hdev->flush = vhci_flush; hdev->flush = vhci_flush;
hdev->send = vhci_send_frame; hdev->send = vhci_send_frame;
/* bit 6 is for external configuration */
if (opcode & 0x40)
set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
/* bit 7 is for raw device */
if (opcode & 0x80)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device"); BT_ERR("Can't register HCI device");
hci_free_dev(hdev); hci_free_dev(hdev);
...@@ -132,7 +151,7 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type) ...@@ -132,7 +151,7 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
*skb_put(skb, 1) = 0xff; *skb_put(skb, 1) = 0xff;
*skb_put(skb, 1) = dev_type; *skb_put(skb, 1) = opcode;
put_unaligned_le16(hdev->id, skb_put(skb, 2)); put_unaligned_le16(hdev->id, skb_put(skb, 2));
skb_queue_tail(&data->readq, skb); skb_queue_tail(&data->readq, skb);
...@@ -146,7 +165,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, ...@@ -146,7 +165,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
{ {
size_t len = iov_length(iov, count); size_t len = iov_length(iov, count);
struct sk_buff *skb; struct sk_buff *skb;
__u8 pkt_type, dev_type; __u8 pkt_type, opcode;
unsigned long i; unsigned long i;
int ret; int ret;
...@@ -190,7 +209,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, ...@@ -190,7 +209,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
cancel_delayed_work_sync(&data->open_timeout); cancel_delayed_work_sync(&data->open_timeout);
dev_type = *((__u8 *) skb->data); opcode = *((__u8 *) skb->data);
skb_pull(skb, 1); skb_pull(skb, 1);
if (skb->len > 0) { if (skb->len > 0) {
...@@ -200,10 +219,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, ...@@ -200,10 +219,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
kfree_skb(skb); kfree_skb(skb);
if (dev_type != HCI_BREDR && dev_type != HCI_AMP) ret = vhci_create_device(data, opcode);
return -EINVAL;
ret = vhci_create_device(data, dev_type);
break; break;
default: default:
......
...@@ -260,15 +260,15 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock); ...@@ -260,15 +260,15 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
/* Skb helpers */ /* Skb helpers */
struct l2cap_ctrl { struct l2cap_ctrl {
unsigned int sframe:1, __u8 sframe:1,
poll:1, poll:1,
final:1, final:1,
fcs:1, fcs:1,
sar:2, sar:2,
super:2; super:2;
__u16 reqseq; __u16 reqseq;
__u16 txseq; __u16 txseq;
__u8 retries; __u8 retries;
}; };
struct hci_dev; struct hci_dev;
......
...@@ -81,10 +81,54 @@ ...@@ -81,10 +81,54 @@
/* HCI device quirks */ /* HCI device quirks */
enum { enum {
/* When this quirk is set, the HCI Reset command is send when
* closing the transport instead of when opening it.
*
* This quirk must be set before hci_register_dev is called.
*/
HCI_QUIRK_RESET_ON_CLOSE, HCI_QUIRK_RESET_ON_CLOSE,
/* When this quirk is set, the device is turned into a raw-only
* device and it will stay in unconfigured state.
*
* This quirk must be set before hci_register_dev is called.
*/
HCI_QUIRK_RAW_DEVICE, HCI_QUIRK_RAW_DEVICE,
/* When this quirk is set, the buffer sizes reported by
* HCI Read Buffer Size command are corrected if invalid.
*
* This quirk must be set before hci_register_dev is called.
*/
HCI_QUIRK_FIXUP_BUFFER_SIZE, HCI_QUIRK_FIXUP_BUFFER_SIZE,
/* When this quirk is set, then no stored link key handling
* is performed. This is mainly due to the fact that the
* HCI Delete Stored Link Key command is advertised, but
* not supported.
*
* This quirk must be set before hci_register_dev is called.
*/
HCI_QUIRK_BROKEN_STORED_LINK_KEY, HCI_QUIRK_BROKEN_STORED_LINK_KEY,
/* When this quirk is set, an external configuration step
* is required and will be indicated with the controller
* configuation.
*
* This quirk can be set before hci_register_dev is called or
* during the hdev->setup vendor callback.
*/
HCI_QUIRK_EXTERNAL_CONFIG,
/* When this quirk is set, the public Bluetooth address
* initially reported by HCI Read BD Address command
* is considered invalid. Controller configuration is
* required before this device can be used.
*
* This quirk can be set before hci_register_dev is called or
* during the hdev->setup vendor callback.
*/
HCI_QUIRK_INVALID_BDADDR,
}; };
/* HCI device flags */ /* HCI device flags */
...@@ -104,24 +148,34 @@ enum { ...@@ -104,24 +148,34 @@ enum {
HCI_RESET, HCI_RESET,
}; };
/* BR/EDR and/or LE controller flags: the flags defined here should represent
* states configured via debugfs for debugging and testing purposes only.
*/
enum {
HCI_DUT_MODE,
HCI_FORCE_SC,
HCI_FORCE_STATIC_ADDR,
};
/* /*
* BR/EDR and/or LE controller flags: the flags defined here should represent * BR/EDR and/or LE controller flags: the flags defined here should represent
* states from the controller. * states from the controller.
*/ */
enum { enum {
HCI_SETUP, HCI_SETUP,
HCI_CONFIG,
HCI_AUTO_OFF, HCI_AUTO_OFF,
HCI_RFKILLED, HCI_RFKILLED,
HCI_MGMT, HCI_MGMT,
HCI_PAIRABLE, HCI_PAIRABLE,
HCI_SERVICE_CACHE, HCI_SERVICE_CACHE,
HCI_DEBUG_KEYS, HCI_KEEP_DEBUG_KEYS,
HCI_DUT_MODE, HCI_USE_DEBUG_KEYS,
HCI_FORCE_SC,
HCI_FORCE_STATIC_ADDR,
HCI_UNREGISTER, HCI_UNREGISTER,
HCI_UNCONFIGURED,
HCI_USER_CHANNEL, HCI_USER_CHANNEL,
HCI_EXT_CONFIGURED,
HCI_LE_ADV,
HCI_LE_SCAN, HCI_LE_SCAN,
HCI_SSP_ENABLED, HCI_SSP_ENABLED,
HCI_SC_ENABLED, HCI_SC_ENABLED,
...@@ -139,7 +193,6 @@ enum { ...@@ -139,7 +193,6 @@ enum {
HCI_PERIODIC_INQ, HCI_PERIODIC_INQ,
HCI_FAST_CONNECTABLE, HCI_FAST_CONNECTABLE,
HCI_BREDR_ENABLED, HCI_BREDR_ENABLED,
HCI_6LOWPAN_ENABLED,
HCI_LE_SCAN_INTERRUPTED, HCI_LE_SCAN_INTERRUPTED,
}; };
...@@ -147,7 +200,7 @@ enum { ...@@ -147,7 +200,7 @@ enum {
* or the HCI device is closed. * or the HCI device is closed.
*/ */
#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \ #define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \
BIT(HCI_FAST_CONNECTABLE)) BIT(HCI_FAST_CONNECTABLE) | BIT(HCI_LE_ADV))
/* HCI ioctl defines */ /* HCI ioctl defines */
#define HCIDEVUP _IOW('H', 201, int) #define HCIDEVUP _IOW('H', 201, int)
...@@ -185,6 +238,7 @@ enum { ...@@ -185,6 +238,7 @@ enum {
#define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
#define HCI_POWER_OFF_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */ #define HCI_POWER_OFF_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */
#define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */ #define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */
#define HCI_LE_AUTOCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
/* HCI data types */ /* HCI data types */
#define HCI_COMMAND_PKT 0x01 #define HCI_COMMAND_PKT 0x01
...@@ -301,6 +355,10 @@ enum { ...@@ -301,6 +355,10 @@ enum {
#define LMP_HOST_LE_BREDR 0x04 #define LMP_HOST_LE_BREDR 0x04
#define LMP_HOST_SC 0x08 #define LMP_HOST_SC 0x08
/* LE features */
#define HCI_LE_CONN_PARAM_REQ_PROC 0x02
#define HCI_LE_PING 0x10
/* Connection modes */ /* Connection modes */
#define HCI_CM_ACTIVE 0x0000 #define HCI_CM_ACTIVE 0x0000
#define HCI_CM_HOLD 0x0001 #define HCI_CM_HOLD 0x0001
...@@ -347,17 +405,9 @@ enum { ...@@ -347,17 +405,9 @@ enum {
#define HCI_LK_CHANGED_COMBINATION 0x06 #define HCI_LK_CHANGED_COMBINATION 0x06
#define HCI_LK_UNAUTH_COMBINATION_P256 0x07 #define HCI_LK_UNAUTH_COMBINATION_P256 0x07
#define HCI_LK_AUTH_COMBINATION_P256 0x08 #define HCI_LK_AUTH_COMBINATION_P256 0x08
/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */
#define HCI_SMP_STK 0x80
#define HCI_SMP_STK_SLAVE 0x81
#define HCI_SMP_LTK 0x82
#define HCI_SMP_LTK_SLAVE 0x83
/* Long Term Key types */
#define HCI_LTK_UNAUTH 0x00
#define HCI_LTK_AUTH 0x01
/* ---- HCI Error Codes ---- */ /* ---- HCI Error Codes ---- */
#define HCI_ERROR_UNKNOWN_CONN_ID 0x02
#define HCI_ERROR_AUTH_FAILURE 0x05 #define HCI_ERROR_AUTH_FAILURE 0x05
#define HCI_ERROR_MEMORY_EXCEEDED 0x07 #define HCI_ERROR_MEMORY_EXCEEDED 0x07
#define HCI_ERROR_CONNECTION_TIMEOUT 0x08 #define HCI_ERROR_CONNECTION_TIMEOUT 0x08
...@@ -367,6 +417,7 @@ enum { ...@@ -367,6 +417,7 @@ enum {
#define HCI_ERROR_REMOTE_POWER_OFF 0x15 #define HCI_ERROR_REMOTE_POWER_OFF 0x15
#define HCI_ERROR_LOCAL_HOST_TERM 0x16 #define HCI_ERROR_LOCAL_HOST_TERM 0x16
#define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18 #define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18
#define HCI_ERROR_INVALID_LL_PARAMS 0x1E
#define HCI_ERROR_ADVERTISING_TIMEOUT 0x3c #define HCI_ERROR_ADVERTISING_TIMEOUT 0x3c
/* Flow control modes */ /* Flow control modes */
...@@ -536,6 +587,11 @@ struct hci_cp_read_remote_version { ...@@ -536,6 +587,11 @@ struct hci_cp_read_remote_version {
__le16 handle; __le16 handle;
} __packed; } __packed;
#define HCI_OP_READ_CLOCK_OFFSET 0x041f
struct hci_cp_read_clock_offset {
__le16 handle;
} __packed;
#define HCI_OP_SETUP_SYNC_CONN 0x0428 #define HCI_OP_SETUP_SYNC_CONN 0x0428
struct hci_cp_setup_sync_conn { struct hci_cp_setup_sync_conn {
__le16 handle; __le16 handle;
...@@ -1085,6 +1141,18 @@ struct hci_rp_read_rssi { ...@@ -1085,6 +1141,18 @@ struct hci_rp_read_rssi {
__s8 rssi; __s8 rssi;
} __packed; } __packed;
#define HCI_OP_READ_CLOCK 0x1407
struct hci_cp_read_clock {
__le16 handle;
__u8 which;
} __packed;
struct hci_rp_read_clock {
__u8 status;
__le16 handle;
__le32 clock;
__le16 accuracy;
} __packed;
#define HCI_OP_READ_LOCAL_AMP_INFO 0x1409 #define HCI_OP_READ_LOCAL_AMP_INFO 0x1409
struct hci_rp_read_local_amp_info { struct hci_rp_read_local_amp_info {
__u8 status; __u8 status;
...@@ -1291,6 +1359,23 @@ struct hci_rp_le_read_supported_states { ...@@ -1291,6 +1359,23 @@ struct hci_rp_le_read_supported_states {
__u8 le_states[8]; __u8 le_states[8];
} __packed; } __packed;
#define HCI_OP_LE_CONN_PARAM_REQ_REPLY 0x2020
struct hci_cp_le_conn_param_req_reply {
__le16 handle;
__le16 interval_min;
__le16 interval_max;
__le16 latency;
__le16 timeout;
__le16 min_ce_len;
__le16 max_ce_len;
} __packed;
#define HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY 0x2021
struct hci_cp_le_conn_param_req_neg_reply {
__le16 handle;
__u8 reason;
} __packed;
/* ---- HCI Events ---- */ /* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01 #define HCI_EV_INQUIRY_COMPLETE 0x01
...@@ -1670,6 +1755,15 @@ struct hci_ev_le_conn_complete { ...@@ -1670,6 +1755,15 @@ struct hci_ev_le_conn_complete {
__u8 clk_accurancy; __u8 clk_accurancy;
} __packed; } __packed;
#define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03
struct hci_ev_le_conn_update_complete {
__u8 status;
__le16 handle;
__le16 interval;
__le16 latency;
__le16 supervision_timeout;
} __packed;
#define HCI_EV_LE_LTK_REQ 0x05 #define HCI_EV_LE_LTK_REQ 0x05
struct hci_ev_le_ltk_req { struct hci_ev_le_ltk_req {
__le16 handle; __le16 handle;
...@@ -1677,6 +1771,15 @@ struct hci_ev_le_ltk_req { ...@@ -1677,6 +1771,15 @@ struct hci_ev_le_ltk_req {
__le16 ediv; __le16 ediv;
} __packed; } __packed;
#define HCI_EV_LE_REMOTE_CONN_PARAM_REQ 0x06
struct hci_ev_le_remote_conn_param_req {
__le16 handle;
__le16 interval_min;
__le16 interval_max;
__le16 latency;
__le16 timeout;
} __packed;
/* Advertising report event types */ /* Advertising report event types */
#define LE_ADV_IND 0x00 #define LE_ADV_IND 0x00
#define LE_ADV_DIRECT_IND 0x01 #define LE_ADV_DIRECT_IND 0x01
......
This diff is collapsed.
...@@ -137,7 +137,6 @@ struct l2cap_conninfo { ...@@ -137,7 +137,6 @@ struct l2cap_conninfo {
#define L2CAP_FC_L2CAP 0x02 #define L2CAP_FC_L2CAP 0x02
#define L2CAP_FC_CONNLESS 0x04 #define L2CAP_FC_CONNLESS 0x04
#define L2CAP_FC_A2MP 0x08 #define L2CAP_FC_A2MP 0x08
#define L2CAP_FC_6LOWPAN 0x3e /* reserved and temporary value */
/* L2CAP Control Field bit masks */ /* L2CAP Control Field bit masks */
#define L2CAP_CTRL_SAR 0xC000 #define L2CAP_CTRL_SAR 0xC000
...@@ -579,7 +578,7 @@ struct l2cap_chan { ...@@ -579,7 +578,7 @@ struct l2cap_chan {
struct list_head global_l; struct list_head global_l;
void *data; void *data;
struct l2cap_ops *ops; const struct l2cap_ops *ops;
struct mutex lock; struct mutex lock;
}; };
...@@ -600,7 +599,12 @@ struct l2cap_ops { ...@@ -600,7 +599,12 @@ struct l2cap_ops {
void (*set_shutdown) (struct l2cap_chan *chan); void (*set_shutdown) (struct l2cap_chan *chan);
long (*get_sndtimeo) (struct l2cap_chan *chan); long (*get_sndtimeo) (struct l2cap_chan *chan);
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
unsigned long hdr_len,
unsigned long len, int nb); unsigned long len, int nb);
int (*memcpy_fromiovec) (struct l2cap_chan *chan,
unsigned char *kdata,
struct iovec *iov,
int len);
}; };
struct l2cap_conn { struct l2cap_conn {
...@@ -856,6 +860,31 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan) ...@@ -856,6 +860,31 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
return 0; return 0;
} }
static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan,
unsigned char *kdata,
struct iovec *iov,
int len)
{
/* Following is safe since for compiler definitions of kvec and
* iovec are identical, yielding the same in-core layout and alignment
*/
struct kvec *vec = (struct kvec *)iov;
while (len > 0) {
if (vec->iov_len) {
int copy = min_t(unsigned int, len, vec->iov_len);
memcpy(kdata, vec->iov_base, copy);
len -= copy;
kdata += copy;
vec->iov_base += copy;
vec->iov_len -= copy;
}
vec++;
}
return 0;
}
extern bool disable_ertm; extern bool disable_ertm;
int l2cap_init_sockets(void); int l2cap_init_sockets(void);
...@@ -872,8 +901,7 @@ struct l2cap_chan *l2cap_chan_create(void); ...@@ -872,8 +901,7 @@ struct l2cap_chan *l2cap_chan_create(void);
void l2cap_chan_close(struct l2cap_chan *chan, int reason); void l2cap_chan_close(struct l2cap_chan *chan, int reason);
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
bdaddr_t *dst, u8 dst_type); bdaddr_t *dst, u8 dst_type);
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
u32 priority);
void l2cap_chan_busy(struct l2cap_chan *chan, int busy); void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
int l2cap_chan_check_security(struct l2cap_chan *chan); int l2cap_chan_check_security(struct l2cap_chan *chan);
void l2cap_chan_set_defaults(struct l2cap_chan *chan); void l2cap_chan_set_defaults(struct l2cap_chan *chan);
......
...@@ -97,6 +97,7 @@ struct mgmt_rp_read_index_list { ...@@ -97,6 +97,7 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_SECURE_CONN 0x00000800 #define MGMT_SETTING_SECURE_CONN 0x00000800
#define MGMT_SETTING_DEBUG_KEYS 0x00001000 #define MGMT_SETTING_DEBUG_KEYS 0x00001000
#define MGMT_SETTING_PRIVACY 0x00002000 #define MGMT_SETTING_PRIVACY 0x00002000
#define MGMT_SETTING_CONFIGURATION 0x00004000
#define MGMT_OP_READ_INFO 0x0004 #define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0 #define MGMT_READ_INFO_SIZE 0
...@@ -424,6 +425,76 @@ struct mgmt_rp_get_conn_info { ...@@ -424,6 +425,76 @@ struct mgmt_rp_get_conn_info {
__s8 max_tx_power; __s8 max_tx_power;
} __packed; } __packed;
#define MGMT_OP_GET_CLOCK_INFO 0x0032
struct mgmt_cp_get_clock_info {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_GET_CLOCK_INFO_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_rp_get_clock_info {
struct mgmt_addr_info addr;
__le32 local_clock;
__le32 piconet_clock;
__le16 accuracy;
} __packed;
#define MGMT_OP_ADD_DEVICE 0x0033
struct mgmt_cp_add_device {
struct mgmt_addr_info addr;
__u8 action;
} __packed;
#define MGMT_ADD_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1)
#define MGMT_OP_REMOVE_DEVICE 0x0034
struct mgmt_cp_remove_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_REMOVE_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_conn_param {
struct mgmt_addr_info addr;
__le16 min_interval;
__le16 max_interval;
__le16 latency;
__le16 timeout;
} __packed;
#define MGMT_OP_LOAD_CONN_PARAM 0x0035
struct mgmt_cp_load_conn_param {
__le16 param_count;
struct mgmt_conn_param params[0];
} __packed;
#define MGMT_LOAD_CONN_PARAM_SIZE 2
#define MGMT_OP_READ_UNCONF_INDEX_LIST 0x0036
#define MGMT_READ_UNCONF_INDEX_LIST_SIZE 0
struct mgmt_rp_read_unconf_index_list {
__le16 num_controllers;
__le16 index[0];
} __packed;
#define MGMT_OPTION_EXTERNAL_CONFIG 0x00000001
#define MGMT_OPTION_PUBLIC_ADDRESS 0x00000002
#define MGMT_OP_READ_CONFIG_INFO 0x0037
#define MGMT_READ_CONFIG_INFO_SIZE 0
struct mgmt_rp_read_config_info {
__le16 manufacturer;
__le32 supported_options;
__le32 missing_options;
} __packed;
#define MGMT_OP_SET_EXTERNAL_CONFIG 0x0038
struct mgmt_cp_set_external_config {
__u8 config;
} __packed;
#define MGMT_SET_EXTERNAL_CONFIG_SIZE 1
#define MGMT_OP_SET_PUBLIC_ADDRESS 0x0039
struct mgmt_cp_set_public_address {
bdaddr_t bdaddr;
} __packed;
#define MGMT_SET_PUBLIC_ADDRESS_SIZE 6
#define MGMT_EV_CMD_COMPLETE 0x0001 #define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete { struct mgmt_ev_cmd_complete {
__le16 opcode; __le16 opcode;
...@@ -522,6 +593,7 @@ struct mgmt_ev_auth_failed { ...@@ -522,6 +593,7 @@ struct mgmt_ev_auth_failed {
#define MGMT_DEV_FOUND_CONFIRM_NAME 0x01 #define MGMT_DEV_FOUND_CONFIRM_NAME 0x01
#define MGMT_DEV_FOUND_LEGACY_PAIRING 0x02 #define MGMT_DEV_FOUND_LEGACY_PAIRING 0x02
#define MGMT_DEV_FOUND_NOT_CONNECTABLE 0x04
#define MGMT_EV_DEVICE_FOUND 0x0012 #define MGMT_EV_DEVICE_FOUND 0x0012
struct mgmt_ev_device_found { struct mgmt_ev_device_found {
...@@ -578,3 +650,30 @@ struct mgmt_ev_new_csrk { ...@@ -578,3 +650,30 @@ struct mgmt_ev_new_csrk {
__u8 store_hint; __u8 store_hint;
struct mgmt_csrk_info key; struct mgmt_csrk_info key;
} __packed; } __packed;
#define MGMT_EV_DEVICE_ADDED 0x001a
struct mgmt_ev_device_added {
struct mgmt_addr_info addr;
__u8 action;
} __packed;
#define MGMT_EV_DEVICE_REMOVED 0x001b
struct mgmt_ev_device_removed {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_NEW_CONN_PARAM 0x001c
struct mgmt_ev_new_conn_param {
struct mgmt_addr_info addr;
__u8 store_hint;
__le16 min_interval;
__le16 max_interval;
__le16 latency;
__le16 timeout;
} __packed;
#define MGMT_EV_UNCONF_INDEX_ADDED 0x001d
#define MGMT_EV_UNCONF_INDEX_REMOVED 0x001e
#define MGMT_EV_NEW_CONFIG_OPTIONS 0x001f
This diff is collapsed.
/*
Copyright (c) 2013 Intel Corp.
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.
*/
#ifndef __6LOWPAN_H
#define __6LOWPAN_H
#include <linux/errno.h>
#include <linux/skbuff.h>
#include <net/bluetooth/l2cap.h>
#if IS_ENABLED(CONFIG_BT_6LOWPAN)
int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
int bt_6lowpan_add_conn(struct l2cap_conn *conn);
int bt_6lowpan_del_conn(struct l2cap_conn *conn);
int bt_6lowpan_init(void);
void bt_6lowpan_cleanup(void);
#else
static int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb)
{
return -EOPNOTSUPP;
}
static int bt_6lowpan_add_conn(struct l2cap_conn *conn)
{
return -EOPNOTSUPP;
}
int bt_6lowpan_del_conn(struct l2cap_conn *conn)
{
return -EOPNOTSUPP;
}
static int bt_6lowpan_init(void)
{
return -EOPNOTSUPP;
}
static void bt_6lowpan_cleanup(void) { }
#endif
#endif /* __6LOWPAN_H */
...@@ -6,7 +6,6 @@ menuconfig BT ...@@ -6,7 +6,6 @@ menuconfig BT
tristate "Bluetooth subsystem support" tristate "Bluetooth subsystem support"
depends on NET && !S390 depends on NET && !S390
depends on RFKILL || !RFKILL depends on RFKILL || !RFKILL
select 6LOWPAN_IPHC if BT_6LOWPAN
select CRC16 select CRC16
select CRYPTO select CRYPTO
select CRYPTO_BLKCIPHER select CRYPTO_BLKCIPHER
...@@ -41,10 +40,11 @@ menuconfig BT ...@@ -41,10 +40,11 @@ menuconfig BT
more information, see <http://www.bluez.org/>. more information, see <http://www.bluez.org/>.
config BT_6LOWPAN config BT_6LOWPAN
bool "Bluetooth 6LoWPAN support" tristate "Bluetooth 6LoWPAN support"
depends on BT && IPV6 depends on BT && IPV6
select 6LOWPAN_IPHC if BT_6LOWPAN
help help
IPv6 compression over Bluetooth. IPv6 compression over Bluetooth Low Energy.
source "net/bluetooth/rfcomm/Kconfig" source "net/bluetooth/rfcomm/Kconfig"
......
...@@ -7,10 +7,12 @@ obj-$(CONFIG_BT_RFCOMM) += rfcomm/ ...@@ -7,10 +7,12 @@ obj-$(CONFIG_BT_RFCOMM) += rfcomm/
obj-$(CONFIG_BT_BNEP) += bnep/ obj-$(CONFIG_BT_BNEP) += bnep/
obj-$(CONFIG_BT_CMTP) += cmtp/ obj-$(CONFIG_BT_CMTP) += cmtp/
obj-$(CONFIG_BT_HIDP) += hidp/ obj-$(CONFIG_BT_HIDP) += hidp/
obj-$(CONFIG_BT_6LOWPAN) += bluetooth_6lowpan.o
bluetooth_6lowpan-y := 6lowpan.o
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
a2mp.o amp.o a2mp.o amp.o
bluetooth-$(CONFIG_BT_6LOWPAN) += 6lowpan.o
subdir-ccflags-y += -D__CHECK_ENDIAN__ subdir-ccflags-y += -D__CHECK_ENDIAN__
...@@ -63,7 +63,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data) ...@@ -63,7 +63,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
msg.msg_iov = (struct iovec *) &iv; msg.msg_iov = (struct iovec *) &iv;
msg.msg_iovlen = 1; msg.msg_iovlen = 1;
l2cap_chan_send(chan, &msg, total_len, 0); l2cap_chan_send(chan, &msg, total_len);
kfree(cmd); kfree(cmd);
} }
...@@ -693,18 +693,19 @@ static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state, ...@@ -693,18 +693,19 @@ static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state,
} }
static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan, static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan,
unsigned long hdr_len,
unsigned long len, int nb) unsigned long len, int nb)
{ {
struct sk_buff *skb; struct sk_buff *skb;
skb = bt_skb_alloc(len, GFP_KERNEL); skb = bt_skb_alloc(hdr_len + len, GFP_KERNEL);
if (!skb) if (!skb)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
return skb; return skb;
} }
static struct l2cap_ops a2mp_chan_ops = { static const struct l2cap_ops a2mp_chan_ops = {
.name = "L2CAP A2MP channel", .name = "L2CAP A2MP channel",
.recv = a2mp_chan_recv_cb, .recv = a2mp_chan_recv_cb,
.close = a2mp_chan_close_cb, .close = a2mp_chan_close_cb,
...@@ -719,6 +720,7 @@ static struct l2cap_ops a2mp_chan_ops = { ...@@ -719,6 +720,7 @@ static struct l2cap_ops a2mp_chan_ops = {
.resume = l2cap_chan_no_resume, .resume = l2cap_chan_no_resume,
.set_shutdown = l2cap_chan_no_set_shutdown, .set_shutdown = l2cap_chan_no_set_shutdown,
.get_sndtimeo = l2cap_chan_no_get_sndtimeo, .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
}; };
static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
......
...@@ -639,7 +639,7 @@ static int bt_seq_show(struct seq_file *seq, void *v) ...@@ -639,7 +639,7 @@ static int bt_seq_show(struct seq_file *seq, void *v)
return 0; return 0;
} }
static struct seq_operations bt_seq_ops = { static const struct seq_operations bt_seq_ops = {
.start = bt_seq_start, .start = bt_seq_start,
.next = bt_seq_next, .next = bt_seq_next,
.stop = bt_seq_stop, .stop = bt_seq_stop,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -481,7 +481,7 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) ...@@ -481,7 +481,7 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
hci_dev_lock(hdev); hci_dev_lock(hdev);
err = hci_blacklist_add(hdev, &bdaddr, BDADDR_BREDR); err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -498,7 +498,7 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) ...@@ -498,7 +498,7 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
hci_dev_lock(hdev); hci_dev_lock(hdev);
err = hci_blacklist_del(hdev, &bdaddr, BDADDR_BREDR); err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -517,6 +517,9 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, ...@@ -517,6 +517,9 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
return -EBUSY; return -EBUSY;
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
return -EOPNOTSUPP;
if (hdev->dev_type != HCI_BREDR) if (hdev->dev_type != HCI_BREDR)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -690,7 +693,8 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, ...@@ -690,7 +693,8 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
if (test_bit(HCI_UP, &hdev->flags) || if (test_bit(HCI_UP, &hdev->flags) ||
test_bit(HCI_INIT, &hdev->flags) || test_bit(HCI_INIT, &hdev->flags) ||
test_bit(HCI_SETUP, &hdev->dev_flags)) { test_bit(HCI_SETUP, &hdev->dev_flags) ||
test_bit(HCI_CONFIG, &hdev->dev_flags)) {
err = -EBUSY; err = -EBUSY;
hci_dev_put(hdev); hci_dev_put(hdev);
goto done; goto done;
...@@ -960,7 +964,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -960,7 +964,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
goto drop; goto drop;
} }
if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) { if (ogf == 0x3f) {
skb_queue_tail(&hdev->raw_q, skb); skb_queue_tail(&hdev->raw_q, skb);
queue_work(hdev->workqueue, &hdev->tx_work); queue_work(hdev->workqueue, &hdev->tx_work);
} else { } else {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -116,6 +116,13 @@ struct smp_cmd_security_req { ...@@ -116,6 +116,13 @@ struct smp_cmd_security_req {
#define SMP_MIN_ENC_KEY_SIZE 7 #define SMP_MIN_ENC_KEY_SIZE 7
#define SMP_MAX_ENC_KEY_SIZE 16 #define SMP_MAX_ENC_KEY_SIZE 16
/* LTK types used in internal storage (struct smp_ltk) */
enum {
SMP_STK,
SMP_LTK,
SMP_LTK_SLAVE,
};
/* SMP Commands */ /* SMP Commands */
bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level); bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level);
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment