blob: 1c6ffaa8902f5e9fe32a86f2a19cf9073d6f0dae [file] [log] [blame]
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright (C) 2011 ProFUSION Embedded Systems
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
/* Bluetooth HCI core. */
#include <linux/export.h>
#include <linux/idr.h>
#include <linux/rfkill.h>
#include <linux/debugfs.h>
#include <linux/crypto.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "smp.h"
static void hci_rx_work(struct work_struct *work);
static void hci_cmd_work(struct work_struct *work);
static void hci_tx_work(struct work_struct *work);
/* HCI device list */
LIST_HEAD(hci_dev_list);
DEFINE_RWLOCK(hci_dev_list_lock);
/* HCI callback list */
LIST_HEAD(hci_cb_list);
DEFINE_RWLOCK(hci_cb_list_lock);
/* HCI ID Numbering */
static DEFINE_IDA(hci_index_ida);
/* ---- HCI notifications ---- */
static void hci_notify(struct hci_dev *hdev, int event)
{
hci_sock_dev_event(hdev, event);
}
/* ---- HCI debugfs entries ---- */
static ssize_t dut_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_DUT_MODE, &hdev->dev_flags) ? 'Y': 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
static ssize_t dut_mode_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
struct sk_buff *skb;
char buf[32];
size_t buf_size = min(count, (sizeof(buf)-1));
bool enable;
int err;
if (!test_bit(HCI_UP, &hdev->flags))
return -ENETDOWN;
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_DUT_MODE, &hdev->dev_flags))
return -EALREADY;
hci_req_lock(hdev);
if (enable)
skb = __hci_cmd_sync(hdev, HCI_OP_ENABLE_DUT_MODE, 0, NULL,
HCI_CMD_TIMEOUT);
else
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL,
HCI_CMD_TIMEOUT);
hci_req_unlock(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
err = -bt_to_errno(skb->data[0]);
kfree_skb(skb);
if (err < 0)
return err;
change_bit(HCI_DUT_MODE, &hdev->dev_flags);
return count;
}
static const struct file_operations dut_mode_fops = {
.open = simple_open,
.read = dut_mode_read,
.write = dut_mode_write,
.llseek = default_llseek,
};
static int features_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
u8 p;
hci_dev_lock(hdev);
for (p = 0; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
seq_printf(f, "%2u: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
"0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", p,
hdev->features[p][0], hdev->features[p][1],
hdev->features[p][2], hdev->features[p][3],
hdev->features[p][4], hdev->features[p][5],
hdev->features[p][6], hdev->features[p][7]);
}
if (lmp_le_capable(hdev))
seq_printf(f, "LE: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
"0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
hdev->le_features[0], hdev->le_features[1],
hdev->le_features[2], hdev->le_features[3],
hdev->le_features[4], hdev->le_features[5],
hdev->le_features[6], hdev->le_features[7]);
hci_dev_unlock(hdev);
return 0;
}
static int features_open(struct inode *inode, struct file *file)
{
return single_open(file, features_show, inode->i_private);
}
static const struct file_operations features_fops = {
.open = features_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int blacklist_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct bdaddr_list *b;
hci_dev_lock(hdev);
list_for_each_entry(b, &hdev->blacklist, list)
seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
hci_dev_unlock(hdev);
return 0;
}
static int blacklist_open(struct inode *inode, struct file *file)
{
return single_open(file, blacklist_show, inode->i_private);
}
static const struct file_operations blacklist_fops = {
.open = blacklist_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int uuids_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct bt_uuid *uuid;
hci_dev_lock(hdev);
list_for_each_entry(uuid, &hdev->uuids, list) {
u8 i, val[16];
/* The Bluetooth UUID values are stored in big endian,
* but with reversed byte order. So convert them into
* the right order for the %pUb modifier.
*/
for (i = 0; i < 16; i++)
val[i] = uuid->uuid[15 - i];
seq_printf(f, "%pUb\n", val);
}
hci_dev_unlock(hdev);
return 0;
}
static int uuids_open(struct inode *inode, struct file *file)
{
return single_open(file, uuids_show, inode->i_private);
}
static const struct file_operations uuids_fops = {
.open = uuids_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int inquiry_cache_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
hci_dev_lock(hdev);
list_for_each_entry(e, &cache->all, all) {
struct inquiry_data *data = &e->data;
seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
&data->bdaddr,
data->pscan_rep_mode, data->pscan_period_mode,
data->pscan_mode, data->dev_class[2],
data->dev_class[1], data->dev_class[0],
__le16_to_cpu(data->clock_offset),
data->rssi, data->ssp_mode, e->timestamp);
}
hci_dev_unlock(hdev);
return 0;
}
static int inquiry_cache_open(struct inode *inode, struct file *file)
{
return single_open(file, inquiry_cache_show, inode->i_private);
}
static const struct file_operations inquiry_cache_fops = {
.open = inquiry_cache_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int link_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
struct list_head *p, *n;
hci_dev_lock(hdev);
list_for_each_safe(p, n, &hdev->link_keys) {
struct link_key *key = list_entry(p, struct link_key, list);
seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
HCI_LINK_KEY_SIZE, key->val, key->pin_len);
}
hci_dev_unlock(hdev);
return 0;
}
static int link_keys_open(struct inode *inode, struct file *file)
{
return single_open(file, link_keys_show, inode->i_private);
}
static const struct file_operations link_keys_fops = {
.open = link_keys_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int dev_class_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
hci_dev_lock(hdev);
seq_printf(f, "0x%.2x%.2x%.2x\n", hdev->dev_class[2],
hdev->dev_class[1], hdev->dev_class[0]);
hci_dev_unlock(hdev);
return 0;
}
static int dev_class_open(struct inode *inode, struct file *file)
{
return single_open(file, dev_class_show, inode->i_private);
}
static const struct file_operations dev_class_fops = {
.open = dev_class_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int voice_setting_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->voice_setting;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get,
NULL, "0x%4.4llx\n");
static int auto_accept_delay_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
hdev->auto_accept_delay = val;
hci_dev_unlock(hdev);
return 0;
}
static int auto_accept_delay_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->auto_accept_delay;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
auto_accept_delay_set, "%llu\n");
static int ssp_debug_mode_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
struct sk_buff *skb;
__u8 mode;
int err;
if (val != 0 && val != 1)
return -EINVAL;
if (!test_bit(HCI_UP, &hdev->flags))
return -ENETDOWN;
hci_req_lock(hdev);
mode = val;
skb = __hci_cmd_sync(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE, sizeof(mode),
&mode, HCI_CMD_TIMEOUT);
hci_req_unlock(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
err = -bt_to_errno(skb->data[0]);
kfree_skb(skb);
if (err < 0)
return err;
hci_dev_lock(hdev);
hdev->ssp_debug_mode = val;
hci_dev_unlock(hdev);
return 0;
}
static int ssp_debug_mode_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->ssp_debug_mode;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(ssp_debug_mode_fops, ssp_debug_mode_get,
ssp_debug_mode_set, "%llu\n");
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->dev_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->dev_flags))
return -EALREADY;
change_bit(HCI_FORCE_SC, &hdev->dev_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 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 int idle_timeout_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val != 0 && (val < 500 || val > 3600000))
return -EINVAL;
hci_dev_lock(hdev);
hdev->idle_timeout = val;
hci_dev_unlock(hdev);
return 0;
}
static int idle_timeout_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->idle_timeout;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get,
idle_timeout_set, "%llu\n");
static int rpa_timeout_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
/* Require the RPA timeout to be at least 30 seconds and at most
* 24 hours.
*/
if (val < 30 || val > (60 * 60 * 24))
return -EINVAL;
hci_dev_lock(hdev);
hdev->rpa_timeout = val;
hci_dev_unlock(hdev);
return 0;
}
static int rpa_timeout_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->rpa_timeout;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(rpa_timeout_fops, rpa_timeout_get,
rpa_timeout_set, "%llu\n");
static int sniff_min_interval_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val == 0 || val % 2 || val > hdev->sniff_max_interval)
return -EINVAL;
hci_dev_lock(hdev);
hdev->sniff_min_interval = val;
hci_dev_unlock(hdev);
return 0;
}
static int sniff_min_interval_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->sniff_min_interval;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(sniff_min_interval_fops, sniff_min_interval_get,
sniff_min_interval_set, "%llu\n");
static int sniff_max_interval_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val == 0 || val % 2 || val < hdev->sniff_min_interval)
return -EINVAL;
hci_dev_lock(hdev);
hdev->sniff_max_interval = val;
hci_dev_unlock(hdev);
return 0;
}
static int sniff_max_interval_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->sniff_max_interval;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get,
sniff_max_interval_set, "%llu\n");
static int identity_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
bdaddr_t addr;
u8 addr_type;
hci_dev_lock(hdev);
hci_copy_identity_address(hdev, &addr, &addr_type);
seq_printf(f, "%pMR (type %u) %*phN %pMR\n", &addr, addr_type,
16, hdev->irk, &hdev->rpa);
hci_dev_unlock(hdev);
return 0;
}
static int identity_open(struct inode *inode, struct file *file)
{
return single_open(file, identity_show, inode->i_private);
}
static const struct file_operations identity_fops = {
.open = identity_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int random_address_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
hci_dev_lock(hdev);
seq_printf(f, "%pMR\n", &hdev->random_addr);
hci_dev_unlock(hdev);
return 0;
}
static int random_address_open(struct inode *inode, struct file *file)
{
return single_open(file, random_address_show, inode->i_private);
}
static const struct file_operations random_address_fops = {
.open = random_address_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int static_address_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
hci_dev_lock(hdev);
seq_printf(f, "%pMR\n", &hdev->static_addr);
hci_dev_unlock(hdev);
return 0;
}
static int static_address_open(struct inode *inode, struct file *file)
{
return single_open(file, static_address_show, inode->i_private);
}
static const struct file_operations static_address_fops = {
.open = static_address_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static ssize_t force_static_address_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_STATIC_ADDR, &hdev->dev_flags) ? 'Y': 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
static ssize_t force_static_address_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_STATIC_ADDR, &hdev->dev_flags))
return -EALREADY;
change_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags);
return count;
}
static const struct file_operations force_static_address_fops = {
.open = simple_open,
.read = force_static_address_read,
.write = force_static_address_write,
.llseek = default_llseek,
};
static int white_list_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
struct bdaddr_list *b;
hci_dev_lock(hdev);
list_for_each_entry(b, &hdev->le_white_list, list)
seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
hci_dev_unlock(hdev);
return 0;
}
static int white_list_open(struct inode *inode, struct file *file)
{
return single_open(file, white_list_show, inode->i_private);
}
static const struct file_operations white_list_fops = {
.open = white_list_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int identity_resolving_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
struct list_head *p, *n;
hci_dev_lock(hdev);
list_for_each_safe(p, n, &hdev->identity_resolving_keys) {
struct smp_irk *irk = list_entry(p, struct smp_irk, list);
seq_printf(f, "%pMR (type %u) %*phN %pMR\n",
&irk->bdaddr, irk->addr_type,
16, irk->val, &irk->rpa);
}
hci_dev_unlock(hdev);
return 0;
}
static int identity_resolving_keys_open(struct inode *inode, struct file *file)
{
return single_open(file, identity_resolving_keys_show,
inode->i_private);
}
static const struct file_operations identity_resolving_keys_fops = {
.open = identity_resolving_keys_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int long_term_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
struct list_head *p, *n;
hci_dev_lock(hdev);
list_for_each_safe(p, n, &hdev->long_term_keys) {
struct smp_ltk *ltk = list_entry(p, struct smp_ltk, list);
seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n",
&ltk->bdaddr, ltk->bdaddr_type, ltk->authenticated,
ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv),
__le64_to_cpu(ltk->rand), 16, ltk->val);
}
hci_dev_unlock(hdev);
return 0;
}
static int long_term_keys_open(struct inode *inode, struct file *file)
{
return single_open(file, long_term_keys_show, inode->i_private);
}
static const struct file_operations long_term_keys_fops = {
.open = long_term_keys_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int conn_min_interval_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val < 0x0006 || val > 0x0c80 || val > hdev->le_conn_max_interval)
return -EINVAL;
hci_dev_lock(hdev);
hdev->le_conn_min_interval = val;
hci_dev_unlock(hdev);
return 0;
}
static int conn_min_interval_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->le_conn_min_interval;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(conn_min_interval_fops, conn_min_interval_get,
conn_min_interval_set, "%llu\n");
static int conn_max_interval_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val < 0x0006 || val > 0x0c80 || val < hdev->le_conn_min_interval)
return -EINVAL;
hci_dev_lock(hdev);
hdev->le_conn_max_interval = val;
hci_dev_unlock(hdev);
return 0;
}
static int conn_max_interval_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->le_conn_max_interval;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get,
conn_max_interval_set, "%llu\n");
static int adv_channel_map_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val < 0x01 || val > 0x07)
return -EINVAL;
hci_dev_lock(hdev);
hdev->le_adv_channel_map = val;
hci_dev_unlock(hdev);
return 0;
}
static int adv_channel_map_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->le_adv_channel_map;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get,
adv_channel_map_set, "%llu\n");
static ssize_t lowpan_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_6LOWPAN_ENABLED, &hdev->dev_flags) ? 'Y' : 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
static ssize_t lowpan_write(struct file *fp, const char __user *user_buffer,
size_t count, loff_t *position)
{
struct hci_dev *hdev = fp->private_data;
bool enable;
char buf[32];
size_t buf_size = min(count, (sizeof(buf)-1));
if (copy_from_user(buf, user_buffer, buf_size))
return -EFAULT;
buf[buf_size] = '\0';
if (strtobool(buf, &enable) < 0)
return -EINVAL;
if (enable == test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
return -EALREADY;
change_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags);
return count;
}
static const struct file_operations lowpan_debugfs_fops = {
.open = simple_open,
.read = lowpan_read,
.write = lowpan_write,
.llseek = default_llseek,
};
static int le_auto_conn_show(struct seq_file *sf, void *ptr)
{
struct hci_dev *hdev = sf->private;
struct hci_conn_params *p;
hci_dev_lock(hdev);
list_for_each_entry(p, &hdev->le_conn_params, list) {
seq_printf(sf, "%pMR %u %u\n", &p->addr, p->addr_type,
p->auto_connect);
}
hci_dev_unlock(hdev);
return 0;
}
static int le_auto_conn_open(struct inode *inode, struct file *file)
{
return single_open(file, le_auto_conn_show, inode->i_private);
}
static ssize_t le_auto_conn_write(struct file *file, const char __user *data,
size_t count, loff_t *offset)
{
struct seq_file *sf = file->private_data;
struct hci_dev *hdev = sf->private;
u8 auto_connect = 0;
bdaddr_t addr;
u8 addr_type;
char *buf;
int err = 0;
int n;
/* Don't allow partial write */
if (*offset != 0)
return -EINVAL;
if (count < 3)
return -EINVAL;
buf = kzalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (copy_from_user(buf, data, count)) {
err = -EFAULT;
goto done;
}
if (memcmp(buf, "add", 3) == 0) {
n = sscanf(&buf[4], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu %hhu",
&addr.b[5], &addr.b[4], &addr.b[3], &addr.b[2],
&addr.b[1], &addr.b[0], &addr_type,
&auto_connect);
if (n < 7) {
err = -EINVAL;
goto done;
}
hci_dev_lock(hdev);
err = hci_conn_params_add(hdev, &addr, addr_type, auto_connect,
hdev->le_conn_min_interval,
hdev->le_conn_max_interval);
hci_dev_unlock(hdev);
if (err)
goto done;
} else if (memcmp(buf, "del", 3) == 0) {
n = sscanf(&buf[4], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu",
&addr.b[5], &addr.b[4], &addr.b[3], &addr.b[2],
&addr.b[1], &addr.b[0], &addr_type);
if (n < 7) {
err = -EINVAL;
goto done;
}
hci_dev_lock(hdev);
hci_conn_params_del(hdev, &addr, addr_type);
hci_dev_unlock(hdev);
} else if (memcmp(buf, "clr", 3) == 0) {
hci_dev_lock(hdev);
hci_conn_params_clear(hdev);
hci_pend_le_conns_clear(hdev);
hci_update_background_scan(hdev);
hci_dev_unlock(hdev);
} else {
err = -EINVAL;
}
done:
kfree(buf);
if (err)
return err;
else
return count;
}
static const struct file_operations le_auto_conn_fops = {
.open = le_auto_conn_open,
.read = seq_read,
.write = le_auto_conn_write,
.llseek = seq_lseek,
.release = single_release,
};
/* ---- HCI requests ---- */
static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
{
BT_DBG("%s result 0x%2.2x", hdev->name, result);
if (hdev->req_status == HCI_REQ_PEND) {
hdev->req_result = result;
hdev->req_status = HCI_REQ_DONE;
wake_up_interruptible(&hdev->req_wait_q);
}
}
static void hci_req_cancel(struct hci_dev *hdev, int err)
{
BT_DBG("%s err 0x%2.2x", hdev->name, err);
if (hdev->req_status == HCI_REQ_PEND) {
hdev->req_result = err;
hdev->req_status = HCI_REQ_CANCELED;
wake_up_interruptible(&hdev->req_wait_q);
}
}
static struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
u8 event)
{
struct hci_ev_cmd_complete *ev;
struct hci_event_hdr *hdr;
struct sk_buff *skb;
hci_dev_lock(hdev);
skb = hdev->recv_evt;
hdev->recv_evt = NULL;
hci_dev_unlock(hdev);
if (!skb)
return ERR_PTR(-ENODATA);
if (skb->len < sizeof(*hdr)) {
BT_ERR("Too short HCI event");
goto failed;
}
hdr = (void *) skb->data;
skb_pull(skb, HCI_EVENT_HDR_SIZE);
if (event) {
if (hdr->evt != event)
goto failed;
return skb;
}
if (hdr->evt != HCI_EV_CMD_COMPLETE) {
BT_DBG("Last event is not cmd complete (0x%2.2x)", hdr->evt);
goto failed;
}
if (skb->len < sizeof(*ev)) {
BT_ERR("Too short cmd_complete event");
goto failed;
}
ev = (void *) skb->data;
skb_pull(skb, sizeof(*ev));
if (opcode == __le16_to_cpu(ev->opcode))
return skb;
BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
__le16_to_cpu(ev->opcode));
failed:
kfree_skb(skb);
return ERR_PTR(-ENODATA);
}
struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
const void *param, u8 event, u32 timeout)
{
DECLARE_WAITQUEUE(wait, current);
struct hci_request req;
int err = 0;
BT_DBG("%s", hdev->name);
hci_req_init(&req, hdev);
hci_req_add_ev(&req, opcode, plen, param, event);
hdev->req_status = HCI_REQ_PEND;
err = hci_req_run(&req, hci_req_sync_complete);
if (err < 0)
return ERR_PTR(err);
add_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(timeout);
remove_wait_queue(&hdev->req_wait_q, &wait);
if (signal_pending(current))
return ERR_PTR(-EINTR);
switch (hdev->req_status) {
case HCI_REQ_DONE:
err = -bt_to_errno(hdev->req_result);
break;
case HCI_REQ_CANCELED:
err = -hdev->req_result;
break;
default:
err = -ETIMEDOUT;
break;
}
hdev->req_status = hdev->req_result = 0;
BT_DBG("%s end: err %d", hdev->name, err);
if (err < 0)
return ERR_PTR(err);
return hci_get_cmd_complete(hdev, opcode, event);
}
EXPORT_SYMBOL(__hci_cmd_sync_ev);
struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
const void *param, u32 timeout)
{
return __hci_cmd_sync_ev(hdev, opcode, plen, param, 0, timeout);
}
EXPORT_SYMBOL(__hci_cmd_sync);
/* Execute request and wait for completion. */
static int __hci_req_sync(struct hci_dev *hdev,
void (*func)(struct hci_request *req,
unsigned long opt),
unsigned long opt, __u32 timeout)
{
struct hci_request req;
DECLARE_WAITQUEUE(wait, current);
int err = 0;
BT_DBG("%s start", hdev->name);
hci_req_init(&req, hdev);
hdev->req_status = HCI_REQ_PEND;
func(&req, opt);
err = hci_req_run(&req, hci_req_sync_complete);
if (err < 0) {
hdev->req_status = 0;
/* ENODATA means the HCI request command queue is empty.
* This can happen when a request with conditionals doesn't
* trigger any commands to be sent. This is normal behavior
* and should not trigger an error return.
*/
if (err == -ENODATA)
return 0;
return err;
}
add_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(timeout);
remove_wait_queue(&hdev->req_wait_q, &wait);
if (signal_pending(current))
return -EINTR;
switch (hdev->req_status) {
case HCI_REQ_DONE:
err = -bt_to_errno(hdev->req_result);
break;
case HCI_REQ_CANCELED:
err = -hdev->req_result;
break;
default:
err = -ETIMEDOUT;
break;
}
hdev->req_status = hdev->req_result = 0;
BT_DBG("%s end: err %d", hdev->name, err);
return err;
}
static int hci_req_sync(struct hci_dev *hdev,
void (*req)(struct hci_request *req,
unsigned long opt),
unsigned long opt, __u32 timeout)
{
int ret;
if (!test_bit(HCI_UP, &hdev->flags))
return -ENETDOWN;
/* Serialize all requests */
hci_req_lock(hdev);
ret = __hci_req_sync(hdev, req, opt, timeout);
hci_req_unlock(hdev);
return ret;
}
static void hci_reset_req(struct hci_request *req, unsigned long opt)
{
BT_DBG("%s %ld", req->hdev->name, opt);
/* Reset device */
set_bit(HCI_RESET, &req->hdev->flags);
hci_req_add(req, HCI_OP_RESET, 0, NULL);
}
static void bredr_init(struct hci_request *req)
{
req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
/* Read Local Supported Features */
hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
/* Read Local Version */
hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
/* Read BD Address */
hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL);
}
static void amp_init(struct hci_request *req)
{
req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED;
/* Read Local Version */
hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
/* Read Local Supported Commands */
hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
/* Read Local Supported Features */
hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
/* Read Local AMP Info */
hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
/* Read Data Blk size */
hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL);
/* Read Flow Control Mode */
hci_req_add(req, HCI_OP_READ_FLOW_CONTROL_MODE, 0, NULL);
/* Read Location Data */
hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL);
}
static void hci_init1_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
BT_DBG("%s %ld", hdev->name, opt);
/* Reset */
if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks))
hci_reset_req(req, 0);
switch (hdev->dev_type) {
case HCI_BREDR:
bredr_init(req);
break;
case HCI_AMP:
amp_init(req);
break;
default:
BT_ERR("Unknown device type %d", hdev->dev_type);
break;
}
}
static void bredr_setup(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
__le16 param;
__u8 flt_type;
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
hci_req_add(req, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
/* Read Class of Device */
hci_req_add(req, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
/* Read Local Name */
hci_req_add(req, HCI_OP_READ_LOCAL_NAME, 0, NULL);
/* Read Voice Setting */
hci_req_add(req, HCI_OP_READ_VOICE_SETTING, 0, NULL);
/* Read Number of Supported IAC */
hci_req_add(req, HCI_OP_READ_NUM_SUPPORTED_IAC, 0, NULL);
/* Read Current IAC LAP */
hci_req_add(req, HCI_OP_READ_CURRENT_IAC_LAP, 0, NULL);
/* Clear Event Filters */
flt_type = HCI_FLT_CLEAR_ALL;
hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
/* Connection accept timeout ~20 secs */
param = cpu_to_le16(0x7d00);
hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
/* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2,
* but it does not support page scan related HCI commands.
*/
if (hdev->manufacturer != 31 && hdev->hci_ver > BLUETOOTH_VER_1_1) {
hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL);
}
}
static void le_setup(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
/* Read LE Buffer Size */
hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
/* Read LE Local Supported Features */
hci_req_add(req, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
/* Read LE Supported States */
hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
/* Read LE Advertising Channel TX Power */
hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
/* Read LE White List Size */
hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
/* Clear LE White List */
hci_req_add(req, HCI_OP_LE_CLEAR_WHITE_LIST, 0, NULL);
/* LE-only controllers have LE implicitly enabled */
if (!lmp_bredr_capable(hdev))
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;
/* The second byte is 0xff instead of 0x9f (two reserved bits
* disabled) since a Broadcom 1.2 dongle doesn't respond to the
* command otherwise.
*/
u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
/* 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->hci_ver < BLUETOOTH_VER_1_2)
return;
if (lmp_bredr_capable(hdev)) {
events[4] |= 0x01; /* Flow Specification Complete */
events[4] |= 0x02; /* Inquiry Result with RSSI */
events[4] |= 0x04; /* Read Remote Extended Features Complete */
events[5] |= 0x08; /* Synchronous Connection Complete */
events[5] |= 0x10; /* Synchronous Connection Changed */
} else {
/* Use a different default for LE-only devices */
memset(events, 0, sizeof(events));
events[0] |= 0x10; /* Disconnection Complete */
events[0] |= 0x80; /* Encryption Change */
events[1] |= 0x08; /* Read Remote Version Information Complete */
events[1] |= 0x20; /* Command Complete */
events[1] |= 0x40; /* Command Status */
events[1] |= 0x80; /* Hardware Error */
events[2] |= 0x04; /* Number of Completed Packets */
events[3] |= 0x02; /* Data Buffer Overflow */
events[5] |= 0x80; /* Encryption Key Refresh Complete */
}
if (lmp_inq_rssi_capable(hdev))
events[4] |= 0x02; /* Inquiry Result with RSSI */
if (lmp_sniffsubr_capable(hdev))
events[5] |= 0x20; /* Sniff Subrating */
if (lmp_pause_enc_capable(hdev))
events[5] |= 0x80; /* Encryption Key Refresh Complete */
if (lmp_ext_inq_capable(hdev))
events[5] |= 0x40; /* Extended Inquiry Result */
if (lmp_no_flush_capable(hdev))
events[7] |= 0x01; /* Enhanced Flush Complete */
if (lmp_lsto_capable(hdev))
events[6] |= 0x80; /* Link Supervision Timeout Changed */
if (lmp_ssp_capable(hdev)) {
events[6] |= 0x01; /* IO Capability Request */
events[6] |= 0x02; /* IO Capability Response */
events[6] |= 0x04; /* User Confirmation Request */
events[6] |= 0x08; /* User Passkey Request */
events[6] |= 0x10; /* Remote OOB Data Request */
events[6] |= 0x20; /* Simple Pairing Complete */
events[7] |= 0x04; /* User Passkey Notification */
events[7] |= 0x08; /* Keypress Notification */
events[7] |= 0x10; /* Remote Host Supported
* Features Notification
*/
}
if (lmp_le_capable(hdev))
events[7] |= 0x20; /* LE Meta-Event */
hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
if (lmp_le_capable(hdev)) {
memset(events, 0, sizeof(events));
events[0] = 0x1f;
hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK,
sizeof(events), events);
}
}
static void hci_init2_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
if (lmp_bredr_capable(hdev))
bredr_setup(req);
else
clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
if (lmp_le_capable(hdev))
le_setup(req);
hci_setup_event_mask(req);
/* AVM Berlin (31), aka "BlueFRITZ!", doesn't support the read
* local supported commands HCI command.
*/
if (hdev->manufacturer != 31 && hdev->hci_ver > BLUETOOTH_VER_1_1)
hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
if (lmp_ssp_capable(hdev)) {
/* When SSP is available, then the host features page
* should also be available as well. However some
* controllers list the max_page as 0 as long as SSP
* has not been enabled. To achieve proper debugging
* output, force the minimum max_page to 1 at least.
*/
hdev->max_page = 0x01;
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
u8 mode = 0x01;
hci_req_add(req, HCI_OP_WRITE_SSP_MODE,
sizeof(mode), &mode);
} else {
struct hci_cp_write_eir cp;
memset(hdev->eir, 0, sizeof(hdev->eir));
memset(&cp, 0, sizeof(cp));
hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
}
}
if (lmp_inq_rssi_capable(hdev))
hci_setup_inquiry_mode(req);
if (lmp_inq_tx_pwr_capable(hdev))
hci_req_add(req, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
if (lmp_ext_feat_capable(hdev)) {
struct hci_cp_read_local_ext_features cp;
cp.page = 0x01;
hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES,
sizeof(cp), &cp);
}
if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
u8 enable = 1;
hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
&enable);
}
}
static void hci_setup_link_policy(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
struct hci_cp_write_def_link_policy cp;
u16 link_policy = 0;
if (lmp_rswitch_capable(hdev))
link_policy |= HCI_LP_RSWITCH;
if (lmp_hold_capable(hdev))
link_policy |= HCI_LP_HOLD;
if (lmp_sniff_capable(hdev))
link_policy |= HCI_LP_SNIFF;
if (lmp_park_capable(hdev))
link_policy |= HCI_LP_PARK;
cp.policy = cpu_to_le16(link_policy);
hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
}
static void hci_set_le_support(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
struct hci_cp_write_le_host_supported cp;
/* LE-only devices do not support explicit enablement */
if (!lmp_bredr_capable(hdev))
return;
memset(&cp, 0, sizeof(cp));
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
cp.le = 0x01;
cp.simul = lmp_le_br_capable(hdev);
}
if (cp.le != lmp_host_le_capable(hdev))
hci_req_add(req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
&cp);
}
static void hci_set_event_mask_page_2(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
u8 events[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* If Connectionless Slave Broadcast master role is supported
* enable all necessary events for it.
*/
if (lmp_csb_master_capable(hdev)) {
events[1] |= 0x40; /* Triggered Clock Capture */
events[1] |= 0x80; /* Synchronization Train Complete */
events[2] |= 0x10; /* Slave Page Response Timeout */
events[2] |= 0x20; /* CSB Channel Map Change */
}
/* If Connectionless Slave Broadcast slave role is supported
* enable all necessary events for it.
*/
if (lmp_csb_slave_capable(hdev)) {
events[2] |= 0x01; /* Synchronization Train Received */
events[2] |= 0x02; /* CSB Receive */
events[2] |= 0x04; /* CSB Timeout */
events[2] |= 0x08; /* Truncated Page Complete */
}
/* Enable Authenticated Payload Timeout Expired event if supported */
if (lmp_ping_capable(hdev))
events[2] |= 0x80;
hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events);
}
static void hci_init3_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
u8 p;
/* 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);
}
if (hdev->commands[5] & 0x10)
hci_setup_link_policy(req);
if (lmp_le_capable(hdev))
hci_set_le_support(req);
/* Read features beyond page 1 if available */
for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
struct hci_cp_read_local_ext_features cp;
cp.page = p;
hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES,
sizeof(cp), &cp);
}
}
static void hci_init4_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
/* 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);
/* Check for Synchronization Train support */
if (lmp_sync_train_capable(hdev))
hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
/* Enable Secure Connections if supported and configured */
if ((lmp_sc_capable(hdev) ||
test_bit(HCI_FORCE_SC, &hdev->dev_flags)) &&
test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
u8 support = 0x01;
hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT,
sizeof(support), &support);
}
}
static int __hci_init(struct hci_dev *hdev)
{
int err;
err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT);
if (err < 0)
return err;
/* The Device Under Test (DUT) mode is special and available for
* all controller types. So just create it early on.
*/
if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev,
&dut_mode_fops);
}
/* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode
* BR/EDR/LE type controllers. AMP controllers only need the
* first stage init.
*/
if (hdev->dev_type != HCI_BREDR)
return 0;
err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT);
if (err < 0)
return err;
err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT);
if (err < 0)
return err;
err = __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT);
if (err < 0)
return err;
/* Only create debugfs entries during the initial setup
* phase and not every time the controller gets powered on.
*/
if (!test_bit(HCI_SETUP, &hdev->dev_flags))
return 0;
debugfs_create_file("features", 0444, hdev->debugfs, hdev,
&features_fops);
debugfs_create_u16("manufacturer", 0444, hdev->debugfs,
&hdev->manufacturer);
debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
&blacklist_fops);
debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
if (lmp_bredr_capable(hdev)) {
debugfs_create_file("inquiry_cache", 0444, hdev->debugfs,
hdev, &inquiry_cache_fops);
debugfs_create_file("link_keys", 0400, hdev->debugfs,
hdev, &link_keys_fops);
debugfs_create_file("dev_class", 0444, hdev->debugfs,
hdev, &dev_class_fops);
debugfs_create_file("voice_setting", 0444, hdev->debugfs,
hdev, &voice_setting_fops);
}
if (lmp_ssp_capable(hdev)) {
debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
hdev, &auto_accept_delay_fops);
debugfs_create_file("ssp_debug_mode", 0644, hdev->debugfs,
hdev, &ssp_debug_mode_fops);
debugfs_create_file("force_sc_support", 0644, hdev->debugfs,
hdev, &force_sc_support_fops);
debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
hdev, &sc_only_mode_fops);
}
if (lmp_sniff_capable(hdev)) {
debugfs_create_file("idle_timeout", 0644, hdev->debugfs,
hdev, &idle_timeout_fops);
debugfs_create_file("sniff_min_interval", 0644, hdev->debugfs,
hdev, &sniff_min_interval_fops);
debugfs_create_file("sniff_max_interval", 0644, hdev->debugfs,
hdev, &sniff_max_interval_fops);
}
if (lmp_le_capable(hdev)) {
debugfs_create_file("identity", 0400, hdev->debugfs,
hdev, &identity_fops);
debugfs_create_file("rpa_timeout", 0644, hdev->debugfs,
hdev, &rpa_timeout_fops);
debugfs_create_file("random_address", 0444, hdev->debugfs,
hdev, &random_address_fops);
debugfs_create_file("static_address", 0444, hdev->debugfs,
hdev, &static_address_fops);
/* For controllers with a public address, provide a debug
* option to force the usage of the configured static
* address. By default the public address is used.
*/
if (bacmp(&hdev->bdaddr, BDADDR_ANY))
debugfs_create_file("force_static_address", 0644,
hdev->debugfs, hdev,
&force_static_address_fops);
debugfs_create_u8("white_list_size", 0444, hdev->debugfs,
&hdev->le_white_list_size);
debugfs_create_file("white_list", 0444, hdev->debugfs, hdev,
&white_list_fops);
debugfs_create_file("identity_resolving_keys", 0400,
hdev->debugfs, hdev,
&identity_resolving_keys_fops);
debugfs_create_file("long_term_keys", 0400, hdev->debugfs,
hdev, &long_term_keys_fops);
debugfs_create_file("conn_min_interval", 0644, hdev->debugfs,
hdev, &conn_min_interval_fops);
debugfs_create_file("conn_max_interval", 0644, hdev->debugfs,
hdev, &conn_max_interval_fops);
debugfs_create_file("adv_channel_map", 0644, hdev->debugfs,
hdev, &adv_channel_map_fops);
debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev,
&lowpan_debugfs_fops);
debugfs_create_file("le_auto_conn", 0644, hdev->debugfs, hdev,
&le_auto_conn_fops);
}
return 0;
}
static void hci_scan_req(struct hci_request *req, unsigned long opt)
{
__u8 scan = opt;
BT_DBG("%s %x", req->hdev->name, scan);
/* Inquiry and Page scans */
hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
}
static void hci_auth_req(struct hci_request *req, unsigned long opt)
{
__u8 auth = opt;
BT_DBG("%s %x", req->hdev->name, auth);
/* Authentication */
hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth);
}
static void hci_encrypt_req(struct hci_request *req, unsigned long opt)
{
__u8 encrypt = opt;
BT_DBG("%s %x", req->hdev->name, encrypt);
/* Encryption */
hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt);
}
static void hci_linkpol_req(struct hci_request *req, unsigned long opt)
{
__le16 policy = cpu_to_le16(opt);
BT_DBG("%s %x", req->hdev->name, policy);
/* Default link policy */
hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy);
}
/* Get HCI device by index.
* Device is held on return. */
struct hci_dev *hci_dev_get(int index)
{
struct hci_dev *hdev = NULL, *d;
BT_DBG("%d", index);
if (index < 0)
return NULL;
read_lock(&hci_dev_list_lock);
list_for_each_entry(d, &hci_dev_list, list) {
if (d->id == index) {
hdev = hci_dev_hold(d);
break;
}
}
read_unlock(&hci_dev_list_lock);
return hdev;
}
/* ---- Inquiry support ---- */
bool hci_discovery_active(struct hci_dev *hdev)
{
struct discovery_state *discov = &hdev->discovery;
switch (discov->state) {
case DISCOVERY_FINDING:
case DISCOVERY_RESOLVING:
return true;
default:
return false;
}
}
void hci_discovery_set_state(struct hci_dev *hdev, int state)
{
BT_DBG("%s state %u -> %u", hdev->name, hdev->discovery.state, state);
if (hdev->discovery.state == state)
return;
switch (state) {
case DISCOVERY_STOPPED:
hci_update_background_scan(hdev);
if (hdev->discovery.state != DISCOVERY_STARTING)
mgmt_discovering(hdev, 0);
break;
case DISCOVERY_STARTING:
break;
case DISCOVERY_FINDING:
mgmt_discovering(hdev, 1);
break;
case DISCOVERY_RESOLVING:
break;
case DISCOVERY_STOPPING:
break;
}
hdev->discovery.state = state;
}
void hci_inquiry_cache_flush(struct hci_dev *hdev)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *p, *n;
list_for_each_entry_safe(p, n, &cache->all, all) {
list_del(&p->all);
kfree(p);
}
INIT_LIST_HEAD(&cache->unknown);
INIT_LIST_HEAD(&cache->resolve);
}
struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
bdaddr_t *bdaddr)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
BT_DBG("cache %p, %pMR", cache, bdaddr);
list_for_each_entry(e, &cache->all, all) {
if (!bacmp(&e->data.bdaddr, bdaddr))
return e;
}
return NULL;
}
struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
bdaddr_t *bdaddr)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
BT_DBG("cache %p, %pMR", cache, bdaddr);
list_for_each_entry(e, &cache->unknown, list) {
if (!bacmp(&e->data.bdaddr, bdaddr))
return e;
}
return NULL;
}
struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
bdaddr_t *bdaddr,
int state)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state);
list_for_each_entry(e, &cache->resolve, list) {
if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state)
return e;
if (!bacmp(&e->data.bdaddr, bdaddr))
return e;
}
return NULL;
}
void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
struct inquiry_entry *ie)
{
struct discovery_state *cache = &hdev->discovery;
struct list_head *pos = &cache->resolve;
struct inquiry_entry *p;
list_del(&ie->list);
list_for_each_entry(p, &cache->resolve, list) {
if (p->name_state != NAME_PENDING &&
abs(p->data.rssi) >= abs(ie->data.rssi))
break;
pos = &p->list;
}
list_add(&ie->list, pos);
}
bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
bool name_known, bool *ssp)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *ie;
BT_DBG("cache %p, %pMR", cache, &data->bdaddr);
hci_remove_remote_oob_data(hdev, &data->bdaddr);
if (ssp)
*ssp = data->ssp_mode;
ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr);
if (ie) {
if (ie->data.ssp_mode && ssp)
*ssp = true;
if (ie->name_state == NAME_NEEDED &&
data->rssi != ie->data.rssi) {
ie->data.rssi = data->rssi;
hci_inquiry_cache_update_resolve(hdev, ie);
}
goto update;
}
/* Entry not in the cache. Add new one. */
ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC);
if (!ie)
return false;
list_add(&ie->all, &cache->all);
if (name_known) {
ie->name_state = NAME_KNOWN;
} else {
ie->name_state = NAME_NOT_KNOWN;
list_add(&ie->list, &cache->unknown);
}
update:
if (name_known && ie->name_state != NAME_KNOWN &&
ie->name_state != NAME_PENDING) {
ie->name_state = NAME_KNOWN;
list_del(&ie->list);
}
memcpy(&ie->data, data, sizeof(*data));
ie->timestamp = jiffies;
cache->timestamp = jiffies;
if (ie->name_state == NAME_NOT_KNOWN)
return false;
return true;
}
static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_info *info = (struct inquiry_info *) buf;
struct inquiry_entry *e;
int copied = 0;
list_for_each_entry(e, &cache->all, all) {
struct inquiry_data *data = &e->data;
if (copied >= num)
break;
bacpy(&info->bdaddr, &data->bdaddr);
info->pscan_rep_mode = data->pscan_rep_mode;
info->pscan_period_mode = data->pscan_period_mode;
info->pscan_mode = data->pscan_mode;
memcpy(info->dev_class, data->dev_class, 3);
info->clock_offset = data->clock_offset;
info++;
copied++;
}
BT_DBG("cache %p, copied %d", cache, copied);
return copied;
}
static void hci_inq_req(struct hci_request *req, unsigned long opt)
{
struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt;
struct hci_dev *hdev = req->hdev;
struct hci_cp_inquiry cp;
BT_DBG("%s", hdev->name);
if (test_bit(HCI_INQUIRY, &hdev->flags))
return;
/* Start Inquiry */
memcpy(&cp.lap, &ir->lap, 3);
cp.length = ir->length;
cp.num_rsp = ir->num_rsp;
hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
}
static int wait_inquiry(void *word)
{
schedule();
return signal_pending(current);
}
int hci_inquiry(void __user *arg)
{
__u8 __user *ptr = arg;
struct hci_inquiry_req ir;
struct hci_dev *hdev;
int err = 0, do_inquiry = 0, max_rsp;
long timeo;
__u8 *buf;
if (copy_from_user(&ir, ptr, sizeof(ir)))
return -EFAULT;
hdev = hci_dev_get(ir.dev_id);
if (!hdev)
return -ENODEV;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
err = -EBUSY;
goto done;
}
if (hdev->dev_type != HCI_BREDR) {
err = -EOPNOTSUPP;
goto done;
}
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
err = -EOPNOTSUPP;
goto done;
}
hci_dev_lock(hdev);
if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) {
hci_inquiry_cache_flush(hdev);
do_inquiry = 1;
}
hci_dev_unlock(hdev);
timeo = ir.length * msecs_to_jiffies(2000);
if (do_inquiry) {
err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir,
timeo);
if (err < 0)
goto done;
/* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is
* cleared). If it is interrupted by a signal, return -EINTR.
*/
if (wait_on_bit(&hdev->flags, HCI_INQUIRY, wait_inquiry,
TASK_INTERRUPTIBLE))
return -EINTR;
}
/* for unlimited number of responses we will use buffer with
* 255 entries
*/
max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp;
/* cache_dump can't sleep. Therefore we allocate temp buffer and then
* copy it to the user space.
*/
buf = kmalloc(sizeof(struct inquiry_info) * max_rsp, GFP_KERNEL);
if (!buf) {
err = -ENOMEM;
goto done;
}
hci_dev_lock(hdev);
ir.num_rsp = inquiry_cache_dump(hdev, max_rsp, buf);
hci_dev_unlock(hdev);
BT_DBG("num_rsp %d", ir.num_rsp);
if (!copy_to_user(ptr, &ir, sizeof(ir))) {
ptr += sizeof(ir);
if (copy_to_user(ptr, buf, sizeof(struct inquiry_info) *
ir.num_rsp))
err = -EFAULT;
} else
err = -EFAULT;
kfree(buf);
done:
hci_dev_put(hdev);
return err;
}
static int hci_dev_do_open(struct hci_dev *hdev)
{
int ret = 0;
BT_DBG("%s %p", hdev->name, hdev);
hci_req_lock(hdev);
if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
ret = -ENODEV;
goto done;
}
if (!test_bit(HCI_SETUP, &hdev->dev_flags)) {
/* Check for rfkill but allow the HCI setup stage to
* proceed (which in itself doesn't cause any RF activity).
*/
if (test_bit(HCI_RFKILLED, &hdev->dev_flags)) {
ret = -ERFKILL;
goto done;
}
/* Check for valid public address or a configured static
* random adddress, but let the HCI setup proceed to
* be able to determine if there is a public address
* or not.
*
* In case of user channel usage, it is not important
* if a public address or static random address is
* available.
*
* This check is only valid for BR/EDR controllers
* since AMP controllers do not have an address.
*/
if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) &&
hdev->dev_type == HCI_BREDR &&
!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
!bacmp(&hdev->static_addr, BDADDR_ANY)) {
ret = -EADDRNOTAVAIL;
goto done;
}
}
if (test_bit(HCI_UP, &hdev->flags)) {
ret = -EALREADY;
goto done;
}
if (hdev->open(hdev)) {
ret = -EIO;
goto done;
}
atomic_set(&hdev->cmd_cnt, 1);
set_bit(HCI_INIT, &hdev->flags);
if (hdev->setup && test_bit(HCI_SETUP, &hdev->dev_flags))
ret = hdev->setup(hdev);
if (!ret) {
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
set_bit(HCI_RAW, &hdev->flags);
if (!test_bit(HCI_RAW, &hdev->flags) &&
!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
ret = __hci_init(hdev);
}
clear_bit(HCI_INIT, &hdev->flags);
if (!ret) {
hci_dev_hold(hdev);
set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP);
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) &&
hdev->dev_type == HCI_BREDR) {
hci_dev_lock(hdev);
mgmt_powered(hdev, 1);
hci_dev_unlock(hdev);
}
} else {
/* Init failed, cleanup */
flush_work(&hdev->tx_work);
flush_work(&hdev->cmd_work);
flush_work(&hdev->rx_work);
skb_queue_purge(&hdev->cmd_q);
skb_queue_purge(&hdev->rx_q);
if (hdev->flush)
hdev->flush(hdev);
if (hdev->sent_cmd) {
kfree_skb(hdev->sent_cmd);
hdev->sent_cmd = NULL;
}
hdev->close(hdev);
hdev->flags = 0;
}
done:
hci_req_unlock(hdev);
return ret;
}
/* ---- HCI ioctl helpers ---- */
int hci_dev_open(__u16 dev)
{
struct hci_dev *hdev;
int err;
hdev = hci_dev_get(dev);
if (!hdev)
return -ENODEV;
/* We need to ensure that no other power on/off work is pending
* before proceeding to call hci_dev_do_open. This is
* particularly important if the setup procedure has not yet
* completed.
*/
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
cancel_delayed_work(&hdev->power_off);
/* After this call it is guaranteed that the setup procedure
* has finished. This means that error conditions like RFKILL
* or no valid public or static random address apply.
*/
flush_workqueue(hdev->req_workqueue);
err = hci_dev_do_open(hdev);
hci_dev_put(hdev);
return err;
}
static int hci_dev_do_close(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);
cancel_delayed_work(&hdev->power_off);
hci_req_cancel(hdev, ENODEV);
hci_req_lock(hdev);
if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
del_timer_sync(&hdev->cmd_timer);
hci_req_unlock(hdev);
return 0;
}
/* Flush RX and TX works */
flush_work(&hdev->tx_work);
flush_work(&hdev->rx_work);
if (hdev->discov_timeout > 0) {
cancel_delayed_work(&hdev->discov_off);
hdev->discov_timeout = 0;
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
}
if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
cancel_delayed_work(&hdev->service_cache);
cancel_delayed_work_sync(&hdev->le_scan_disable);
if (test_bit(HCI_MGMT, &hdev->dev_flags))
cancel_delayed_work_sync(&hdev->rpa_expired);
hci_dev_lock(hdev);
hci_inquiry_cache_flush(hdev);
hci_conn_hash_flush(hdev);
hci_pend_le_conns_clear(hdev);
hci_dev_unlock(hdev);
hci_notify(hdev, HCI_DEV_DOWN);
if (hdev->flush)
hdev->flush(hdev);
/* Reset device */
skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1);
if (!test_bit(HCI_RAW, &hdev->flags) &&
!test_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) {
set_bit(HCI_INIT, &hdev->flags);
__hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT);
clear_bit(HCI_INIT, &hdev->flags);
}
/* flush cmd work */
flush_work(&hdev->cmd_work);
/* Drop queues */
skb_queue_purge(&hdev->rx_q);
skb_queue_purge(&hdev->cmd_q);
skb_queue_purge(&hdev->raw_q);
/* Drop last sent command */
if (hdev->sent_cmd) {
del_timer_sync(&hdev->cmd_timer);
kfree_skb(hdev->sent_cmd);
hdev->sent_cmd = NULL;
}
kfree_skb(hdev->recv_evt);
hdev->recv_evt = NULL;
/* After this point our queues are empty
* and no tasks are scheduled. */
hdev->close(hdev);
/* Clear flags */
hdev->flags = 0;
hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
if (hdev->dev_type == HCI_BREDR) {
hci_dev_lock(hdev);
mgmt_powered(hdev, 0);
hci_dev_unlock(hdev);
}
}
/* Controller radio is available but is currently powered down */
hdev->amp_status = AMP_STATUS_POWERED_DOWN;
memset(hdev->eir, 0, sizeof(hdev->eir));
memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
bacpy(&hdev->random_addr, BDADDR_ANY);
hci_req_unlock(hdev);
hci_dev_put(hdev);
return 0;
}
int hci_dev_close(__u16 dev)
{
struct hci_dev *hdev;
int err;
hdev = hci_dev_get(dev);
if (!hdev)
return -ENODEV;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
err = -EBUSY;
goto done;
}
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
cancel_delayed_work(&hdev->power_off);
err = hci_dev_do_close(hdev);
done:
hci_dev_put(hdev);
return err;
}
int hci_dev_reset(__u16 dev)
{
struct hci_dev *hdev;
int ret = 0;
hdev = hci_dev_get(dev);
if (!hdev)
return -ENODEV;
hci_req_lock(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
ret = -ENETDOWN;
goto done;
}
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
ret = -EBUSY;
goto done;
}
/* Drop queues */
skb_queue_purge(&hdev->rx_q);
skb_queue_purge(&hdev->cmd_q);
hci_dev_lock(hdev);
hci_inquiry_cache_flush(hdev);
hci_conn_hash_flush(hdev);
hci_dev_unlock(hdev);
if (hdev->flush)
hdev->flush(hdev);
atomic_set(&hdev->cmd_cnt, 1);
hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0;
if (!test_bit(HCI_RAW, &hdev->flags))
ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT);
done:
hci_req_unlock(hdev);
hci_dev_put(hdev);
return ret;
}
int hci_dev_reset_stat(__u16 dev)
{
struct hci_dev *hdev;
int ret = 0;
hdev = hci_dev_get(dev);
if (!hdev)
return -ENODEV;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
ret = -EBUSY;
goto done;
}
memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
done:
hci_dev_put(hdev);
return ret;
}
int hci_dev_cmd(unsigned int cmd, void __user *arg)
{
struct hci_dev *hdev;
struct hci_dev_req dr;
int err = 0;
if (copy_from_user(&dr, arg, sizeof(dr)))
return -EFAULT;
hdev = hci_dev_get(dr.dev_id);
if (!hdev)
return -ENODEV;
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
err = -EBUSY;
goto done;
}
if (hdev->dev_type != HCI_BREDR) {
err = -EOPNOTSUPP;
goto done;
}
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
err = -EOPNOTSUPP;
goto done;
}
switch (cmd) {
case HCISETAUTH:
err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
HCI_INIT_TIMEOUT);
break;
case HCISETENCRYPT:
if (!lmp_encrypt_capable(hdev)) {
err = -EOPNOTSUPP;
break;
}
if (!test_bit(HCI_AUTH, &hdev->flags)) {
/* Auth must be enabled first */
err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
HCI_INIT_TIMEOUT);
if (err)
break;
}
err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt,
HCI_INIT_TIMEOUT);
break;
case HCISETSCAN:
err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt,
HCI_INIT_TIMEOUT);
break;
case HCISETLINKPOL:
err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt,
HCI_INIT_TIMEOUT);
break;
case HCISETLINKMODE:
hdev->link_mode = ((__u16) dr.dev_opt) &
(HCI_LM_MASTER | HCI_LM_ACCEPT);
break;
case HCISETPTYPE:
hdev->pkt_type = (__u16) dr.dev_opt;
break;
case HCISETACLMTU:
hdev->acl_mtu = *((__u16 *) &dr.dev_opt + 1);
hdev->acl_pkts = *((__u16 *) &dr.dev_opt + 0);
break;
case HCISETSCOMTU:
hdev->sco_mtu = *((__u16 *) &dr.dev_opt + 1);
hdev->sco_pkts = *((__u16 *) &dr.dev_opt + 0);
break;
default:
err = -EINVAL;
break;
}
done:
hci_dev_put(hdev);
return err;
}
int hci_get_dev_list(void __user *arg)
{
struct hci_dev *hdev;
struct hci_dev_list_req *dl;
struct hci_dev_req *dr;
int n = 0, size, err;
__u16 dev_num;
if (get_user(dev_num, (__u16 __user *) arg))
return -EFAULT;
if (!dev_num || dev_num > (PAGE_SIZE * 2) / sizeof(*dr))
return -EINVAL;
size = sizeof(*dl) + dev_num * sizeof(*dr);
dl = kzalloc(size, GFP_KERNEL);
if (!dl)
return -ENOMEM;
dr = dl->dev_req;
read_lock(&hci_dev_list_lock);
list_for_each_entry(hdev, &hci_dev_list, list) {
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
cancel_delayed_work(&hdev->power_off);
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
set_bit(HCI_PAIRABLE, &hdev->dev_flags);
(dr + n)->dev_id = hdev->id;
(dr + n)->dev_opt = hdev->flags;
if (++n >= dev_num)
break;
}
read_unlock(&hci_dev_list_lock);
dl->dev_num = n;
size = sizeof(*dl) + n * sizeof(*dr);
err = copy_to_user(arg, dl, size);
kfree(dl);
return err ? -EFAULT : 0;
}
int hci_get_dev_info(void __user *arg)
{
struct hci_dev *hdev;
struct hci_dev_info di;
int err = 0;
if (copy_from_user(&di, arg, sizeof(di)))
return -EFAULT;
hdev = hci_dev_get(di.dev_id);
if (!hdev)
return -ENODEV;
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
cancel_delayed_work_sync(&hdev->power_off);
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
set_bit(HCI_PAIRABLE, &hdev->dev_flags);
strcpy(di.name, hdev->name);
di.bdaddr = hdev->bdaddr;
di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4);
di.flags = hdev->flags;
di.pkt_type = hdev->pkt_type;
if (lmp_bredr_capable(hdev)) {
di.acl_mtu = hdev->acl_mtu;
di.acl_pkts = hdev->acl_pkts;
di.sco_mtu = hdev->sco_mtu;
di.sco_pkts = hdev->sco_pkts;
} else {
di.acl_mtu = hdev->le_mtu;
di.acl_pkts = hdev->le_pkts;
di.sco_mtu = 0;
di.sco_pkts = 0;
}
di.link_policy = hdev->link_policy;
di.link_mode = hdev->link_mo