You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== pull request: bluetooth-next 2015-01-16 Here are some more bluetooth & ieee802154 patches intended for 3.20: - Refactoring & cleanups of ieee802154 & 6lowpan code - Various fixes to the btmrvl driver - Fixes for Bluetooth Low Energy Privacy feature handling - Added build-time sanity checks for sockaddr sizes - Fixes for Security Manager registration on LE-only controllers - Refactoring of broken inquiry mode handling to a generic quirk Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -28,9 +28,9 @@
|
||||
#define BTM_UPLD_SIZE 2312
|
||||
|
||||
/* Time to wait until Host Sleep state change in millisecond */
|
||||
#define WAIT_UNTIL_HS_STATE_CHANGED 5000
|
||||
#define WAIT_UNTIL_HS_STATE_CHANGED msecs_to_jiffies(5000)
|
||||
/* Time to wait for command response in millisecond */
|
||||
#define WAIT_UNTIL_CMD_RESP 5000
|
||||
#define WAIT_UNTIL_CMD_RESP msecs_to_jiffies(5000)
|
||||
|
||||
enum rdwr_status {
|
||||
RDWR_STATUS_SUCCESS = 0,
|
||||
@@ -104,6 +104,7 @@ struct btmrvl_private {
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void *debugfs_data;
|
||||
#endif
|
||||
bool surprise_removed;
|
||||
};
|
||||
|
||||
#define MRVL_VENDOR_PKT 0xFE
|
||||
|
||||
@@ -178,6 +178,11 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
|
||||
struct sk_buff *skb;
|
||||
struct hci_command_hdr *hdr;
|
||||
|
||||
if (priv->surprise_removed) {
|
||||
BT_ERR("Card is removed");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
@@ -202,10 +207,14 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
|
||||
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)))
|
||||
priv->adapter->cmd_complete ||
|
||||
priv->surprise_removed,
|
||||
WAIT_UNTIL_CMD_RESP))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (priv->surprise_removed)
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -287,9 +296,10 @@ int btmrvl_enable_hs(struct btmrvl_private *priv)
|
||||
}
|
||||
|
||||
ret = wait_event_interruptible_timeout(adapter->event_hs_wait_q,
|
||||
adapter->hs_state,
|
||||
msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED));
|
||||
if (ret < 0) {
|
||||
adapter->hs_state ||
|
||||
priv->surprise_removed,
|
||||
WAIT_UNTIL_HS_STATE_CHANGED);
|
||||
if (ret < 0 || priv->surprise_removed) {
|
||||
BT_ERR("event_hs_wait_q terminated (%d): %d,%d,%d",
|
||||
ret, adapter->hs_state, adapter->ps_state,
|
||||
adapter->wakeup_tries);
|
||||
@@ -538,8 +548,11 @@ static int btmrvl_check_device_tree(struct btmrvl_private *priv)
|
||||
static int btmrvl_setup(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
||||
int ret;
|
||||
|
||||
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
||||
ret = btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->btmrvl_dev.gpio_gap = 0xffff;
|
||||
|
||||
@@ -597,7 +610,7 @@ static int btmrvl_service_main_thread(void *data)
|
||||
add_wait_queue(&thread->wait_q, &wait);
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (kthread_should_stop()) {
|
||||
if (kthread_should_stop() || priv->surprise_removed) {
|
||||
BT_DBG("main_thread: break from main thread");
|
||||
break;
|
||||
}
|
||||
@@ -616,6 +629,11 @@ static int btmrvl_service_main_thread(void *data)
|
||||
|
||||
BT_DBG("main_thread woke up");
|
||||
|
||||
if (kthread_should_stop() || priv->surprise_removed) {
|
||||
BT_DBG("main_thread: break from main thread");
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
if (adapter->int_count) {
|
||||
adapter->int_count = 0;
|
||||
|
||||
@@ -573,7 +573,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||
offset += txlen;
|
||||
} while (true);
|
||||
|
||||
BT_DBG("FW download over, size %d bytes", offset);
|
||||
BT_INFO("FW download over, size %d bytes", offset);
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -798,6 +798,9 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
|
||||
|
||||
priv = card->priv;
|
||||
|
||||
if (priv->surprise_removed)
|
||||
return;
|
||||
|
||||
if (card->reg->int_read_to_clear)
|
||||
ret = btmrvl_sdio_read_to_clear(card, &ireg);
|
||||
else
|
||||
@@ -1466,6 +1469,7 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
|
||||
btmrvl_sdio_disable_host_int(card);
|
||||
}
|
||||
BT_DBG("unregester dev");
|
||||
card->priv->surprise_removed = true;
|
||||
btmrvl_sdio_unregister_dev(card);
|
||||
btmrvl_remove_card(card->priv);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ static struct usb_driver btusb_driver;
|
||||
#define BTUSB_INTEL_BOOT 0x200
|
||||
#define BTUSB_BCM_PATCHRAM 0x400
|
||||
#define BTUSB_MARVELL 0x800
|
||||
#define BTUSB_AVM 0x1000
|
||||
#define BTUSB_SWAVE 0x1000
|
||||
|
||||
static const struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
@@ -86,7 +86,7 @@ static const struct usb_device_id btusb_table[] = {
|
||||
{ USB_DEVICE(0x05ac, 0x8281) },
|
||||
|
||||
/* AVM BlueFRITZ! USB v2.0 */
|
||||
{ USB_DEVICE(0x057c, 0x3800), .driver_info = BTUSB_AVM },
|
||||
{ USB_DEVICE(0x057c, 0x3800), .driver_info = BTUSB_SWAVE },
|
||||
|
||||
/* Bluetooth Ultraport Module from IBM */
|
||||
{ USB_DEVICE(0x04bf, 0x030a) },
|
||||
@@ -238,6 +238,9 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
/* CONWISE Technology based adapters with buggy SCO support */
|
||||
{ USB_DEVICE(0x0e5e, 0x6622), .driver_info = BTUSB_BROKEN_ISOC },
|
||||
|
||||
/* Roper Class 1 Bluetooth Dongle (Silicon Wave based) */
|
||||
{ USB_DEVICE(0x1300, 0x0001), .driver_info = BTUSB_SWAVE },
|
||||
|
||||
/* Digianswer devices */
|
||||
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
|
||||
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
|
||||
@@ -306,6 +309,7 @@ struct btusb_data {
|
||||
int isoc_altsetting;
|
||||
int suspend_count;
|
||||
|
||||
int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
|
||||
};
|
||||
|
||||
@@ -371,7 +375,7 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
|
||||
|
||||
if (bt_cb(skb)->expect == 0) {
|
||||
/* Complete frame */
|
||||
hci_recv_frame(data->hdev, skb);
|
||||
data->recv_event(data->hdev, skb);
|
||||
skb = NULL;
|
||||
}
|
||||
}
|
||||
@@ -2045,6 +2049,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
init_usb_anchor(&data->isoc_anchor);
|
||||
spin_lock_init(&data->rxlock);
|
||||
|
||||
data->recv_event = hci_recv_frame;
|
||||
data->recv_bulk = btusb_recv_bulk;
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
@@ -2081,8 +2086,10 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
if (id->driver_info & BTUSB_MARVELL)
|
||||
hdev->set_bdaddr = btusb_set_bdaddr_marvell;
|
||||
|
||||
if (id->driver_info & BTUSB_AVM)
|
||||
if (id->driver_info & BTUSB_SWAVE) {
|
||||
set_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks);
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_INTEL_BOOT)
|
||||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
||||
|
||||
@@ -273,7 +273,7 @@ struct l2cap_ctrl {
|
||||
|
||||
struct hci_dev;
|
||||
|
||||
typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status);
|
||||
typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status, u16 opcode);
|
||||
|
||||
struct hci_req_ctrl {
|
||||
bool start;
|
||||
|
||||
@@ -102,6 +102,18 @@ enum {
|
||||
*/
|
||||
HCI_QUIRK_FIXUP_BUFFER_SIZE,
|
||||
|
||||
/* When this quirk is set, then a controller that does not
|
||||
* indicate support for Inquiry Result with RSSI is assumed to
|
||||
* support it anyway. Some early Bluetooth 1.2 controllers had
|
||||
* wrongly configured local features that will require forcing
|
||||
* them to enable this mode. Getting RSSI information with the
|
||||
* inquiry responses is preferred since it allows for a better
|
||||
* user expierence.
|
||||
*
|
||||
* This quirk must be set before hci_register_dev is called.
|
||||
*/
|
||||
HCI_QUIRK_FIXUP_INQUIRY_MODE,
|
||||
|
||||
/* When this quirk is set, then the HCI Read Local Supported
|
||||
* Commands command is not supported. In general Bluetooth 1.2
|
||||
* and later controllers should support this command. However
|
||||
@@ -172,8 +184,7 @@ enum {
|
||||
*/
|
||||
enum {
|
||||
HCI_DUT_MODE,
|
||||
HCI_FORCE_SC,
|
||||
HCI_FORCE_LESC,
|
||||
HCI_FORCE_BREDR_SMP,
|
||||
HCI_FORCE_STATIC_ADDR,
|
||||
};
|
||||
|
||||
@@ -844,11 +855,26 @@ struct hci_cp_set_event_flt {
|
||||
#define HCI_CONN_SETUP_AUTO_OFF 0x01
|
||||
#define HCI_CONN_SETUP_AUTO_ON 0x02
|
||||
|
||||
#define HCI_OP_READ_STORED_LINK_KEY 0x0c0d
|
||||
struct hci_cp_read_stored_link_key {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 read_all;
|
||||
} __packed;
|
||||
struct hci_rp_read_stored_link_key {
|
||||
__u8 status;
|
||||
__u8 max_keys;
|
||||
__u8 num_keys;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_DELETE_STORED_LINK_KEY 0x0c12
|
||||
struct hci_cp_delete_stored_link_key {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 delete_all;
|
||||
} __packed;
|
||||
struct hci_rp_delete_stored_link_key {
|
||||
__u8 status;
|
||||
__u8 num_keys;
|
||||
} __packed;
|
||||
|
||||
#define HCI_MAX_NAME_LENGTH 248
|
||||
|
||||
|
||||
@@ -205,6 +205,8 @@ struct hci_dev {
|
||||
__u16 lmp_subver;
|
||||
__u16 voice_setting;
|
||||
__u8 num_iac;
|
||||
__u8 stored_max_keys;
|
||||
__u8 stored_num_keys;
|
||||
__u8 io_capability;
|
||||
__s8 inq_tx_power;
|
||||
__u16 page_scan_interval;
|
||||
@@ -779,7 +781,6 @@ int hci_conn_check_link_mode(struct hci_conn *conn);
|
||||
int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
|
||||
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type,
|
||||
bool initiator);
|
||||
int hci_conn_change_link_key(struct hci_conn *conn);
|
||||
int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
|
||||
|
||||
void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
|
||||
@@ -1017,8 +1018,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
|
||||
|
||||
#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
|
||||
!test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
||||
#define bredr_sc_enabled(dev) ((lmp_sc_capable(dev) || \
|
||||
test_bit(HCI_FORCE_SC, &(dev)->dbg_flags)) && \
|
||||
#define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \
|
||||
test_bit(HCI_SC_ENABLED, &(dev)->dev_flags))
|
||||
|
||||
/* ----- HCI protocols ----- */
|
||||
|
||||
+31
-35
@@ -31,7 +31,7 @@
|
||||
|
||||
#define VERSION "0.1"
|
||||
|
||||
static struct dentry *lowpan_psm_debugfs;
|
||||
static struct dentry *lowpan_enable_debugfs;
|
||||
static struct dentry *lowpan_control_debugfs;
|
||||
|
||||
#define IFACE_NAME_TEMPLATE "bt%d"
|
||||
@@ -55,11 +55,7 @@ struct skb_cb {
|
||||
static LIST_HEAD(bt_6lowpan_devices);
|
||||
static DEFINE_SPINLOCK(devices_lock);
|
||||
|
||||
/* If psm is set to 0 (default value), then 6lowpan is disabled.
|
||||
* Other values are used to indicate a Protocol Service Multiplexer
|
||||
* value for 6lowpan.
|
||||
*/
|
||||
static u16 psm_6lowpan;
|
||||
static bool enable_6lowpan;
|
||||
|
||||
/* We are listening incoming connections via this channel
|
||||
*/
|
||||
@@ -761,7 +757,7 @@ static bool is_bt_6lowpan(struct hci_conn *hcon)
|
||||
if (hcon->type != LE_LINK)
|
||||
return false;
|
||||
|
||||
if (!psm_6lowpan)
|
||||
if (!enable_6lowpan)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -1085,7 +1081,7 @@ static int bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type)
|
||||
if (!pchan)
|
||||
return -EINVAL;
|
||||
|
||||
err = l2cap_chan_connect(pchan, cpu_to_le16(psm_6lowpan), 0,
|
||||
err = l2cap_chan_connect(pchan, cpu_to_le16(L2CAP_PSM_IPSP), 0,
|
||||
addr, dst_type);
|
||||
|
||||
BT_DBG("chan %p err %d", pchan, err);
|
||||
@@ -1118,7 +1114,7 @@ static struct l2cap_chan *bt_6lowpan_listen(void)
|
||||
struct l2cap_chan *pchan;
|
||||
int err;
|
||||
|
||||
if (psm_6lowpan == 0)
|
||||
if (!enable_6lowpan)
|
||||
return NULL;
|
||||
|
||||
pchan = chan_get();
|
||||
@@ -1130,10 +1126,9 @@ static struct l2cap_chan *bt_6lowpan_listen(void)
|
||||
|
||||
atomic_set(&pchan->nesting, L2CAP_NESTING_PARENT);
|
||||
|
||||
BT_DBG("psm 0x%04x chan %p src type %d", psm_6lowpan, pchan,
|
||||
pchan->src_type);
|
||||
BT_DBG("chan %p src type %d", pchan, pchan->src_type);
|
||||
|
||||
err = l2cap_add_psm(pchan, addr, cpu_to_le16(psm_6lowpan));
|
||||
err = l2cap_add_psm(pchan, addr, cpu_to_le16(L2CAP_PSM_IPSP));
|
||||
if (err) {
|
||||
l2cap_chan_put(pchan);
|
||||
BT_ERR("psm cannot be added err %d", err);
|
||||
@@ -1219,22 +1214,23 @@ static void disconnect_all_peers(void)
|
||||
spin_unlock(&devices_lock);
|
||||
}
|
||||
|
||||
struct set_psm {
|
||||
struct set_enable {
|
||||
struct work_struct work;
|
||||
u16 psm;
|
||||
bool flag;
|
||||
};
|
||||
|
||||
static void do_psm_set(struct work_struct *work)
|
||||
static void do_enable_set(struct work_struct *work)
|
||||
{
|
||||
struct set_psm *set_psm = container_of(work, struct set_psm, work);
|
||||
struct set_enable *set_enable = container_of(work,
|
||||
struct set_enable, work);
|
||||
|
||||
if (set_psm->psm == 0 || psm_6lowpan != set_psm->psm)
|
||||
if (!set_enable->flag || enable_6lowpan != set_enable->flag)
|
||||
/* Disconnect existing connections if 6lowpan is
|
||||
* disabled (psm = 0), or if psm changes.
|
||||
* disabled
|
||||
*/
|
||||
disconnect_all_peers();
|
||||
|
||||
psm_6lowpan = set_psm->psm;
|
||||
enable_6lowpan = set_enable->flag;
|
||||
|
||||
if (listen_chan) {
|
||||
l2cap_chan_close(listen_chan, 0);
|
||||
@@ -1243,33 +1239,33 @@ static void do_psm_set(struct work_struct *work)
|
||||
|
||||
listen_chan = bt_6lowpan_listen();
|
||||
|
||||
kfree(set_psm);
|
||||
kfree(set_enable);
|
||||
}
|
||||
|
||||
static int lowpan_psm_set(void *data, u64 val)
|
||||
static int lowpan_enable_set(void *data, u64 val)
|
||||
{
|
||||
struct set_psm *set_psm;
|
||||
struct set_enable *set_enable;
|
||||
|
||||
set_psm = kzalloc(sizeof(*set_psm), GFP_KERNEL);
|
||||
if (!set_psm)
|
||||
set_enable = kzalloc(sizeof(*set_enable), GFP_KERNEL);
|
||||
if (!set_enable)
|
||||
return -ENOMEM;
|
||||
|
||||
set_psm->psm = val;
|
||||
INIT_WORK(&set_psm->work, do_psm_set);
|
||||
set_enable->flag = !!val;
|
||||
INIT_WORK(&set_enable->work, do_enable_set);
|
||||
|
||||
schedule_work(&set_psm->work);
|
||||
schedule_work(&set_enable->work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lowpan_psm_get(void *data, u64 *val)
|
||||
static int lowpan_enable_get(void *data, u64 *val)
|
||||
{
|
||||
*val = psm_6lowpan;
|
||||
*val = enable_6lowpan;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(lowpan_psm_fops, lowpan_psm_get,
|
||||
lowpan_psm_set, "%llu\n");
|
||||
DEFINE_SIMPLE_ATTRIBUTE(lowpan_enable_fops, lowpan_enable_get,
|
||||
lowpan_enable_set, "%llu\n");
|
||||
|
||||
static ssize_t lowpan_control_write(struct file *fp,
|
||||
const char __user *user_buffer,
|
||||
@@ -1439,9 +1435,9 @@ static struct notifier_block bt_6lowpan_dev_notifier = {
|
||||
|
||||
static int __init bt_6lowpan_init(void)
|
||||
{
|
||||
lowpan_psm_debugfs = debugfs_create_file("6lowpan_psm", 0644,
|
||||
bt_debugfs, NULL,
|
||||
&lowpan_psm_fops);
|
||||
lowpan_enable_debugfs = debugfs_create_file("6lowpan_enable", 0644,
|
||||
bt_debugfs, NULL,
|
||||
&lowpan_enable_fops);
|
||||
lowpan_control_debugfs = debugfs_create_file("6lowpan_control", 0644,
|
||||
bt_debugfs, NULL,
|
||||
&lowpan_control_fops);
|
||||
@@ -1451,7 +1447,7 @@ static int __init bt_6lowpan_init(void)
|
||||
|
||||
static void __exit bt_6lowpan_exit(void)
|
||||
{
|
||||
debugfs_remove(lowpan_psm_debugfs);
|
||||
debugfs_remove(lowpan_enable_debugfs);
|
||||
debugfs_remove(lowpan_control_debugfs);
|
||||
|
||||
if (listen_chan) {
|
||||
|
||||
@@ -253,8 +253,6 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
|
||||
if (skb->len < CAPI_MSG_BASELEN + 15)
|
||||
break;
|
||||
|
||||
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
|
||||
|
||||
if (!info && ctrl) {
|
||||
int len = min_t(uint, CAPI_MANUFACTURER_LEN,
|
||||
skb->data[CAPI_MSG_BASELEN + 14]);
|
||||
@@ -270,8 +268,6 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
|
||||
if (skb->len < CAPI_MSG_BASELEN + 32)
|
||||
break;
|
||||
|
||||
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
|
||||
|
||||
if (!info && ctrl) {
|
||||
ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
|
||||
ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
|
||||
@@ -285,8 +281,6 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
|
||||
if (skb->len < CAPI_MSG_BASELEN + 17)
|
||||
break;
|
||||
|
||||
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
|
||||
|
||||
if (!info && ctrl) {
|
||||
int len = min_t(uint, CAPI_SERIAL_LEN,
|
||||
skb->data[CAPI_MSG_BASELEN + 16]);
|
||||
|
||||
@@ -633,7 +633,7 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
|
||||
mgmt_reenable_advertising(hdev);
|
||||
}
|
||||
|
||||
static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
|
||||
static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct hci_conn *conn;
|
||||
|
||||
@@ -1084,21 +1084,6 @@ int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
|
||||
}
|
||||
EXPORT_SYMBOL(hci_conn_check_secure);
|
||||
|
||||
/* Change link key */
|
||||
int hci_conn_change_link_key(struct hci_conn *conn)
|
||||
{
|
||||
BT_DBG("hcon %p", conn);
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
|
||||
struct hci_cp_change_conn_link_key cp;
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Switch role */
|
||||
int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
|
||||
{
|
||||
|
||||
+60
-68
@@ -141,7 +141,7 @@ static const struct file_operations dut_mode_fops = {
|
||||
|
||||
/* ---- HCI requests ---- */
|
||||
|
||||
static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
|
||||
static void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode)
|
||||
{
|
||||
BT_DBG("%s result 0x%2.2x", hdev->name, result);
|
||||
|
||||
@@ -497,43 +497,6 @@ static void le_setup(struct hci_request *req)
|
||||
set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
|
||||
}
|
||||
|
||||
static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
|
||||
{
|
||||
if (lmp_ext_inq_capable(hdev))
|
||||
return 0x02;
|
||||
|
||||
if (lmp_inq_rssi_capable(hdev))
|
||||
return 0x01;
|
||||
|
||||
if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
|
||||
hdev->lmp_subver == 0x0757)
|
||||
return 0x01;
|
||||
|
||||
if (hdev->manufacturer == 15) {
|
||||
if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
|
||||
return 0x01;
|
||||
if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
|
||||
return 0x01;
|
||||
if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
|
||||
return 0x01;
|
||||
}
|
||||
|
||||
if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
|
||||
hdev->lmp_subver == 0x1805)
|
||||
return 0x01;
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static void hci_setup_inquiry_mode(struct hci_request *req)
|
||||
{
|
||||
u8 mode;
|
||||
|
||||
mode = hci_get_inquiry_mode(req->hdev);
|
||||
|
||||
hci_req_add(req, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
|
||||
}
|
||||
|
||||
static void hci_setup_event_mask(struct hci_request *req)
|
||||
{
|
||||
struct hci_dev *hdev = req->hdev;
|
||||
@@ -658,8 +621,18 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
|
||||
}
|
||||
}
|
||||
|
||||
if (lmp_inq_rssi_capable(hdev))
|
||||
hci_setup_inquiry_mode(req);
|
||||
if (lmp_inq_rssi_capable(hdev) ||
|
||||
test_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks)) {
|
||||
u8 mode;
|
||||
|
||||
/* If Extended Inquiry Result events are supported, then
|
||||
* they are clearly preferred over Inquiry Result with RSSI
|
||||
* events.
|
||||
*/
|
||||
mode = lmp_ext_inq_capable(hdev) ? 0x02 : 0x01;
|
||||
|
||||
hci_req_add(req, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
|
||||
}
|
||||
|
||||
if (lmp_inq_tx_pwr_capable(hdev))
|
||||
hci_req_add(req, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
|
||||
@@ -758,27 +731,12 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
||||
|
||||
hci_setup_event_mask(req);
|
||||
|
||||
/* Some Broadcom based Bluetooth controllers do not support the
|
||||
* Delete Stored Link Key command. They are clearly indicating its
|
||||
* absence in the bit mask of supported commands.
|
||||
*
|
||||
* Check the supported commands and only if the the command is marked
|
||||
* as supported send it. If not supported assume that the controller
|
||||
* does not have actual support for stored link keys which makes this
|
||||
* command redundant anyway.
|
||||
*
|
||||
* Some controllers indicate that they support handling deleting
|
||||
* stored link keys, but they don't. The quirk lets a driver
|
||||
* just disable this command.
|
||||
*/
|
||||
if (hdev->commands[6] & 0x80 &&
|
||||
!test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) {
|
||||
struct hci_cp_delete_stored_link_key cp;
|
||||
if (hdev->commands[6] & 0x20) {
|
||||
struct hci_cp_read_stored_link_key cp;
|
||||
|
||||
bacpy(&cp.bdaddr, BDADDR_ANY);
|
||||
cp.delete_all = 0x01;
|
||||
hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY,
|
||||
sizeof(cp), &cp);
|
||||
cp.read_all = 0x01;
|
||||
hci_req_add(req, HCI_OP_READ_STORED_LINK_KEY, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
if (hdev->commands[5] & 0x10)
|
||||
@@ -872,6 +830,29 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt)
|
||||
{
|
||||
struct hci_dev *hdev = req->hdev;
|
||||
|
||||
/* Some Broadcom based Bluetooth controllers do not support the
|
||||
* Delete Stored Link Key command. They are clearly indicating its
|
||||
* absence in the bit mask of supported commands.
|
||||
*
|
||||
* Check the supported commands and only if the the command is marked
|
||||
* as supported send it. If not supported assume that the controller
|
||||
* does not have actual support for stored link keys which makes this
|
||||
* command redundant anyway.
|
||||
*
|
||||
* Some controllers indicate that they support handling deleting
|
||||
* stored link keys, but they don't. The quirk lets a driver
|
||||
* just disable this command.
|
||||
*/
|
||||
if (hdev->commands[6] & 0x80 &&
|
||||
!test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) {
|
||||
struct hci_cp_delete_stored_link_key cp;
|
||||
|
||||
bacpy(&cp.bdaddr, BDADDR_ANY);
|
||||
cp.delete_all = 0x01;
|
||||
hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
/* Set event mask page 2 if the HCI command for it is supported */
|
||||
if (hdev->commands[22] & 0x04)
|
||||
hci_set_event_mask_page_2(req);
|
||||
@@ -931,10 +912,20 @@ static int __hci_init(struct hci_dev *hdev)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Only create debugfs entries during the initial setup
|
||||
* phase and not every time the controller gets powered on.
|
||||
/* This function is only called when the controller is actually in
|
||||
* configured state. When the controller is marked as unconfigured,
|
||||
* this initialization procedure is not run.
|
||||
*
|
||||
* It means that it is possible that a controller runs through its
|
||||
* setup phase and then discovers missing settings. If that is the
|
||||
* case, then this function will not be called. It then will only
|
||||
* be called during the config phase.
|
||||
*
|
||||
* So only when in setup phase or config phase, create the debugfs
|
||||
* entries and register the SMP channels.
|
||||
*/
|
||||
if (!test_bit(HCI_SETUP, &hdev->dev_flags))
|
||||
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
|
||||
!test_bit(HCI_CONFIG, &hdev->dev_flags))
|
||||
return 0;
|
||||
|
||||
hci_debugfs_create_common(hdev);
|
||||
@@ -942,10 +933,8 @@ static int __hci_init(struct hci_dev *hdev)
|
||||
if (lmp_bredr_capable(hdev))
|
||||
hci_debugfs_create_bredr(hdev);
|
||||
|
||||
if (lmp_le_capable(hdev)) {
|
||||
if (lmp_le_capable(hdev))
|
||||
hci_debugfs_create_le(hdev);
|
||||
smp_register(hdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2142,6 +2131,8 @@ static void hci_power_off(struct work_struct *work)
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
hci_dev_do_close(hdev);
|
||||
|
||||
smp_unregister(hdev);
|
||||
}
|
||||
|
||||
static void hci_discov_off(struct work_struct *work)
|
||||
@@ -2771,7 +2762,7 @@ void hci_conn_params_clear_all(struct hci_dev *hdev)
|
||||
BT_DBG("All LE connection parameters were removed");
|
||||
}
|
||||
|
||||
static void inquiry_complete(struct hci_dev *hdev, u8 status)
|
||||
static void inquiry_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
if (status) {
|
||||
BT_ERR("Failed to start inquiry: status %d", status);
|
||||
@@ -2783,7 +2774,8 @@ static void inquiry_complete(struct hci_dev *hdev, u8 status)
|
||||
}
|
||||
}
|
||||
|
||||
static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status)
|
||||
static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode)
|
||||
{
|
||||
/* General inquiry access code (GIAC) */
|
||||
u8 lap[3] = { 0x33, 0x8b, 0x9e };
|
||||
@@ -4176,7 +4168,7 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status)
|
||||
|
||||
call_complete:
|
||||
if (req_complete)
|
||||
req_complete(hdev, status);
|
||||
req_complete(hdev, status, status ? opcode : HCI_OP_NOP);
|
||||
}
|
||||
|
||||
static void hci_rx_work(struct work_struct *work)
|
||||
|
||||
+23
-120
@@ -212,6 +212,24 @@ static int conn_info_max_age_get(void *data, u64 *val)
|
||||
DEFINE_SIMPLE_ATTRIBUTE(conn_info_max_age_fops, conn_info_max_age_get,
|
||||
conn_info_max_age_set, "%llu\n");
|
||||
|
||||
static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hci_dev *hdev = file->private_data;
|
||||
char buf[3];
|
||||
|
||||
buf[0] = test_bit(HCI_SC_ONLY, &hdev->dev_flags) ? 'Y': 'N';
|
||||
buf[1] = '\n';
|
||||
buf[2] = '\0';
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static const struct file_operations sc_only_mode_fops = {
|
||||
.open = simple_open,
|
||||
.read = sc_only_mode_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void hci_debugfs_create_common(struct hci_dev *hdev)
|
||||
{
|
||||
debugfs_create_file("features", 0444, hdev->debugfs, hdev,
|
||||
@@ -230,6 +248,10 @@ void hci_debugfs_create_common(struct hci_dev *hdev)
|
||||
&conn_info_min_age_fops);
|
||||
debugfs_create_file("conn_info_max_age", 0644, hdev->debugfs, hdev,
|
||||
&conn_info_max_age_fops);
|
||||
|
||||
if (lmp_sc_capable(hdev) || lmp_le_capable(hdev))
|
||||
debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
|
||||
hdev, &sc_only_mode_fops);
|
||||
}
|
||||
|
||||
static int inquiry_cache_show(struct seq_file *f, void *p)
|
||||
@@ -357,114 +379,6 @@ static int auto_accept_delay_get(void *data, u64 *val)
|
||||
DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
|
||||
auto_accept_delay_set, "%llu\n");
|
||||
|
||||
static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hci_dev *hdev = file->private_data;
|
||||
char buf[3];
|
||||
|
||||
buf[0] = test_bit(HCI_SC_ONLY, &hdev->dev_flags) ? 'Y': 'N';
|
||||
buf[1] = '\n';
|
||||
buf[2] = '\0';
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static const struct file_operations sc_only_mode_fops = {
|
||||
.open = simple_open,
|
||||
.read = sc_only_mode_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t force_sc_support_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hci_dev *hdev = file->private_data;
|
||||
char buf[3];
|
||||
|
||||
buf[0] = test_bit(HCI_FORCE_SC, &hdev->dbg_flags) ? 'Y': 'N';
|
||||
buf[1] = '\n';
|
||||
buf[2] = '\0';
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static ssize_t force_sc_support_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hci_dev *hdev = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size = min(count, (sizeof(buf)-1));
|
||||
bool enable;
|
||||
|
||||
if (test_bit(HCI_UP, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
|
||||
buf[buf_size] = '\0';
|
||||
if (strtobool(buf, &enable))
|
||||
return -EINVAL;
|
||||
|
||||
if (enable == test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
|
||||
return -EALREADY;
|
||||
|
||||
change_bit(HCI_FORCE_SC, &hdev->dbg_flags);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations force_sc_support_fops = {
|
||||
.open = simple_open,
|
||||
.read = force_sc_support_read,
|
||||
.write = force_sc_support_write,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t force_lesc_support_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hci_dev *hdev = file->private_data;
|
||||
char buf[3];
|
||||
|
||||
buf[0] = test_bit(HCI_FORCE_LESC, &hdev->dbg_flags) ? 'Y': 'N';
|
||||
buf[1] = '\n';
|
||||
buf[2] = '\0';
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static ssize_t force_lesc_support_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hci_dev *hdev = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size = min(count, (sizeof(buf)-1));
|
||||
bool enable;
|
||||
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
|
||||
buf[buf_size] = '\0';
|
||||
if (strtobool(buf, &enable))
|
||||
return -EINVAL;
|
||||
|
||||
if (enable == test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
|
||||
return -EALREADY;
|
||||
|
||||
change_bit(HCI_FORCE_LESC, &hdev->dbg_flags);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations force_lesc_support_fops = {
|
||||
.open = simple_open,
|
||||
.read = force_lesc_support_read,
|
||||
.write = force_lesc_support_write,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int idle_timeout_set(void *data, u64 val)
|
||||
{
|
||||
struct hci_dev *hdev = data;
|
||||
@@ -560,20 +474,9 @@ void hci_debugfs_create_bredr(struct hci_dev *hdev)
|
||||
debugfs_create_file("voice_setting", 0444, hdev->debugfs, hdev,
|
||||
&voice_setting_fops);
|
||||
|
||||
if (lmp_ssp_capable(hdev)) {
|
||||
if (lmp_ssp_capable(hdev))
|
||||
debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
|
||||
hdev, &auto_accept_delay_fops);
|
||||
debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
|
||||
hdev, &sc_only_mode_fops);
|
||||
|
||||
debugfs_create_file("force_sc_support", 0644, hdev->debugfs,
|
||||
hdev, &force_sc_support_fops);
|
||||
|
||||
if (lmp_le_capable(hdev))
|
||||
debugfs_create_file("force_lesc_support", 0644,
|
||||
hdev->debugfs, hdev,
|
||||
&force_lesc_support_fops);
|
||||
}
|
||||
|
||||
if (lmp_sniff_capable(hdev)) {
|
||||
debugfs_create_file("idle_timeout", 0644, hdev->debugfs,
|
||||
|
||||
@@ -214,6 +214,40 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_bdaddr_list_clear(&hdev->le_white_list);
|
||||
}
|
||||
|
||||
static void hci_cc_read_stored_link_key(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_read_stored_link_key *rp = (void *)skb->data;
|
||||
struct hci_cp_read_stored_link_key *sent;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY);
|
||||
if (!sent)
|
||||
return;
|
||||
|
||||
if (!rp->status && sent->read_all == 0x01) {
|
||||
hdev->stored_max_keys = rp->max_keys;
|
||||
hdev->stored_num_keys = rp->num_keys;
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_delete_stored_link_key *rp = (void *)skb->data;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
return;
|
||||
|
||||
if (rp->num_keys <= hdev->stored_num_keys)
|
||||
hdev->stored_num_keys -= rp->num_keys;
|
||||
else
|
||||
hdev->stored_num_keys = 0;
|
||||
}
|
||||
|
||||
static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
@@ -2714,6 +2748,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cc_reset(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_READ_STORED_LINK_KEY:
|
||||
hci_cc_read_stored_link_key(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_DELETE_STORED_LINK_KEY:
|
||||
hci_cc_delete_stored_link_key(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_WRITE_LOCAL_NAME:
|
||||
hci_cc_write_local_name(hdev, skb);
|
||||
break;
|
||||
|
||||
@@ -533,7 +533,8 @@ void __hci_update_background_scan(struct hci_request *req)
|
||||
}
|
||||
}
|
||||
|
||||
static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
|
||||
static void update_background_scan_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode)
|
||||
{
|
||||
if (status)
|
||||
BT_DBG("HCI request failed to update background scanning: "
|
||||
|
||||
+42
-65
@@ -216,11 +216,39 @@ void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk)
|
||||
read_unlock(&hci_sk_list.lock);
|
||||
}
|
||||
|
||||
static void queue_monitor_skb(struct sk_buff *skb)
|
||||
{
|
||||
struct sock *sk;
|
||||
|
||||
BT_DBG("len %d", skb->len);
|
||||
|
||||
read_lock(&hci_sk_list.lock);
|
||||
|
||||
sk_for_each(sk, &hci_sk_list.head) {
|
||||
struct sk_buff *nskb;
|
||||
|
||||
if (sk->sk_state != BT_BOUND)
|
||||
continue;
|
||||
|
||||
if (hci_pi(sk)->channel != HCI_CHANNEL_MONITOR)
|
||||
continue;
|
||||
|
||||
nskb = skb_clone(skb, GFP_ATOMIC);
|
||||
if (!nskb)
|
||||
continue;
|
||||
|
||||
if (sock_queue_rcv_skb(sk, nskb))
|
||||
kfree_skb(nskb);
|
||||
}
|
||||
|
||||
read_unlock(&hci_sk_list.lock);
|
||||
}
|
||||
|
||||
/* Send frame to monitor socket */
|
||||
void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct sock *sk;
|
||||
struct sk_buff *skb_copy = NULL;
|
||||
struct hci_mon_hdr *hdr;
|
||||
__le16 opcode;
|
||||
|
||||
if (!atomic_read(&monitor_promisc))
|
||||
@@ -251,74 +279,21 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
return;
|
||||
}
|
||||
|
||||
read_lock(&hci_sk_list.lock);
|
||||
/* Create a private copy with headroom */
|
||||
skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC, true);
|
||||
if (!skb_copy)
|
||||
return;
|
||||
|
||||
sk_for_each(sk, &hci_sk_list.head) {
|
||||
struct sk_buff *nskb;
|
||||
|
||||
if (sk->sk_state != BT_BOUND)
|
||||
continue;
|
||||
|
||||
if (hci_pi(sk)->channel != HCI_CHANNEL_MONITOR)
|
||||
continue;
|
||||
|
||||
if (!skb_copy) {
|
||||
struct hci_mon_hdr *hdr;
|
||||
|
||||
/* Create a private copy with headroom */
|
||||
skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE,
|
||||
GFP_ATOMIC, true);
|
||||
if (!skb_copy)
|
||||
continue;
|
||||
|
||||
/* Put header before the data */
|
||||
hdr = (void *) skb_push(skb_copy, HCI_MON_HDR_SIZE);
|
||||
hdr->opcode = opcode;
|
||||
hdr->index = cpu_to_le16(hdev->id);
|
||||
hdr->len = cpu_to_le16(skb->len);
|
||||
}
|
||||
|
||||
nskb = skb_clone(skb_copy, GFP_ATOMIC);
|
||||
if (!nskb)
|
||||
continue;
|
||||
|
||||
if (sock_queue_rcv_skb(sk, nskb))
|
||||
kfree_skb(nskb);
|
||||
}
|
||||
|
||||
read_unlock(&hci_sk_list.lock);
|
||||
/* Put header before the data */
|
||||
hdr = (void *) skb_push(skb_copy, HCI_MON_HDR_SIZE);
|
||||
hdr->opcode = opcode;
|
||||
hdr->index = cpu_to_le16(hdev->id);
|
||||
hdr->len = cpu_to_le16(skb->len);
|
||||
|
||||
queue_monitor_skb(skb_copy);
|
||||
kfree_skb(skb_copy);
|
||||
}
|
||||
|
||||
static void send_monitor_event(struct sk_buff *skb)
|
||||
{
|
||||
struct sock *sk;
|
||||
|
||||
BT_DBG("len %d", skb->len);
|
||||
|
||||
read_lock(&hci_sk_list.lock);
|
||||
|
||||
sk_for_each(sk, &hci_sk_list.head) {
|
||||
struct sk_buff *nskb;
|
||||
|
||||
if (sk->sk_state != BT_BOUND)
|
||||
continue;
|
||||
|
||||
if (hci_pi(sk)->channel != HCI_CHANNEL_MONITOR)
|
||||
continue;
|
||||
|
||||
nskb = skb_clone(skb, GFP_ATOMIC);
|
||||
if (!nskb)
|
||||
continue;
|
||||
|
||||
if (sock_queue_rcv_skb(sk, nskb))
|
||||
kfree_skb(nskb);
|
||||
}
|
||||
|
||||
read_unlock(&hci_sk_list.lock);
|
||||
}
|
||||
|
||||
static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
|
||||
{
|
||||
struct hci_mon_hdr *hdr;
|
||||
@@ -422,7 +397,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event)
|
||||
|
||||
skb = create_monitor_event(hdev, event);
|
||||
if (skb) {
|
||||
send_monitor_event(skb);
|
||||
queue_monitor_skb(skb);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
@@ -1230,6 +1205,8 @@ int __init hci_sock_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct sockaddr_hci) > sizeof(struct sockaddr));
|
||||
|
||||
err = proto_register(&hci_sk_proto, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
+32
-23
@@ -63,10 +63,10 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
|
||||
static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
|
||||
struct sk_buff_head *skbs, u8 event);
|
||||
|
||||
static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type)
|
||||
static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type)
|
||||
{
|
||||
if (hcon->type == LE_LINK) {
|
||||
if (type == ADDR_LE_DEV_PUBLIC)
|
||||
if (link_type == LE_LINK) {
|
||||
if (bdaddr_type == ADDR_LE_DEV_PUBLIC)
|
||||
return BDADDR_LE_PUBLIC;
|
||||
else
|
||||
return BDADDR_LE_RANDOM;
|
||||
@@ -75,6 +75,16 @@ static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type)
|
||||
return BDADDR_BREDR;
|
||||
}
|
||||
|
||||
static inline u8 bdaddr_src_type(struct hci_conn *hcon)
|
||||
{
|
||||
return bdaddr_type(hcon->type, hcon->src_type);
|
||||
}
|
||||
|
||||
static inline u8 bdaddr_dst_type(struct hci_conn *hcon)
|
||||
{
|
||||
return bdaddr_type(hcon->type, hcon->dst_type);
|
||||
}
|
||||
|
||||
/* ---- L2CAP channels ---- */
|
||||
|
||||
static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
|
||||
@@ -646,7 +656,7 @@ static void l2cap_conn_update_id_addr(struct work_struct *work)
|
||||
list_for_each_entry(chan, &conn->chan_l, list) {
|
||||
l2cap_chan_lock(chan);
|
||||
bacpy(&chan->dst, &hcon->dst);
|
||||
chan->dst_type = bdaddr_type(hcon, hcon->dst_type);
|
||||
chan->dst_type = bdaddr_dst_type(hcon);
|
||||
l2cap_chan_unlock(chan);
|
||||
}
|
||||
|
||||
@@ -3790,8 +3800,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
|
||||
|
||||
bacpy(&chan->src, &conn->hcon->src);
|
||||
bacpy(&chan->dst, &conn->hcon->dst);
|
||||
chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
|
||||
chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
|
||||
chan->src_type = bdaddr_src_type(conn->hcon);
|
||||
chan->dst_type = bdaddr_dst_type(conn->hcon);
|
||||
chan->psm = psm;
|
||||
chan->dcid = scid;
|
||||
chan->local_amp_id = amp_id;
|
||||
@@ -5441,8 +5451,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
|
||||
|
||||
bacpy(&chan->src, &conn->hcon->src);
|
||||
bacpy(&chan->dst, &conn->hcon->dst);
|
||||
chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
|
||||
chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
|
||||
chan->src_type = bdaddr_src_type(conn->hcon);
|
||||
chan->dst_type = bdaddr_dst_type(conn->hcon);
|
||||
chan->psm = psm;
|
||||
chan->dcid = scid;
|
||||
chan->omtu = mtu;
|
||||
@@ -6881,7 +6891,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
*/
|
||||
if (hcon->type == LE_LINK &&
|
||||
hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst,
|
||||
bdaddr_type(hcon, hcon->dst_type))) {
|
||||
bdaddr_dst_type(hcon))) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
@@ -6968,7 +6978,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
|
||||
|
||||
if (test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags) &&
|
||||
(bredr_sc_enabled(hcon->hdev) ||
|
||||
test_bit(HCI_FORCE_LESC, &hcon->hdev->dbg_flags)))
|
||||
test_bit(HCI_FORCE_BREDR_SMP, &hcon->hdev->dbg_flags)))
|
||||
conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
|
||||
|
||||
mutex_init(&conn->ident_lock);
|
||||
@@ -7123,7 +7133,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||
|
||||
/* Update source addr of the socket */
|
||||
bacpy(&chan->src, &hcon->src);
|
||||
chan->src_type = bdaddr_type(hcon, hcon->src_type);
|
||||
chan->src_type = bdaddr_src_type(hcon);
|
||||
|
||||
__l2cap_chan_add(conn, chan);
|
||||
|
||||
@@ -7197,8 +7207,10 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||
* global list (by passing NULL as first parameter).
|
||||
*/
|
||||
static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
|
||||
bdaddr_t *src, u8 link_type)
|
||||
struct hci_conn *hcon)
|
||||
{
|
||||
u8 src_type = bdaddr_src_type(hcon);
|
||||
|
||||
read_lock(&chan_list_lock);
|
||||
|
||||
if (c)
|
||||
@@ -7211,11 +7223,9 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
|
||||
continue;
|
||||
if (c->state != BT_LISTEN)
|
||||
continue;
|
||||
if (bacmp(&c->src, src) && bacmp(&c->src, BDADDR_ANY))
|
||||
if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY))
|
||||
continue;
|
||||
if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
|
||||
continue;
|
||||
if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
|
||||
if (src_type != c->src_type)
|
||||
continue;
|
||||
|
||||
l2cap_chan_hold(c);
|
||||
@@ -7246,7 +7256,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
||||
if (!conn)
|
||||
return;
|
||||
|
||||
dst_type = bdaddr_type(hcon, hcon->dst_type);
|
||||
dst_type = bdaddr_dst_type(hcon);
|
||||
|
||||
/* If device is blocked, do not create channels for it */
|
||||
if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type))
|
||||
@@ -7257,7 +7267,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
||||
* we left off, because the list lock would prevent calling the
|
||||
* potentially sleeping l2cap_chan_lock() function.
|
||||
*/
|
||||
pchan = l2cap_global_fixed_chan(NULL, &hdev->bdaddr, hcon->type);
|
||||
pchan = l2cap_global_fixed_chan(NULL, hcon);
|
||||
while (pchan) {
|
||||
struct l2cap_chan *chan, *next;
|
||||
|
||||
@@ -7270,7 +7280,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
||||
if (chan) {
|
||||
bacpy(&chan->src, &hcon->src);
|
||||
bacpy(&chan->dst, &hcon->dst);
|
||||
chan->src_type = bdaddr_type(hcon, hcon->src_type);
|
||||
chan->src_type = bdaddr_src_type(hcon);
|
||||
chan->dst_type = dst_type;
|
||||
|
||||
__l2cap_chan_add(conn, chan);
|
||||
@@ -7278,8 +7288,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
||||
|
||||
l2cap_chan_unlock(pchan);
|
||||
next:
|
||||
next = l2cap_global_fixed_chan(pchan, &hdev->bdaddr,
|
||||
hcon->type);
|
||||
next = l2cap_global_fixed_chan(pchan, hcon);
|
||||
l2cap_chan_put(pchan);
|
||||
pchan = next;
|
||||
}
|
||||
@@ -7527,8 +7536,8 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
|
||||
read_lock(&chan_list_lock);
|
||||
|
||||
list_for_each_entry(c, &chan_list, global_l) {
|
||||
seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
|
||||
&c->src, &c->dst,
|
||||
seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
|
||||
&c->src, c->src_type, &c->dst, c->dst_type,
|
||||
c->state, __le16_to_cpu(c->psm),
|
||||
c->scid, c->dcid, c->imtu, c->omtu,
|
||||
c->sec_level, c->mode);
|
||||
|
||||
@@ -1614,6 +1614,8 @@ int __init l2cap_init_sockets(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct sockaddr_l2) > sizeof(struct sockaddr));
|
||||
|
||||
err = proto_register(&l2cap_proto, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
+53
-26
@@ -570,8 +570,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
|
||||
settings |= MGMT_SETTING_HS;
|
||||
}
|
||||
|
||||
if (lmp_sc_capable(hdev) ||
|
||||
test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
|
||||
if (lmp_sc_capable(hdev))
|
||||
settings |= MGMT_SETTING_SECURE_CONN;
|
||||
}
|
||||
|
||||
@@ -1252,7 +1251,7 @@ static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
|
||||
sizeof(settings));
|
||||
}
|
||||
|
||||
static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
|
||||
static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
BT_DBG("%s status 0x%02x", hdev->name, status);
|
||||
|
||||
@@ -1519,7 +1518,8 @@ static u8 mgmt_le_support(struct hci_dev *hdev)
|
||||
return MGMT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
|
||||
static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
struct mgmt_mode *cp;
|
||||
@@ -1778,7 +1778,8 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
|
||||
hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
|
||||
}
|
||||
|
||||
static void set_connectable_complete(struct hci_dev *hdev, u8 status)
|
||||
static void set_connectable_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
struct mgmt_mode *cp;
|
||||
@@ -2196,7 +2197,7 @@ unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void le_enable_complete(struct hci_dev *hdev, u8 status)
|
||||
static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct cmd_lookup match = { NULL, hdev };
|
||||
|
||||
@@ -2386,7 +2387,7 @@ unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static void add_uuid_complete(struct hci_dev *hdev, u8 status)
|
||||
static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
BT_DBG("status 0x%02x", status);
|
||||
|
||||
@@ -2465,7 +2466,7 @@ static bool enable_service_cache(struct hci_dev *hdev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
|
||||
static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
BT_DBG("status 0x%02x", status);
|
||||
|
||||
@@ -2550,7 +2551,7 @@ unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void set_class_complete(struct hci_dev *hdev, u8 status)
|
||||
static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
BT_DBG("status 0x%02x", status);
|
||||
|
||||
@@ -3484,7 +3485,7 @@ static void update_name(struct hci_request *req)
|
||||
hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
static void set_name_complete(struct hci_dev *hdev, u8 status)
|
||||
static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct mgmt_cp_set_local_name *cp;
|
||||
struct pending_cmd *cmd;
|
||||
@@ -3835,7 +3836,8 @@ static bool trigger_discovery(struct hci_request *req, u8 *status)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void start_discovery_complete(struct hci_dev *hdev, u8 status)
|
||||
static void start_discovery_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
unsigned long timeout;
|
||||
@@ -4064,7 +4066,7 @@ failed:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
|
||||
static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
|
||||
@@ -4290,7 +4292,8 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void set_advertising_complete(struct hci_dev *hdev, u8 status)
|
||||
static void set_advertising_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode)
|
||||
{
|
||||
struct cmd_lookup match = { NULL, hdev };
|
||||
|
||||
@@ -4497,7 +4500,8 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
|
||||
static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
|
||||
@@ -4595,7 +4599,7 @@ unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void set_bredr_complete(struct hci_dev *hdev, u8 status)
|
||||
static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
|
||||
@@ -4679,6 +4683,21 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
||||
err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
|
||||
MGMT_STATUS_REJECTED);
|
||||
goto unlock;
|
||||
} else {
|
||||
/* When configuring a dual-mode controller to operate
|
||||
* with LE only and using a static address, then switching
|
||||
* BR/EDR back on is not allowed.
|
||||
*
|
||||
* Dual-mode controllers shall operate with the public
|
||||
* address as its identity address for BR/EDR and LE. So
|
||||
* reject the attempt to create an invalid configuration.
|
||||
*/
|
||||
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
|
||||
bacmp(&hdev->static_addr, BDADDR_ANY)) {
|
||||
err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
|
||||
MGMT_STATUS_REJECTED);
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
|
||||
@@ -4727,8 +4746,8 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
|
||||
|
||||
BT_DBG("request for %s", hdev->name);
|
||||
|
||||
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
|
||||
!lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
|
||||
if (!lmp_sc_capable(hdev) &&
|
||||
!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
|
||||
return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
|
||||
MGMT_STATUS_NOT_SUPPORTED);
|
||||
|
||||
@@ -4738,9 +4757,7 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (!hdev_is_powered(hdev) ||
|
||||
(!lmp_sc_capable(hdev) &&
|
||||
!test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
|
||||
if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
|
||||
!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
|
||||
bool changed;
|
||||
|
||||
@@ -5122,7 +5139,8 @@ static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status)
|
||||
static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
|
||||
u16 opcode)
|
||||
{
|
||||
struct hci_cp_read_rssi *cp;
|
||||
struct pending_cmd *cmd;
|
||||
@@ -5329,7 +5347,7 @@ complete:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
|
||||
static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct hci_cp_read_clock *hci_cp;
|
||||
struct pending_cmd *cmd;
|
||||
@@ -5507,7 +5525,7 @@ static void device_added(struct sock *sk, struct hci_dev *hdev,
|
||||
mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
|
||||
}
|
||||
|
||||
static void add_device_complete(struct hci_dev *hdev, u8 status)
|
||||
static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
|
||||
@@ -5630,7 +5648,7 @@ static void device_removed(struct sock *sk, struct hci_dev *hdev,
|
||||
mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
|
||||
}
|
||||
|
||||
static void remove_device_complete(struct hci_dev *hdev, u8 status)
|
||||
static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
|
||||
@@ -6208,12 +6226,21 @@ static void restart_le_actions(struct hci_request *req)
|
||||
__hci_update_background_scan(req);
|
||||
}
|
||||
|
||||
static void powered_complete(struct hci_dev *hdev, u8 status)
|
||||
static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
struct cmd_lookup match = { NULL, hdev };
|
||||
|
||||
BT_DBG("status 0x%02x", status);
|
||||
|
||||
if (!status) {
|
||||
/* Register the available SMP channels (BR/EDR and LE) only
|
||||
* when successfully powering on the controller. This late
|
||||
* registration is required so that LE SMP can clearly
|
||||
* decide if the public address or static address is used.
|
||||
*/
|
||||
smp_register(hdev);
|
||||
}
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
|
||||
@@ -7319,7 +7346,7 @@ void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
|
||||
mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
|
||||
}
|
||||
|
||||
static void adv_enable_complete(struct hci_dev *hdev, u8 status)
|
||||
static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
|
||||
{
|
||||
BT_DBG("%s status %u", hdev->name, status);
|
||||
}
|
||||
|
||||
@@ -1058,6 +1058,8 @@ int __init rfcomm_init_sockets(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct sockaddr_rc) > sizeof(struct sockaddr));
|
||||
|
||||
err = proto_register(&rfcomm_proto, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -1184,6 +1184,8 @@ int __init sco_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct sockaddr_sco) > sizeof(struct sockaddr));
|
||||
|
||||
err = proto_register(&sco_proto, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user