Commit 0d4f55bc 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 75ae83d6 4f3e219d
......@@ -30,3 +30,5 @@ hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o
hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o
hci_uart-$(CONFIG_BT_HCIUART_3WIRE) += hci_h5.o
hci_uart-objs := $(hci_uart-y)
ccflags-y += -D__CHECK_ENDIAN__
......@@ -85,6 +85,7 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x04CA, 0x3008) },
{ USB_DEVICE(0x13d3, 0x3362) },
{ USB_DEVICE(0x0CF3, 0xE004) },
{ USB_DEVICE(0x0CF3, 0xE005) },
{ USB_DEVICE(0x0930, 0x0219) },
{ USB_DEVICE(0x0489, 0xe057) },
{ USB_DEVICE(0x13d3, 0x3393) },
......@@ -126,6 +127,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
......
......@@ -23,6 +23,8 @@
#include <linux/bitops.h>
#include <linux/slab.h>
#include <net/bluetooth/bluetooth.h>
#include <linux/ctype.h>
#include <linux/firmware.h>
#define BTM_HEADER_LEN 4
#define BTM_UPLD_SIZE 2312
......@@ -41,6 +43,8 @@ struct btmrvl_thread {
struct btmrvl_device {
void *card;
struct hci_dev *hcidev;
struct device *dev;
const char *cal_data;
u8 dev_type;
......@@ -91,6 +95,7 @@ struct btmrvl_private {
#define BT_CMD_HOST_SLEEP_CONFIG 0x59
#define BT_CMD_HOST_SLEEP_ENABLE 0x5A
#define BT_CMD_MODULE_CFG_REQ 0x5B
#define BT_CMD_LOAD_CONFIG_DATA 0x61
/* Sub-commands: Module Bringup/Shutdown Request/Response */
#define MODULE_BRINGUP_REQ 0xF1
......@@ -116,11 +121,8 @@ struct btmrvl_private {
#define PS_SLEEP 0x01
#define PS_AWAKE 0x00
struct btmrvl_cmd {
__le16 ocf_ogf;
u8 length;
u8 data[4];
} __packed;
#define BT_CMD_DATA_SIZE 32
#define BT_CAL_DATA_SIZE 28
struct btmrvl_event {
u8 ec; /* event counter */
......
......@@ -57,8 +57,7 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
ocf = hci_opcode_ocf(opcode);
ogf = hci_opcode_ogf(opcode);
if (ocf == BT_CMD_MODULE_CFG_REQ &&
priv->btmrvl_dev.sendcmdflag) {
if (priv->btmrvl_dev.sendcmdflag) {
priv->btmrvl_dev.sendcmdflag = false;
priv->adapter->cmd_complete = true;
wake_up_interruptible(&priv->adapter->cmd_wait_q);
......@@ -116,7 +115,6 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
adapter->hs_state = HS_ACTIVATED;
if (adapter->psmode)
adapter->ps_state = PS_SLEEP;
wake_up_interruptible(&adapter->cmd_wait_q);
BT_DBG("HS ACTIVATED!");
} else {
BT_DBG("HS Enable failed");
......@@ -168,22 +166,24 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(btmrvl_process_event);
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
const void *param, u8 len)
{
struct sk_buff *skb;
struct btmrvl_cmd *cmd;
int ret = 0;
struct hci_command_hdr *hdr;
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC);
if (skb == NULL) {
BT_ERR("No free skb");
return -ENOMEM;
}
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_MODULE_CFG_REQ));
cmd->length = 1;
cmd->data[0] = subcmd;
hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE);
hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
hdr->plen = len;
if (len)
memcpy(skb_put(skb, len), param, len);
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
......@@ -194,19 +194,23 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
priv->adapter->cmd_complete = false;
BT_DBG("Queue module cfg Command");
wake_up_interruptible(&priv->main_thread.wait_q);
if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,
priv->adapter->cmd_complete,
msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) {
ret = -ETIMEDOUT;
BT_ERR("module_cfg_cmd(%x): timeout: %d",
subcmd, priv->btmrvl_dev.sendcmdflag);
}
msecs_to_jiffies(WAIT_UNTIL_CMD_RESP)))
return -ETIMEDOUT;
BT_DBG("module cfg Command done");
return 0;
}
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
{
int ret;
ret = btmrvl_send_sync_cmd(priv, BT_CMD_MODULE_CFG_REQ, &subcmd, 1);
if (ret)
BT_ERR("module_cfg_cmd(%x) failed\n", subcmd);
return ret;
}
......@@ -214,61 +218,36 @@ EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)
{
struct sk_buff *skb;
struct btmrvl_cmd *cmd;
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
if (!skb) {
BT_ERR("No free skb");
return -ENOMEM;
}
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF,
BT_CMD_HOST_SLEEP_CONFIG));
cmd->length = 2;
cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
int ret;
u8 param[2];
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
param[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
param[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
skb->dev = (void *) priv->btmrvl_dev.hcidev;
skb_queue_head(&priv->adapter->tx_queue, skb);
BT_DBG("Sending HSCFG Command, gpio=0x%x, gap=0x%x",
param[0], param[1]);
BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0],
cmd->data[1]);
ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_CONFIG, param, 2);
if (ret)
BT_ERR("HSCFG command failed\n");
return 0;
return ret;
}
EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd);
int btmrvl_enable_ps(struct btmrvl_private *priv)
{
struct sk_buff *skb;
struct btmrvl_cmd *cmd;
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
if (skb == NULL) {
BT_ERR("No free skb");
return -ENOMEM;
}
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF,
BT_CMD_AUTO_SLEEP_MODE));
cmd->length = 1;
int ret;
u8 param;
if (priv->btmrvl_dev.psmode)
cmd->data[0] = BT_PS_ENABLE;
param = BT_PS_ENABLE;
else
cmd->data[0] = BT_PS_DISABLE;
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
param = BT_PS_DISABLE;
skb->dev = (void *) priv->btmrvl_dev.hcidev;
skb_queue_head(&priv->adapter->tx_queue, skb);
BT_DBG("Queue PSMODE Command:%d", cmd->data[0]);
ret = btmrvl_send_sync_cmd(priv, BT_CMD_AUTO_SLEEP_MODE, &param, 1);
if (ret)
BT_ERR("PSMODE command failed\n");
return 0;
}
......@@ -276,37 +255,11 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
int btmrvl_enable_hs(struct btmrvl_private *priv)
{
struct sk_buff *skb;
struct btmrvl_cmd *cmd;
int ret = 0;
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
if (skb == NULL) {
BT_ERR("No free skb");
return -ENOMEM;
}
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_ENABLE));
cmd->length = 0;
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
skb->dev = (void *) priv->btmrvl_dev.hcidev;
skb_queue_head(&priv->adapter->tx_queue, skb);
BT_DBG("Queue hs enable Command");
wake_up_interruptible(&priv->main_thread.wait_q);
int ret;
if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,
priv->adapter->hs_state,
msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED))) {
ret = -ETIMEDOUT;
BT_ERR("timeout: %d, %d,%d", priv->adapter->hs_state,
priv->adapter->ps_state,
priv->adapter->wakeup_tries);
}
ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
if (ret)
BT_ERR("Host sleep enable command failed\n");
return ret;
}
......@@ -479,6 +432,137 @@ static int btmrvl_open(struct hci_dev *hdev)
return 0;
}
/*
* This function parses provided calibration data input. It should contain
* hex bytes separated by space or new line character. Here is an example.
* 00 1C 01 37 FF FF FF FF 02 04 7F 01
* CE BA 00 00 00 2D C6 C0 00 00 00 00
* 00 F0 00 00
*/
static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size)
{
const u8 *s = src;
u8 *d = dst;
int ret;
u8 tmp[3];
tmp[2] = '\0';
while ((s - src) <= len - 2) {
if (isspace(*s)) {
s++;
continue;
}
if (isxdigit(*s)) {
if ((d - dst) >= dst_size) {
BT_ERR("calibration data file too big!!!");
return -EINVAL;
}
memcpy(tmp, s, 2);
ret = kstrtou8(tmp, 16, d++);
if (ret < 0)
return ret;
s += 2;
} else {
return -EINVAL;
}
}
if (d == dst)
return -EINVAL;
return 0;
}
static int btmrvl_load_cal_data(struct btmrvl_private *priv,
u8 *config_data)
{
int i, ret;
u8 data[BT_CMD_DATA_SIZE];
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = BT_CMD_DATA_SIZE - 4;
/* Swap cal-data bytes. Each four bytes are swapped. Considering 4
* byte SDIO header offset, mapping of input and output bytes will be
* {3, 2, 1, 0} -> {0+4, 1+4, 2+4, 3+4},
* {7, 6, 5, 4} -> {4+4, 5+4, 6+4, 7+4} */
for (i = 4; i < BT_CMD_DATA_SIZE; i++)
data[i] = config_data[(i / 4) * 8 - 1 - i];
print_hex_dump_bytes("Calibration data: ",
DUMP_PREFIX_OFFSET, data, BT_CMD_DATA_SIZE);
ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
BT_CMD_DATA_SIZE);
if (ret)
BT_ERR("Failed to download caibration data\n");
return 0;
}
static int
btmrvl_process_cal_cfg(struct btmrvl_private *priv, u8 *data, u32 size)
{
u8 cal_data[BT_CAL_DATA_SIZE];
int ret;
ret = btmrvl_parse_cal_cfg(data, size, cal_data, sizeof(cal_data));
if (ret)
return ret;
ret = btmrvl_load_cal_data(priv, cal_data);
if (ret) {
BT_ERR("Fail to load calibrate data");
return ret;
}
return 0;
}
static int btmrvl_cal_data_config(struct btmrvl_private *priv)
{
const struct firmware *cfg;
int ret;
const char *cal_data = priv->btmrvl_dev.cal_data;
if (!cal_data)
return 0;
ret = request_firmware(&cfg, cal_data, priv->btmrvl_dev.dev);
if (ret < 0) {
BT_DBG("Failed to get %s file, skipping cal data download",
cal_data);
return 0;
}
ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size);
release_firmware(cfg);
return ret;
}
static int btmrvl_setup(struct hci_dev *hdev)
{
struct btmrvl_private *priv = hci_get_drvdata(hdev);
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
if (btmrvl_cal_data_config(priv))
BT_ERR("Set cal data failed");
priv->btmrvl_dev.psmode = 1;
btmrvl_enable_ps(priv);
priv->btmrvl_dev.gpio_gap = 0xffff;
btmrvl_send_hscfg_cmd(priv);
return 0;
}
/*
* This function handles the event generated by firmware, rx data
* received from firmware, and tx data sent from kernel.
......@@ -572,8 +656,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
hdev->flush = btmrvl_flush;
hdev->send = btmrvl_send_frame;
hdev->ioctl = btmrvl_ioctl;
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
hdev->setup = btmrvl_setup;
hdev->dev_type = priv->btmrvl_dev.dev_type;
......
......@@ -18,7 +18,6 @@
* this warranty disclaimer.
**/
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/mmc/sdio_ids.h>
......@@ -102,6 +101,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin",
.cal_data = NULL,
.reg = &btmrvl_reg_8688,
.sd_blksz_fw_dl = 64,
};
......@@ -109,6 +109,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
.helper = NULL,
.firmware = "mrvl/sd8787_uapsta.bin",
.cal_data = NULL,
.reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256,
};
......@@ -116,6 +117,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.helper = NULL,
.firmware = "mrvl/sd8797_uapsta.bin",
.cal_data = "mrvl/sd8797_caldata.conf",
.reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256,
};
......@@ -123,6 +125,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.helper = NULL,
.firmware = "mrvl/sd8897_uapsta.bin",
.cal_data = NULL,
.reg = &btmrvl_reg_88xx,
.sd_blksz_fw_dl = 256,
};
......@@ -1006,6 +1009,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
struct btmrvl_sdio_device *data = (void *) id->driver_data;
card->helper = data->helper;
card->firmware = data->firmware;
card->cal_data = data->cal_data;
card->reg = data->reg;
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
}
......@@ -1034,6 +1038,8 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
}
card->priv = priv;
priv->btmrvl_dev.dev = &card->func->dev;
priv->btmrvl_dev.cal_data = card->cal_data;
/* Initialize the interface specific function pointers */
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
......@@ -1046,12 +1052,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
goto disable_host_int;
}
priv->btmrvl_dev.psmode = 1;
btmrvl_enable_ps(priv);
priv->btmrvl_dev.gpio_gap = 0xffff;
btmrvl_send_hscfg_cmd(priv);
return 0;
disable_host_int:
......@@ -1222,4 +1222,5 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
MODULE_FIRMWARE("mrvl/sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_caldata.conf");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
......@@ -85,6 +85,7 @@ struct btmrvl_sdio_card {
u32 ioport;
const char *helper;
const char *firmware;
const char *cal_data;
const struct btmrvl_sdio_card_reg *reg;
u16 sd_blksz_fw_dl;
u8 rx_unit;
......@@ -94,6 +95,7 @@ struct btmrvl_sdio_card {
struct btmrvl_sdio_device {
const char *helper;
const char *firmware;
const char *cal_data;
const struct btmrvl_sdio_card_reg *reg;
u16 sd_blksz_fw_dl;
};
......
......@@ -102,6 +102,7 @@ static struct usb_device_id btusb_table[] = {
/* Broadcom BCM20702A0 */
{ USB_DEVICE(0x0b05, 0x17b5) },
{ USB_DEVICE(0x0b05, 0x17cb) },
{ USB_DEVICE(0x04ca, 0x2003) },
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x413c, 0x8197) },
......@@ -112,6 +113,9 @@ static struct usb_device_id btusb_table[] = {
/*Broadcom devices with vendor specific id */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
/* Belkin F8065bf - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
{ } /* Terminating entry */
};
......@@ -148,6 +152,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
......
......@@ -24,6 +24,7 @@
*/
#include <linux/module.h>
#include <asm/unaligned.h>
#include <linux/kernel.h>
#include <linux/init.h>
......@@ -39,17 +40,17 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#define VERSION "1.3"
#define VERSION "1.4"
static bool amp;
struct vhci_data {
struct hci_dev *hdev;
unsigned long flags;
wait_queue_head_t read_wait;
struct sk_buff_head readq;
struct delayed_work open_timeout;
};
static int vhci_open_dev(struct hci_dev *hdev)
......@@ -99,16 +100,62 @@ static int vhci_send_frame(struct sk_buff *skb)
skb_queue_tail(&data->readq, skb);
wake_up_interruptible(&data->read_wait);
return 0;
}
static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
{
struct hci_dev *hdev;
struct sk_buff *skb;
skb = bt_skb_alloc(4, GFP_KERNEL);
if (!skb)
return -ENOMEM;
hdev = hci_alloc_dev();
if (!hdev) {
kfree_skb(skb);
return -ENOMEM;
}
data->hdev = hdev;
hdev->bus = HCI_VIRTUAL;
hdev->dev_type = dev_type;
hci_set_drvdata(hdev, data);
hdev->open = vhci_open_dev;
hdev->close = vhci_close_dev;
hdev->flush = vhci_flush;
hdev->send = vhci_send_frame;
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
data->hdev = NULL;
kfree_skb(skb);
return -EBUSY;
}
bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
*skb_put(skb, 1) = 0xff;
*skb_put(skb, 1) = dev_type;
put_unaligned_le16(hdev->id, skb_put(skb, 2));
skb_queue_tail(&data->readq, skb);
wake_up_interruptible(&data->read_wait);
return 0;
}
static inline ssize_t vhci_get_user(struct vhci_data *data,
const char __user *buf, size_t count)
const char __user *buf, size_t count)
{
struct sk_buff *skb;
__u8 pkt_type, dev_type;
int ret;
if (count > HCI_MAX_FRAME_SIZE)
if (count < 2 || count > HCI_MAX_FRAME_SIZE)
return -EINVAL;
skb = bt_skb_alloc(count, GFP_KERNEL);
......@@ -120,27 +167,70 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
return -EFAULT;
}
skb->dev = (void *) data->hdev;
bt_cb(skb)->pkt_type = *((__u8 *) skb->data);
pkt_type = *((__u8 *) skb->data);
skb_pull(skb, 1);
hci_recv_frame(skb);
switch (pkt_type) {
case HCI_EVENT_PKT:
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
if (!data->hdev) {
kfree_skb(skb);
return -ENODEV;
}
skb->dev = (void *) data->hdev;
bt_cb(skb)->pkt_type = pkt_type;
ret = hci_recv_frame(skb);
break;
case HCI_VENDOR_PKT:
if (data->hdev) {
kfree_skb(skb);
return -EBADFD;
}
return count;
cancel_delayed_work_sync(&data->open_timeout);
dev_type = *((__u8 *) skb->data);
skb_pull(skb, 1);
if (skb->len > 0) {
kfree_skb(skb);
return -EINVAL;
}
kfree_skb(skb);
if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
return -EINVAL;
ret = vhci_create_device(data, dev_type);
break;
default:
kfree_skb(skb);
return -EINVAL;
}
return (ret < 0) ? ret : count;
}
static inline ssize_t vhci_put_user(struct vhci_data *data,
struct sk_buff *skb, char __user *buf, int count)
struct sk_buff *skb,
char __user *buf, int count)
{
char __user *ptr = buf;
int len, total = 0;
int len;
len = min_t(unsigned int, skb->len, count);
if (copy_to_user(ptr, skb->data, len))
return -EFAULT;
total += len;
if (!data->hdev)
return len;
data->hdev->stat.byte_tx += len;
......@@ -148,21 +238,19 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,
case HCI_COMMAND_PKT:
data->hdev->stat.cmd_tx++;
break;
case HCI_ACLDATA_PKT:
data->hdev->stat.acl_tx++;
break;
case HCI_SCODATA_PKT:
data->hdev->stat.sco_tx++;
break;
}
return total;
return len;
}
static ssize_t vhci_read(struct file *file,
char __user *buf, size_t count, loff_t *pos)
char __user *buf, size_t count, loff_t *pos)
{
struct vhci_data *data = file->private_data;
struct sk_buff *skb;
......@@ -185,7 +273,7 @@ static ssize_t vhci_read(struct file *file,
}
ret = wait_event_interruptible(data->read_wait,
!skb_queue_empty(&data->readq));
!skb_queue_empty(&data->readq));
if (ret < 0)
break;
}
......@@ -194,7 +282,7 @@ static ssize_t vhci_read(struct file *file,
}
static ssize_t vhci_write(struct file *file,
const char __user *buf, size_t count, loff_t *pos)
const char __user *buf, size_t count, loff_t *pos)
{
struct vhci_data *data = file->private_data;
......@@ -213,10 +301,17 @@ static unsigned int vhci_poll(struct file *file, poll_table *wait)
return POLLOUT | POLLWRNORM;
}
static void vhci_open_timeout(struct work_struct *work)
{
struct vhci_data *data = container_of(work, struct vhci_data,
open_timeout.work);
vhci_create_device(data, amp ? HCI_AMP : HCI_BREDR);
}
static int vhci_open(struct inode *inode, struct file *file)
{
struct vhci_data *data;
struct hci_dev *hdev;
data = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
if (!data)
......@@ -225,35 +320,13 @@ static int vhci_open(struct inode *inode, struct file *file)
skb_queue_head_init(&data->readq);
init_waitqueue_head(&data->read_wait);
hdev = hci_alloc_dev();
if (!hdev) {
kfree(data);
return -ENOMEM;
}
data->hdev = hdev;
hdev->bus = HCI_VIRTUAL;
hci_set_drvdata(hdev, data);
if (amp)
hdev->dev_type = HCI_AMP;
hdev->open = vhci_open_dev;
hdev->close = vhci_close_dev;
hdev->flush = vhci_flush;
hdev->send = vhci_send_frame;
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
kfree(data);
hci_free_dev(hdev);
return -EBUSY;
}
INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);
file->private_data = data;
nonseekable_open(inode, file);
schedule_delayed_work(&data->open_timeout, msecs_to_jiffies(1000));
return 0;
}
......@@ -262,8 +335,12 @@ static int vhci_release(struct inode *inode, struct file *file)
struct vhci_data *data = file->private_data;
struct hci_dev *hdev = data->hdev;
hci_unregister_dev(hdev);
hci_free_dev(hdev);
cancel_delayed_work_sync(&data->open_timeout);
if (hdev) {
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
file->private_data = NULL;
kfree(data);
......@@ -309,3 +386,4 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_ALIAS("devname:vhci");
......@@ -197,8 +197,8 @@ static inline bool bdaddr_type_is_le(__u8 type)
return false;
}
#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0} })
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff} })
#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
#define BDADDR_NONE (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
/* Copy, swap, convert BD Address */
static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
......@@ -249,6 +249,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait);
int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
int bt_sock_wait_ready(struct sock *sk, unsigned long flags);
void bt_accept_enqueue(struct sock *parent, struct sock *sk);
void bt_accept_unlink(struct sock *sk);
......
......@@ -35,6 +35,8 @@
#define HCI_MAX_AMP_ASSOC_SIZE 672
#define HCI_MAX_CSB_DATA_SIZE 252
/* HCI dev events */
#define HCI_DEV_REG 1
#define HCI_DEV_UNREG 2
......@@ -104,11 +106,13 @@ enum {
enum {
HCI_SETUP,
HCI_AUTO_OFF,
HCI_RFKILLED,
HCI_MGMT,
HCI_PAIRABLE,
HCI_SERVICE_CACHE,
HCI_DEBUG_KEYS,
HCI_UNREGISTER,
HCI_USER_CHANNEL,
HCI_LE_SCAN,
HCI_SSP_ENABLED,
......@@ -120,6 +124,7 @@ enum {
HCI_LINK_SECURITY,
HCI_PERIODIC_INQ,
HCI_FAST_CONNECTABLE,
HCI_BREDR_ENABLED,
};
/* A mask for the flags that are supposed to remain when a reset happens
......@@ -623,6 +628,24 @@ struct hci_rp_logical_link_cancel {
__u8 flow_spec_id;
} __packed;
#define HCI_OP_SET_CSB 0x0441
struct hci_cp_set_csb {
__u8 enable;
__u8 lt_addr;
__u8 lpo_allowed;
__le16 packet_type;
__le16 interval_min;
__le16 interval_max;
__le16 csb_sv_tout;
} __packed;
struct hci_rp_set_csb {
__u8 status;
__u8 lt_addr;
__le16 interval;
} __packed;
#define HCI_OP_START_SYNC_TRAIN 0x0443
#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
__le16 handle;
......@@ -693,9 +716,6 @@ struct hci_cp_sniff_subrate {
} __packed;
#define HCI_OP_SET_EVENT_MASK 0x0c01
struct hci_cp_set_event_mask {
__u8 mask[8];
} __packed;
#define HCI_OP_RESET 0x0c03
......@@ -825,6 +845,8 @@ struct hci_rp_read_inq_rsp_tx_power {
__s8 tx_power;
} __packed;
#define HCI_OP_SET_EVENT_MASK_PAGE_2 0x0c63
#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66
struct hci_rp_read_flow_control_mode {
__u8 status;
......@@ -837,6 +859,50 @@ struct hci_cp_write_le_host_supported {
__u8 simul;
} __packed;
#define HCI_OP_SET_RESERVED_LT_ADDR 0x0c74
struct hci_cp_set_reserved_lt_addr {
__u8 lt_addr;
} __packed;
struct hci_rp_set_reserved_lt_addr {
__u8 status;
__u8 lt_addr;
} __packed;
#define HCI_OP_DELETE_RESERVED_LT_ADDR 0x0c75
struct hci_cp_delete_reserved_lt_addr {
__u8 lt_addr;
} __packed;
struct hci_rp_delete_reserved_lt_addr {
__u8 status;
__u8 lt_addr;
} __packed;
#define HCI_OP_SET_CSB_DATA 0x0c76
struct hci_cp_set_csb_data {
__u8 lt_addr;
__u8 fragment;
__u8 data_length;
__u8 data[HCI_MAX_CSB_DATA_SIZE];
} __packed;
struct hci_rp_set_csb_data {
__u8 status;
__u8 lt_addr;
} __packed;
#define HCI_OP_READ_SYNC_TRAIN_PARAMS 0x0c77
#define HCI_OP_WRITE_SYNC_TRAIN_PARAMS 0x0c78
struct hci_cp_write_sync_train_params {
__le16 interval_min;
__le16 interval_max;
__le32 sync_train_tout;
__u8 service_data;
} __packed;
struct hci_rp_write_sync_train_params {
__u8 status;
__le16 sync_train_int;
} __packed;
#define HCI_OP_READ_LOCAL_VERSION 0x1001
struct hci_rp_read_local_version {
__u8 status;
......@@ -974,6 +1040,8 @@ struct hci_rp_le_read_local_features {
__u8 features[8];
} __packed;
#define HCI_OP_LE_SET_RANDOM_ADDR 0x2005
#define HCI_OP_LE_READ_ADV_TX_POWER 0x2007
struct hci_rp_le_read_adv_tx_power {
__u8 status;
......@@ -1437,6 +1505,13 @@ struct hci_ev_num_comp_blocks {
struct hci_comp_blocks_info handles[0];
} __packed;
#define HCI_EV_SYNC_TRAIN_COMPLETE 0x4F
struct hci_ev_sync_train_complete {
__u8 status;
} __packed;
#define HCI_EV_SLAVE_PAGE_RESP_TIMEOUT 0x54
/* Low energy meta events */
#define LE_CONN_ROLE_MASTER 0x00
......@@ -1570,6 +1645,7 @@ struct sockaddr_hci {
#define HCI_DEV_NONE 0xffff
#define HCI_CHANNEL_RAW 0
#define HCI_CHANNEL_USER 1
#define HCI_CHANNEL_MONITOR 2
#define HCI_CHANNEL_CONTROL 3
......
......@@ -140,6 +140,7 @@ struct hci_dev {
__u8 bus;
__u8 dev_type;
bdaddr_t bdaddr;
bdaddr_t static_addr;
__u8 dev_name[HCI_MAX_NAME_LENGTH];
__u8 short_name[HCI_MAX_SHORT_NAME_LENGTH];
__u8 eir[HCI_MAX_EIR_LENGTH];
......@@ -1168,7 +1169,6 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
u8 *randomizer, u8 status);
int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
u8 ssp, u8 *eir, u16 eir_len);
......
......@@ -564,6 +564,7 @@ struct l2cap_conn {
__u32 feat_mask;
__u8 fixed_chan_mask;
bool hs_enabled;
__u8 info_state;
__u8 info_ident;
......
......@@ -93,6 +93,7 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_BREDR 0x00000080
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
#define MGMT_SETTING_ADVERTISING 0x00000400
#define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0
......@@ -351,6 +352,16 @@ struct mgmt_cp_set_device_id {
} __packed;
#define MGMT_SET_DEVICE_ID_SIZE 8
#define MGMT_OP_SET_ADVERTISING 0x0029
#define MGMT_OP_SET_BREDR 0x002A
#define MGMT_OP_SET_STATIC_ADDRESS 0x002B
struct mgmt_cp_set_static_address {
bdaddr_t bdaddr;
} __packed;
#define MGMT_SET_STATIC_ADDRESS_SIZE 6
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
......
......@@ -11,3 +11,5 @@ obj-$(CONFIG_BT_HIDP) += hidp/
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
a2mp.o amp.o
subdir-ccflags-y += -D__CHECK_ENDIAN__
......@@ -490,6 +490,7 @@ int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
EXPORT_SYMBOL(bt_sock_ioctl);
/* This function expects the sk lock to be held when called */
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
{
DECLARE_WAITQUEUE(wait, current);
......@@ -525,6 +526,46 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
}
EXPORT_SYMBOL(bt_sock_wait_state);
/* This function expects the sk lock to be held when called */
int bt_sock_wait_ready(struct sock *sk, unsigned long flags)
{
DECLARE_WAITQUEUE(wait, current);
unsigned long timeo;
int err = 0;
BT_DBG("sk %p", sk);
timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
add_wait_queue(sk_sleep(sk), &wait);
set_current_state(TASK_INTERRUPTIBLE);
while (test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags)) {
if (!timeo) {
err = -EAGAIN;
break;
}
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
break;
}
release_sock(sk);
timeo = schedule_timeout(timeo);
lock_sock(sk);
set_current_state(TASK_INTERRUPTIBLE);
err = sock_error(sk);
if (err)
break;
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(sk), &wait);
return err;
}
EXPORT_SYMBOL(bt_sock_wait_ready);
#ifdef CONFIG_PROC_FS
struct bt_seq_state {
struct bt_sock_list *l;
......
......@@ -518,6 +518,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
list_for_each_entry(d, &hci_dev_list, list) {
if (!test_bit(HCI_UP, &d->flags) ||
test_bit(HCI_RAW, &d->flags) ||
test_bit(HCI_USER_CHANNEL, &d->dev_flags) ||
d->dev_type != HCI_BREDR)
continue;
......@@ -580,6 +581,9 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
{
struct hci_conn *acl;
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return ERR_PTR(-ENOTSUPP);
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
acl = hci_conn_add(hdev, ACL_LINK, dst);
......
This diff is collapsed.
......@@ -297,6 +297,11 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
goto done;
}
/* We need to ensure that we set this back on if someone changed
* the scan mode through a raw HCI socket.
*/
set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
......@@ -994,20 +999,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
return;
if (!status) {
if (sent->le)
if (sent->le) {
hdev->features[1][0] |= LMP_HOST_LE;
else
set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
} else {
hdev->features[1][0] &= ~LMP_HOST_LE;
clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
}
if (sent->simul)
hdev->features[1][0] |= LMP_HOST_LE_BREDR;
else
hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
}
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
!test_bit(HCI_INIT, &hdev->flags))
mgmt_le_enable_complete(hdev, sent->le, status);
}
static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
......@@ -3557,7 +3562,11 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
cp.handle = cpu_to_le16(conn->handle);
if (ltk->authenticated)
conn->sec_level = BT_SECURITY_HIGH;
conn->pending_sec_level = BT_SECURITY_HIGH;
else
conn->pending_sec_level = BT_SECURITY_MEDIUM;
conn->enc_key_size = ltk->enc_size;
hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
......
......@@ -66,6 +66,46 @@ static struct bt_sock_list hci_sk_list = {
.lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock)
};
static bool is_filtered_packet(struct sock *sk, struct sk_buff *skb)
{
struct hci_filter *flt;
int flt_type, flt_event;
/* Apply filter */
flt = &hci_pi(sk)->filter;
if (bt_cb(skb)->pkt_type == HCI_VENDOR_PKT)
flt_type = 0;
else
flt_type = bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS;
if (!test_bit(flt_type, &flt->type_mask))
return true;
/* Extra filter for event packets only */
if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT)
return false;
flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
if (!hci_test_bit(flt_event, &flt->event_mask))
return true;
/* Check filter only when opcode is set */
if (!flt->opcode)
return false;
if (flt_event == HCI_EV_CMD_COMPLETE &&
flt->opcode != get_unaligned((__le16 *)(skb->data + 3)))
return true;
if (flt_event == HCI_EV_CMD_STATUS &&
flt->opcode != get_unaligned((__le16 *)(skb->data + 4)))
return true;
return false;
}
/* Send frame to RAW socket */
void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
{
......@@ -77,7 +117,6 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
read_lock(&hci_sk_list.lock);
sk_for_each(sk, &hci_sk_list.head) {
struct hci_filter *flt;
struct sk_buff *nskb;
if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
......@@ -87,31 +126,19 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
if (skb->sk == sk)
continue;
if (hci_pi(sk)->channel != HCI_CHANNEL_RAW)
continue;
/* Apply filter */
flt = &hci_pi(sk)->filter;
if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS),
&flt->type_mask))
continue;
if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
if (!hci_test_bit(evt, &flt->event_mask))
if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) {
if (is_filtered_packet(sk, skb))
continue;
if (flt->opcode &&
((evt == HCI_EV_CMD_COMPLETE &&
flt->opcode !=
get_unaligned((__le16 *)(skb->data + 3))) ||
(evt == HCI_EV_CMD_STATUS &&
flt->opcode !=
get_unaligned((__le16 *)(skb->data + 4)))))
} else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
if (!bt_cb(skb)->incoming)
continue;
if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT &&
bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
bt_cb(skb)->pkt_type != HCI_SCODATA_PKT)
continue;
} else {
/* Don't send frame to other channel types */
continue;
}
if (!skb_copy) {
......@@ -426,6 +453,12 @@ static int hci_sock_release(struct socket *sock)
bt_sock_unlink(&hci_sk_list, sk);
if (hdev) {
if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
mgmt_index_added(hdev);
clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags);
hci_dev_close(hdev->id);
}
atomic_dec(&hdev->promisc);
hci_dev_put(hdev);
}
......@@ -482,6 +515,9 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
if (!hdev)
return -EBADFD;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
return -EBUSY;
switch (cmd) {
case HCISETRAW:
if (!capable(CAP_NET_ADMIN))
......@@ -512,23 +548,32 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
if (!capable(CAP_NET_ADMIN))
return -EPERM;
return hci_sock_blacklist_del(hdev, (void __user *) arg);
default:
if (hdev->ioctl)
return hdev->ioctl(hdev, cmd, arg);
return -EINVAL;
}
if (hdev->ioctl)
return hdev->ioctl(hdev, cmd, arg);
return -EINVAL;
}
static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg)
{
struct sock *sk = sock->sk;
void __user *argp = (void __user *) arg;
struct sock *sk = sock->sk;
int err;
BT_DBG("cmd %x arg %lx", cmd, arg);
lock_sock(sk);
if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
err = -EBADFD;
goto done;
}
release_sock(sk);
switch (cmd) {
case HCIGETDEVLIST:
return hci_get_dev_list(argp);
......@@ -573,13 +618,15 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
case HCIINQUIRY:
return hci_inquiry(argp);
default:
lock_sock(sk);
err = hci_sock_bound_ioctl(sk, cmd, arg);
release_sock(sk);
return err;
}
lock_sock(sk);
err = hci_sock_bound_ioctl(sk, cmd, arg);
done:
release_sock(sk);
return err;
}
static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
......@@ -629,6 +676,56 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
hci_pi(sk)->hdev = hdev;
break;
case HCI_CHANNEL_USER:
if (hci_pi(sk)->hdev) {
err = -EALREADY;
goto done;
}
if (haddr.hci_dev == HCI_DEV_NONE) {
err = -EINVAL;
goto done;
}
if (!capable(CAP_NET_ADMIN)) {
err = -EPERM;
goto done;
}
hdev = hci_dev_get(haddr.hci_dev);
if (!hdev) {
err = -ENODEV;
goto done;
}
if (test_bit(HCI_UP, &hdev->flags) ||
test_bit(HCI_INIT, &hdev->flags) ||
test_bit(HCI_SETUP, &hdev->dev_flags)) {
err = -EBUSY;
hci_dev_put(hdev);
goto done;
}
if (test_and_set_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
err = -EUSERS;
hci_dev_put(hdev);
goto done;
}
mgmt_index_removed(hdev);
err = hci_dev_open(hdev->id);
if (err) {
clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags);
hci_dev_put(hdev);
goto done;
}
atomic_inc(&hdev->promisc);
hci_pi(sk)->hdev = hdev;
break;
case HCI_CHANNEL_CONTROL:
if (haddr.hci_dev != HCI_DEV_NONE) {
err = -EINVAL;
......@@ -677,22 +774,30 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr,
{
struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
struct sock *sk = sock->sk;
struct hci_dev *hdev = hci_pi(sk)->hdev;
struct hci_dev *hdev;
int err = 0;
BT_DBG("sock %p sk %p", sock, sk);
if (!hdev)
return -EBADFD;
if (peer)
return -EOPNOTSUPP;
lock_sock(sk);
hdev = hci_pi(sk)->hdev;
if (!hdev) {
err = -EBADFD;
goto done;
}
*addr_len = sizeof(*haddr);
haddr->hci_family = AF_BLUETOOTH;
haddr->hci_dev = hdev->id;
haddr->hci_channel= 0;
haddr->hci_channel= hci_pi(sk)->channel;
done:
release_sock(sk);
return 0;
return err;
}
static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg,
......@@ -767,6 +872,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
case HCI_CHANNEL_RAW:
hci_sock_cmsg(sk, msg, skb);
break;
case HCI_CHANNEL_USER:
case HCI_CHANNEL_CONTROL:
case HCI_CHANNEL_MONITOR:
sock_recv_timestamp(msg, sk, skb);
......@@ -801,6 +907,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
switch (hci_pi(sk)->channel) {
case HCI_CHANNEL_RAW:
case HCI_CHANNEL_USER:
break;
case HCI_CHANNEL_CONTROL:
err = mgmt_control(sk, msg, len);
......@@ -837,7 +944,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
skb_pull(skb, 1);
skb->dev = (void *) hdev;
if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
if (hci_pi(sk)->channel == HCI_CHANNEL_RAW &&
bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
u16 opcode = get_unaligned_le16(skb->data);
u16 ogf = hci_opcode_ogf(opcode);
u16 ocf = hci_opcode_ocf(opcode);
......@@ -868,6 +976,14 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
goto drop;
}
if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
err = -EINVAL;
goto drop;
}
skb_queue_tail(&hdev->raw_q, skb);
queue_work(hdev->workqueue, &hdev->tx_work);
}
......@@ -895,7 +1011,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
lock_sock(sk);
if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
err = -EINVAL;
err = -EBADFD;
goto done;
}
......@@ -981,7 +1097,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname,
lock_sock(sk);
if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
err = -EINVAL;
err = -EBADFD;
goto done;
}
......
This diff is collapsed.
......@@ -445,11 +445,6 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
break;
case BT_CHANNEL_POLICY:
if (!enable_hs) {
err = -ENOPROTOOPT;
break;
}
if (put_user(chan->chan_policy, (u32 __user *) optval))
err = -EFAULT;
break;
......@@ -720,11 +715,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
case BT_CHANNEL_POLICY:
if (!enable_hs) {
err = -ENOPROTOOPT;
break;
}
if (get_user(opt, (u32 __user *) optval)) {
err = -EFAULT;
break;
......@@ -777,6 +767,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
if (sk->sk_state != BT_CONNECTED)
return -ENOTCONN;
lock_sock(sk);
err = bt_sock_wait_ready(sk, msg->msg_flags);
release_sock(sk);
if (err)
return err;
l2cap_chan_lock(chan);
err = l2cap_chan_send(chan, msg, len, sk->sk_priority);
l2cap_chan_unlock(chan);
......@@ -799,8 +795,8 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
pi->chan->state = BT_CONFIG;
__l2cap_connect_rsp_defer(pi->chan);
release_sock(sk);
return 0;
err = 0;
goto done;
}
release_sock(sk);
......
This diff is collapsed.
......@@ -544,7 +544,7 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
struct sock *sk = sock->sk;
struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
struct sk_buff *skb;
int sent = 0;
int sent;
if (test_bit(RFCOMM_DEFER_SETUP, &d->flags))
return -ENOTCONN;
......@@ -559,6 +559,10 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
lock_sock(sk);
sent = bt_sock_wait_ready(sk, msg->msg_flags);
if (sent)
goto done;
while (len) {
size_t size = min_t(size_t, len, d->mtu);
int err;
......@@ -594,6 +598,7 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
len -= size;
}
done:
release_sock(sk);
return sent;
......
......@@ -569,7 +569,6 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
{
struct rfcomm_dev *dev = dlc->owner;
struct tty_struct *tty;
if (!dev)
return;
......@@ -581,38 +580,8 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
DPM_ORDER_DEV_AFTER_PARENT);
wake_up_interruptible(&dev->port.open_wait);
} else if (dlc->state == BT_CLOSED) {
tty = tty_port_tty_get(&dev->port);
if (!tty) {
if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
/* Drop DLC lock here to avoid deadlock
* 1. rfcomm_dev_get will take rfcomm_dev_lock
* but in rfcomm_dev_add there's lock order:
* rfcomm_dev_lock -> dlc lock
* 2. tty_port_put will deadlock if it's
* the last reference
*
* FIXME: when we release the lock anything
* could happen to dev, even its destruction
*/
rfcomm_dlc_unlock(dlc);
if (rfcomm_dev_get(dev->id) == NULL) {
rfcomm_dlc_lock(dlc);
return;
}
if (!test_and_set_bit(RFCOMM_TTY_RELEASED,
&dev->flags))
tty_port_put(&dev->port);
tty_port_put(&dev->port);
rfcomm_dlc_lock(dlc);
}
} else {
tty_hangup(tty);
tty_kref_put(tty);
}
}
} else if (dlc->state == BT_CLOSED)
tty_port_tty_hangup(&dev->port, false);
}
static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
......
......@@ -847,16 +847,27 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
{
__u8 code = skb->data[0];
__u8 reason;
struct hci_conn *hcon = conn->hcon;
__u8 code, reason;
int err = 0;
if (hcon->type != LE_LINK) {
kfree_skb(skb);
return -ENOTSUPP;
}
if (skb->len < 1) {
kfree_skb(skb);
return -EILSEQ;
}
if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) {
err = -ENOTSUPP;
reason = SMP_PAIRING_NOTSUPP;
goto done;
}
code = skb->data[0];
skb_pull(skb, sizeof(code));
/*
......
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