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
...@@ -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;
while (count) {
size = min_t(uint, count, BULK_SIZE);
pipe = usb_sndbulkpipe(udev, 0x02); pipe = usb_sndbulkpipe(udev, 0x02);
while (count) {
size = min_t(uint, count, BULK_SIZE);
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,7 +260,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock); ...@@ -260,7 +260,7 @@ 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,
......
...@@ -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.
...@@ -361,7 +361,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, ...@@ -361,7 +361,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
BT_DBG("sock %p, sk %p", sock, sk); BT_DBG("sock %p, sk %p", sock, sk);
if (peer && sk->sk_state != BT_CONNECTED && if (peer && sk->sk_state != BT_CONNECTED &&
sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2) sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2 &&
sk->sk_state != BT_CONFIG)
return -ENOTCONN; return -ENOTCONN;
memset(la, 0, sizeof(struct sockaddr_l2)); memset(la, 0, sizeof(struct sockaddr_l2));
...@@ -964,7 +965,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -964,7 +965,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
return err; return err;
l2cap_chan_lock(chan); l2cap_chan_lock(chan);
err = l2cap_chan_send(chan, msg, len, sk->sk_priority); err = l2cap_chan_send(chan, msg, len);
l2cap_chan_unlock(chan); l2cap_chan_unlock(chan);
return err; return err;
...@@ -1292,6 +1293,7 @@ static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state, ...@@ -1292,6 +1293,7 @@ static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state,
} }
static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
unsigned long hdr_len,
unsigned long len, int nb) unsigned long len, int nb)
{ {
struct sock *sk = chan->data; struct sock *sk = chan->data;
...@@ -1299,17 +1301,26 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, ...@@ -1299,17 +1301,26 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
int err; int err;
l2cap_chan_unlock(chan); l2cap_chan_unlock(chan);
skb = bt_skb_send_alloc(sk, len, nb, &err); skb = bt_skb_send_alloc(sk, hdr_len + len, nb, &err);
l2cap_chan_lock(chan); l2cap_chan_lock(chan);
if (!skb) if (!skb)
return ERR_PTR(err); return ERR_PTR(err);
skb->priority = sk->sk_priority;
bt_cb(skb)->chan = chan; bt_cb(skb)->chan = chan;
return skb; return skb;
} }
static int l2cap_sock_memcpy_fromiovec_cb(struct l2cap_chan *chan,
unsigned char *kdata,
struct iovec *iov, int len)
{
return memcpy_fromiovec(kdata, iov, len);
}
static void l2cap_sock_ready_cb(struct l2cap_chan *chan) static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
{ {
struct sock *sk = chan->data; struct sock *sk = chan->data;
...@@ -1375,7 +1386,7 @@ static void l2cap_sock_suspend_cb(struct l2cap_chan *chan) ...@@ -1375,7 +1386,7 @@ static void l2cap_sock_suspend_cb(struct l2cap_chan *chan)
sk->sk_state_change(sk); sk->sk_state_change(sk);
} }
static struct l2cap_ops l2cap_chan_ops = { static const struct l2cap_ops l2cap_chan_ops = {
.name = "L2CAP Socket Interface", .name = "L2CAP Socket Interface",
.new_connection = l2cap_sock_new_connection_cb, .new_connection = l2cap_sock_new_connection_cb,
.recv = l2cap_sock_recv_cb, .recv = l2cap_sock_recv_cb,
...@@ -1389,6 +1400,7 @@ static struct l2cap_ops l2cap_chan_ops = { ...@@ -1389,6 +1400,7 @@ static struct l2cap_ops l2cap_chan_ops = {
.set_shutdown = l2cap_sock_set_shutdown_cb, .set_shutdown = l2cap_sock_set_shutdown_cb,
.get_sndtimeo = l2cap_sock_get_sndtimeo_cb, .get_sndtimeo = l2cap_sock_get_sndtimeo_cb,
.alloc_skb = l2cap_sock_alloc_skb_cb, .alloc_skb = l2cap_sock_alloc_skb_cb,
.memcpy_fromiovec = l2cap_sock_memcpy_fromiovec_cb,
}; };
static void l2cap_sock_destruct(struct sock *sk) static void l2cap_sock_destruct(struct sock *sk)
......
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