Commit 5f779bbd authored by John W. Linville's avatar John W. Linville
parents d7a4858c 5a13b095
......@@ -188,7 +188,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support
Marvell Bluetooth devices, such as 8688/8787.
Marvell Bluetooth devices, such as 8688/8787/8797.
Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module.
......@@ -201,8 +201,8 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently SD8688/SD8787 chipsets are
supported.
devices with SDIO interface. Currently SD8688/SD8787/SD8797
chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver
into the kernel or say M to compile it as module.
......
......@@ -65,7 +65,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
.io_port_1 = 0x01,
.io_port_2 = 0x02,
};
static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = {
static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
.cfg = 0x00,
.host_int_mask = 0x02,
.host_intstatus = 0x03,
......@@ -92,7 +92,14 @@ 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",
.reg = &btmrvl_reg_8787,
.reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.helper = NULL,
.firmware = "mrvl/sd8797_uapsta.bin",
.reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256,
};
......@@ -103,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8787 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
/* Marvell SD8797 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
{ } /* Terminating entry */
};
......@@ -1076,3 +1086,4 @@ MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE("sd8688_helper.bin");
MODULE_FIRMWARE("sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
......@@ -785,9 +785,8 @@ skip_waking:
usb_mark_last_busy(data->udev);
}
usb_free_urb(urb);
done:
usb_free_urb(urb);
return err;
}
......
......@@ -41,6 +41,8 @@
#define VERSION "1.3"
static bool amp;
struct vhci_data {
struct hci_dev *hdev;
......@@ -239,6 +241,9 @@ static int vhci_open(struct inode *inode, struct file *file)
hdev->bus = HCI_VIRTUAL;
hdev->driver_data = data;
if (amp)
hdev->dev_type = HCI_AMP;
hdev->open = vhci_open_dev;
hdev->close = vhci_close_dev;
hdev->flush = vhci_flush;
......@@ -303,6 +308,9 @@ static void __exit vhci_exit(void)
module_init(vhci_init);
module_exit(vhci_exit);
module_param(amp, bool, 0644);
MODULE_PARM_DESC(amp, "Create AMP controller device");
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
MODULE_VERSION(VERSION);
......
......@@ -36,6 +36,11 @@
#define PF_BLUETOOTH AF_BLUETOOTH
#endif
/* Bluetooth versions */
#define BLUETOOTH_VER_1_1 1
#define BLUETOOTH_VER_1_2 2
#define BLUETOOTH_VER_2_0 3
/* Reserv for core and drivers use */
#define BT_SKB_RESERVE 8
......
......@@ -88,6 +88,14 @@ enum {
HCI_RESET,
};
/*
* BR/EDR and/or LE controller flags: the flags defined here should represent
* states from the controller.
*/
enum {
HCI_LE_SCAN,
};
/* HCI ioctl defines */
#define HCIDEVUP _IOW('H', 201, int)
#define HCIDEVDOWN _IOW('H', 202, int)
......@@ -453,6 +461,14 @@ struct hci_rp_user_confirm_reply {
#define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d
#define HCI_OP_USER_PASSKEY_REPLY 0x042e
struct hci_cp_user_passkey_reply {
bdaddr_t bdaddr;
__le32 passkey;
} __packed;
#define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f
#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430
struct hci_cp_remote_oob_data_reply {
bdaddr_t bdaddr;
......@@ -669,6 +685,12 @@ struct hci_rp_read_local_oob_data {
#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58
#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66
struct hci_rp_read_flow_control_mode {
__u8 status;
__u8 mode;
} __packed;
#define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d
struct hci_cp_write_le_host_supported {
__u8 le;
......@@ -760,6 +782,15 @@ struct hci_rp_le_read_buffer_size {
__u8 le_max_pkt;
} __packed;
#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
struct hci_cp_le_set_scan_param {
__u8 type;
__le16 interval;
__le16 window;
__u8 own_address_type;
__u8 filter_policy;
} __packed;
#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
struct hci_cp_le_set_scan_enable {
__u8 enable;
......@@ -1076,6 +1107,11 @@ struct hci_ev_user_confirm_req {
__le32 passkey;
} __packed;
#define HCI_EV_USER_PASSKEY_REQUEST 0x34
struct hci_ev_user_passkey_req {
bdaddr_t bdaddr;
} __packed;
#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35
struct hci_ev_remote_oob_data_request {
bdaddr_t bdaddr;
......@@ -1331,4 +1367,6 @@ struct hci_inquiry_req {
};
#define IREQ_CACHE_FLUSH 0x0001
extern int enable_hs;
#endif /* __HCI_H */
......@@ -170,6 +170,8 @@ struct hci_dev {
__u32 amp_max_flush_to;
__u32 amp_be_flush_to;
__u8 flow_ctl_mode;
unsigned int auto_accept_delay;
unsigned long quirks;
......@@ -250,6 +252,8 @@ struct hci_dev {
struct module *owner;
unsigned long dev_flags;
int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
......@@ -917,11 +921,13 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
u8 persistent);
int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_disconnect_failed(struct hci_dev *hdev);
int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type,
u8 status);
int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type);
int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type);
int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status);
int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 status);
int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure);
int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status);
......@@ -933,14 +939,20 @@ int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status);
int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 status);
int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr);
int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status);
int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 status);
int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status);
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_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type,
u8 *dev_class, s8 rssi, u8 *eir);
int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir);
int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name);
int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status);
int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
......
......@@ -792,7 +792,6 @@ static inline __u8 __ctrl_size(struct l2cap_chan *chan)
}
extern int disable_ertm;
extern int enable_hs;
int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
......@@ -810,5 +809,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan);
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);
int l2cap_chan_check_security(struct l2cap_chan *chan);
#endif /* __L2CAP_H */
......@@ -23,6 +23,23 @@
#define MGMT_INDEX_NONE 0xFFFF
#define MGMT_STATUS_SUCCESS 0x00
#define MGMT_STATUS_UNKNOWN_COMMAND 0x01
#define MGMT_STATUS_NOT_CONNECTED 0x02
#define MGMT_STATUS_FAILED 0x03
#define MGMT_STATUS_CONNECT_FAILED 0x04
#define MGMT_STATUS_AUTH_FAILED 0x05
#define MGMT_STATUS_NOT_PAIRED 0x06
#define MGMT_STATUS_NO_RESOURCES 0x07
#define MGMT_STATUS_TIMEOUT 0x08
#define MGMT_STATUS_ALREADY_CONNECTED 0x09
#define MGMT_STATUS_BUSY 0x0a
#define MGMT_STATUS_REJECTED 0x0b
#define MGMT_STATUS_NOT_SUPPORTED 0x0c
#define MGMT_STATUS_INVALID_PARAMS 0x0d
#define MGMT_STATUS_DISCONNECTED 0x0e
#define MGMT_STATUS_NOT_POWERED 0x0f
struct mgmt_hdr {
__le16 opcode;
__le16 index;
......@@ -119,6 +136,10 @@ struct mgmt_cp_remove_keys {
bdaddr_t bdaddr;
__u8 disconnect;
} __packed;
struct mgmt_rp_remove_keys {
bdaddr_t bdaddr;
__u8 status;
};
#define MGMT_OP_DISCONNECT 0x000F
struct mgmt_cp_disconnect {
......@@ -126,11 +147,12 @@ struct mgmt_cp_disconnect {
} __packed;
struct mgmt_rp_disconnect {
bdaddr_t bdaddr;
__u8 status;
} __packed;
#define MGMT_ADDR_BREDR 0x00
#define MGMT_ADDR_LE 0x01
#define MGMT_ADDR_BREDR_LE 0x02
#define MGMT_ADDR_LE_PUBLIC 0x01
#define MGMT_ADDR_LE_RANDOM 0x02
#define MGMT_ADDR_INVALID 0xff
struct mgmt_addr_info {
......@@ -167,11 +189,11 @@ struct mgmt_cp_set_io_capability {
#define MGMT_OP_PAIR_DEVICE 0x0014
struct mgmt_cp_pair_device {
bdaddr_t bdaddr;
struct mgmt_addr_info addr;
__u8 io_cap;
} __packed;
struct mgmt_rp_pair_device {
bdaddr_t bdaddr;
struct mgmt_addr_info addr;
__u8 status;
} __packed;
......@@ -210,6 +232,9 @@ struct mgmt_cp_remove_remote_oob_data {
} __packed;
#define MGMT_OP_START_DISCOVERY 0x001B
struct mgmt_cp_start_discovery {
__u8 type;
} __packed;
#define MGMT_OP_STOP_DISCOVERY 0x001C
......@@ -228,6 +253,17 @@ struct mgmt_cp_set_fast_connectable {
__u8 enable;
} __packed;
#define MGMT_OP_USER_PASSKEY_REPLY 0x0020
struct mgmt_cp_user_passkey_reply {
bdaddr_t bdaddr;
__le32 passkey;
} __packed;
#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x0021
struct mgmt_cp_user_passkey_neg_reply {
bdaddr_t bdaddr;
} __packed;
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
......@@ -322,3 +358,8 @@ struct mgmt_ev_device_blocked {
struct mgmt_ev_device_unblocked {
bdaddr_t bdaddr;
} __packed;
#define MGMT_EV_USER_PASSKEY_REQUEST 0x0017
struct mgmt_ev_user_passkey_request {
bdaddr_t bdaddr;
} __packed;
......@@ -77,17 +77,12 @@ static struct bnep_session *__bnep_get_session(u8 *dst)
static void __bnep_link_session(struct bnep_session *s)
{
/* It's safe to call __module_get() here because sessions are added
by the socket layer which has to hold the reference to this module.
*/
__module_get(THIS_MODULE);
list_add(&s->list, &bnep_session_list);
}
static void __bnep_unlink_session(struct bnep_session *s)
{
list_del(&s->list);
module_put(THIS_MODULE);
}
static int bnep_send(struct bnep_session *s, void *data, size_t len)
......@@ -528,6 +523,7 @@ static int bnep_session(void *arg)
up_write(&bnep_session_sem);
free_netdev(dev);
module_put_and_exit(0);
return 0;
}
......@@ -614,9 +610,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
__bnep_link_session(s);
__module_get(THIS_MODULE);
s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name);
if (IS_ERR(s->task)) {
/* Session thread start failed, gotta cleanup. */
module_put(THIS_MODULE);
unregister_netdev(dev);
__bnep_unlink_session(s);
err = PTR_ERR(s->task);
......
......@@ -65,14 +65,12 @@ static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr)
static void __cmtp_link_session(struct cmtp_session *session)
{
__module_get(THIS_MODULE);
list_add(&session->list, &cmtp_session_list);
}
static void __cmtp_unlink_session(struct cmtp_session *session)
{
list_del(&session->list);
module_put(THIS_MODULE);
}
static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci)
......@@ -325,6 +323,7 @@ static int cmtp_session(void *arg)
up_write(&cmtp_session_sem);
kfree(session);
module_put_and_exit(0);
return 0;
}
......@@ -374,9 +373,11 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
__cmtp_link_session(session);
__module_get(THIS_MODULE);
session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d",
session->num);
if (IS_ERR(session->task)) {
module_put(THIS_MODULE);
err = PTR_ERR(session->task);
goto unlink;
}
......
......@@ -123,7 +123,7 @@ static void hci_acl_connect_cancel(struct hci_conn *conn)
BT_DBG("%p", conn);
if (conn->hdev->hci_ver < 2)
if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2)
return;
bacpy(&cp.bdaddr, &conn->dst);
......
......@@ -54,6 +54,8 @@
#define AUTO_OFF_TIMEOUT 2000
int enable_hs;
static void hci_cmd_task(unsigned long arg);
static void hci_rx_task(unsigned long arg);
static void hci_tx_task(unsigned long arg);
......@@ -228,18 +230,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
#if 0
/* Host buffer size */
{
struct hci_cp_host_buffer_size cp;
cp.acl_mtu = cpu_to_le16(HCI_MAX_ACL_SIZE);
cp.sco_mtu = HCI_MAX_SCO_SIZE;
cp.acl_max_pkt = cpu_to_le16(0xffff);
cp.sco_max_pkt = cpu_to_le16(0xffff);
hci_send_cmd(hdev, HCI_OP_HOST_BUFFER_SIZE, sizeof(cp), &cp);
}
#endif
/* Read BD Address */
hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
......@@ -521,8 +511,9 @@ int hci_dev_open(__u16 dev)
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
set_bit(HCI_RAW, &hdev->flags);
/* Treat all non BR/EDR controllers as raw devices for now */
if (hdev->dev_type != HCI_BREDR)
/* Treat all non BR/EDR controllers as raw devices if
enable_hs is not set */
if (hdev->dev_type != HCI_BREDR && !enable_hs)
set_bit(HCI_RAW, &hdev->flags);
if (hdev->open(hdev)) {
......@@ -1336,14 +1327,12 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct bdaddr_list *entry;
if (bacmp(bdaddr, BDADDR_ANY) == 0) {
if (bacmp(bdaddr, BDADDR_ANY) == 0)
return hci_blacklist_clear(hdev);
}
entry = hci_blacklist_lookup(hdev, bdaddr);
if (!entry) {
if (!entry)
return -ENOENT;
}
list_del(&entry->list);
kfree(entry);
......@@ -1451,12 +1440,13 @@ int hci_register_dev(struct hci_dev *hdev)
sprintf(hdev->name, "hci%d", id);
hdev->id = id;
list_add(&hdev->list, head);
list_add_tail(&hdev->list, head);
atomic_set(&hdev->refcnt, 1);
spin_lock_init(&hdev->lock);
hdev->flags = 0;
hdev->dev_flags = 0;
hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
hdev->esco_type = (ESCO_HV1);
hdev->link_mode = (HCI_LM_ACCEPT);
......@@ -2614,3 +2604,6 @@ int hci_cancel_inquiry(struct hci_dev *hdev)
return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
}
module_param(enable_hs, bool, 0644);
MODULE_PARM_DESC(enable_hs, "Enable High Speed");
......@@ -55,8 +55,12 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s status 0x%x", hdev->name, status);
if (status)
if (status) {
hci_dev_lock(hdev);
mgmt_stop_discovery_failed(hdev, status);
hci_dev_unlock(hdev);
return;
}
clear_bit(HCI_INQUIRY, &hdev->flags);
......@@ -190,6 +194,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
clear_bit(HCI_RESET, &hdev->flags);
hci_req_complete(hdev, HCI_OP_RESET, status);
hdev->dev_flags = 0;
}
static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
......@@ -494,7 +500,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
/* CSR 1.1 dongles does not accept any bitfield so don't try to set
* any event mask for pre 1.2 devices */
if (hdev->lmp_ver <= 1)
if (hdev->hci_ver < BLUETOOTH_VER_1_2)
return;
events[4] |= 0x01; /* Flow Specification Complete */
......@@ -558,7 +564,7 @@ static void hci_setup(struct hci_dev *hdev)
{
hci_setup_event_mask(hdev);
if (hdev->lmp_ver > 1)
if (hdev->hci_ver > BLUETOOTH_VER_1_1)
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
if (hdev->features[6] & LMP_SIMPLE_PAIR) {
......@@ -713,6 +719,21 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
}
static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
struct sk_buff *skb)
{
struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
BT_DBG("%s status 0x%x", hdev->name, rp->status);
if (rp->status)
return;
hdev->flow_ctl_mode = rp->mode;
hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
}
static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_read_buffer_size *rp = (void *) skb->data;
......@@ -927,6 +948,37 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
hci_dev_unlock(hdev);
}
static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
BT_DBG("%s status 0x%x", hdev->name, rp->status);
hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
rp->status);
hci_dev_unlock(hdev);
}
static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
BT_DBG("%s status 0x%x", hdev->name, rp->status);
hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
rp->status);
hci_dev_unlock(hdev);
}
static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
struct sk_buff *skb)
{
......@@ -940,6 +992,13 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
hci_dev_unlock(hdev);
}
static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
BT_DBG("%s status 0x%x", hdev->name