/* HCI ID Numbering */
static DEFINE_IDA(hci_index_ida);
+/* ----- HCI requests ----- */
+
+#define HCI_REQ_DONE 0
+#define HCI_REQ_PEND 1
+#define HCI_REQ_CANCELED 2
+
+#define hci_req_lock(d) mutex_lock(&d->req_lock)
+#define hci_req_unlock(d) mutex_unlock(&d->req_lock)
+
/* ---- HCI notifications ---- */
static void hci_notify(struct hci_dev *hdev, int event)
.release = single_release,
};
+static int whitelist_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->whitelist, list)
+ seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
+ hci_dev_unlock(hdev);
+
+ return 0;
+}
+
+static int whitelist_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, whitelist_show, inode->i_private);
+}
+
+static const struct file_operations whitelist_fops = {
+ .open = whitelist_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;
/* 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);
/* 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 (hdev->le_features[0] & HCI_LE_ENCRYPTION) {
+ events[0] |= 0x80; /* Encryption Change */
+ events[5] |= 0x80; /* Encryption Key Refresh Complete */
+ }
}
if (lmp_inq_rssi_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)
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.
*/
}
/* Enable Authenticated Payload Timeout Expired event if supported */
- if (lmp_ping_capable(hdev))
+ if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING)
events[2] |= 0x80;
hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events);
struct hci_dev *hdev = req->hdev;
u8 p;
+ 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.
if (hdev->commands[5] & 0x10)
hci_setup_link_policy(req);
- if (lmp_le_capable(hdev))
+ if (lmp_le_capable(hdev)) {
+ u8 events[8];
+
+ memset(events, 0, sizeof(events));
+ events[0] = 0x0f;
+
+ if (hdev->le_features[0] & HCI_LE_ENCRYPTION)
+ events[0] |= 0x10; /* LE Long Term Key Request */
+
+ /* If controller supports the Connection Parameters Request
+ * Link Layer Procedure, enable the corresponding event.
+ */
+ if (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC)
+ events[0] |= 0x20; /* LE Remote Connection
+ * Parameter Request
+ */
+
+ hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
+ events);
+
+ if (hdev->commands[25] & 0x40) {
+ /* Read LE Advertising Channel TX Power */
+ hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
+ }
+
hci_set_le_support(req);
+ }
/* Read features beyond page 1 if available */
for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
if (hdev->commands[22] & 0x04)
hci_set_event_mask_page_2(req);
+ /* Read local codec list if the HCI command is supported */
+ if (hdev->commands[29] & 0x20)
+ hci_req_add(req, HCI_OP_READ_LOCAL_CODECS, 0, NULL);
+
+ /* Get MWS transport configuration if the HCI command is supported */
+ if (hdev->commands[30] & 0x08)
+ hci_req_add(req, HCI_OP_GET_MWS_TRANSPORT_CONFIG, 0, NULL);
+
/* Check for Synchronization Train support */
if (lmp_sync_train_capable(hdev))
hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
&blacklist_fops);
+ debugfs_create_file("whitelist", 0444, hdev->debugfs, hdev,
+ &whitelist_fops);
debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
return 0;
}
+static void hci_init0_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);
+
+ /* Read Local Version */
+ hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
+
+ /* Read BD Address */
+ if (hdev->set_bdaddr)
+ hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL);
+}
+
+static int __hci_unconf_init(struct hci_dev *hdev)
+{
+ int err;
+
+ if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+ return 0;
+
+ err = __hci_req_sync(hdev, hci_init0_req, 0, HCI_INIT_TIMEOUT);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
static void hci_scan_req(struct hci_request *req, unsigned long opt)
{
__u8 scan = opt;
void hci_discovery_set_state(struct hci_dev *hdev, int state)
{
+ int old_state = hdev->discovery.state;
+
BT_DBG("%s state %u -> %u", hdev->name, hdev->discovery.state, state);
- if (hdev->discovery.state == state)
+ if (old_state == state)
return;
+ hdev->discovery.state = state;
+
switch (state) {
case DISCOVERY_STOPPED:
hci_update_background_scan(hdev);
- if (hdev->discovery.state != DISCOVERY_STARTING)
+ if (old_state != DISCOVERY_STARTING)
mgmt_discovering(hdev, 0);
break;
case DISCOVERY_STARTING:
case DISCOVERY_STOPPING:
break;
}
-
- hdev->discovery.state = state;
}
void hci_inquiry_cache_flush(struct hci_dev *hdev)
}
/* Entry not in the cache. Add new one. */
- ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC);
+ ie = kzalloc(sizeof(*ie), GFP_KERNEL);
if (!ie) {
flags |= MGMT_DEV_FOUND_CONFIRM_NAME;
goto done;
goto done;
}
- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+ if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
err = -EOPNOTSUPP;
goto done;
}
goto done;
}
- if (!test_bit(HCI_SETUP, &hdev->dev_flags)) {
+ if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
+ !test_bit(HCI_CONFIG, &hdev->dev_flags)) {
/* Check for rfkill but allow the HCI setup stage to
* proceed (which in itself doesn't cause any RF activity).
*/
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 (test_bit(HCI_SETUP, &hdev->dev_flags)) {
+ if (hdev->setup)
+ ret = hdev->setup(hdev);
+
+ /* The transport driver can set these quirks before
+ * creating the HCI device or in its setup callback.
+ *
+ * In case any of them is set, the controller has to
+ * start up as unconfigured.
+ */
+ if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
+ test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks))
+ set_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
+
+ /* For an unconfigured controller it is required to
+ * read at least the version information provided by
+ * the Read Local Version Information command.
+ *
+ * If the set_bdaddr driver callback is provided, then
+ * also the original Bluetooth public device address
+ * will be read using the Read BD Address command.
+ */
+ if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
+ ret = __hci_unconf_init(hdev);
+ }
+
+ if (test_bit(HCI_CONFIG, &hdev->dev_flags)) {
+ /* If public address change is configured, ensure that
+ * the address gets programmed. If the driver does not
+ * support changing the public address, fail the power
+ * on procedure.
+ */
+ if (bacmp(&hdev->public_addr, BDADDR_ANY) &&
+ hdev->set_bdaddr)
+ ret = hdev->set_bdaddr(hdev, &hdev->public_addr);
+ else
+ ret = -EADDRNOTAVAIL;
+ }
if (!ret) {
- if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks) &&
+ if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
ret = __hci_init(hdev);
}
set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP);
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
+ !test_bit(HCI_CONFIG, &hdev->dev_flags) &&
+ !test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) &&
hdev->dev_type == HCI_BREDR) {
hci_dev_lock(hdev);
if (!hdev)
return -ENODEV;
- /* Devices that are marked for raw-only usage can only be powered
+ /* Devices that are marked as unconfigured can only be powered
* up as user channel. Trying to bring them up as normal devices
* will result into a failure. Only user channel operation is
* possible.
* HCI_USER_CHANNEL will be set first before attempting to
* open the device.
*/
- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks) &&
+ if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
err = -EOPNOTSUPP;
goto done;
*/
flush_workqueue(hdev->req_workqueue);
+ /* For controllers not using the management interface and that
+ * are brought up using legacy ioctl, set the HCI_PAIRABLE bit
+ * so that pairing works for them. Once the management interface
+ * is in use this bit will be cleared again and userspace has
+ * to explicitly enable it.
+ */
+ if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) &&
+ !test_bit(HCI_MGMT, &hdev->dev_flags))
+ set_bit(HCI_PAIRABLE, &hdev->dev_flags);
+
err = hci_dev_do_open(hdev);
done:
return err;
}
+/* This function requires the caller holds hdev->lock */
+static void hci_pend_le_actions_clear(struct hci_dev *hdev)
+{
+ struct hci_conn_params *p;
+
+ list_for_each_entry(p, &hdev->le_conn_params, list)
+ list_del_init(&p->action);
+
+ BT_DBG("All LE pending actions cleared");
+}
+
static int hci_dev_do_close(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);
hci_dev_lock(hdev);
hci_inquiry_cache_flush(hdev);
hci_conn_hash_flush(hdev);
- hci_pend_le_conns_clear(hdev);
+ hci_pend_le_actions_clear(hdev);
hci_dev_unlock(hdev);
hci_notify(hdev, HCI_DEV_DOWN);
/* Reset device */
skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1);
- if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks) &&
- !test_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
+ if (!test_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
+ !test_bit(HCI_UNCONFIGURED, &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);
goto done;
}
- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+ if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
ret = -EOPNOTSUPP;
goto done;
}
goto done;
}
- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+ if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
ret = -EOPNOTSUPP;
goto done;
}
return ret;
}
+static void hci_update_scan_state(struct hci_dev *hdev, u8 scan)
+{
+ bool conn_changed, discov_changed;
+
+ BT_DBG("%s scan 0x%02x", hdev->name, scan);
+
+ if ((scan & SCAN_PAGE))
+ conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
+ &hdev->dev_flags);
+ else
+ conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
+ &hdev->dev_flags);
+
+ if ((scan & SCAN_INQUIRY)) {
+ discov_changed = !test_and_set_bit(HCI_DISCOVERABLE,
+ &hdev->dev_flags);
+ } else {
+ clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
+ discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
+ &hdev->dev_flags);
+ }
+
+ if (!test_bit(HCI_MGMT, &hdev->dev_flags))
+ return;
+
+ if (conn_changed || discov_changed) {
+ /* In case this was disabled through mgmt */
+ set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
+
+ if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+ mgmt_update_adv_data(hdev);
+
+ mgmt_new_settings(hdev);
+ }
+}
+
int hci_dev_cmd(unsigned int cmd, void __user *arg)
{
struct hci_dev *hdev;
goto done;
}
- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+ if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
err = -EOPNOTSUPP;
goto done;
}
case HCISETSCAN:
err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt,
HCI_INIT_TIMEOUT);
+
+ /* Ensure that the connectable and discoverable states
+ * get correctly modified as this was a non-mgmt change.
+ */
+ if (!err)
+ hci_update_scan_state(hdev, dr.dev_opt);
break;
case HCISETLINKPOL:
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);
+ unsigned long flags = hdev->flags;
- if (!test_bit(HCI_MGMT, &hdev->dev_flags))
- set_bit(HCI_PAIRABLE, &hdev->dev_flags);
+ /* When the auto-off is configured it means the transport
+ * is running, but in that case still indicate that the
+ * device is actually down.
+ */
+ if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+ flags &= ~BIT(HCI_UP);
(dr + n)->dev_id = hdev->id;
- (dr + n)->dev_opt = hdev->flags;
+ (dr + n)->dev_opt = flags;
if (++n >= dev_num)
break;
{
struct hci_dev *hdev;
struct hci_dev_info di;
+ unsigned long flags;
int err = 0;
if (copy_from_user(&di, arg, sizeof(di)))
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);
+ /* When the auto-off is configured it means the transport
+ * is running, but in that case still indicate that the
+ * device is actually down.
+ */
+ if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+ flags = hdev->flags & ~BIT(HCI_UP);
+ else
+ flags = hdev->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.flags = flags;
di.pkt_type = hdev->pkt_type;
if (lmp_bredr_capable(hdev)) {
di.acl_mtu = hdev->acl_mtu;
if (blocked) {
set_bit(HCI_RFKILLED, &hdev->dev_flags);
- if (!test_bit(HCI_SETUP, &hdev->dev_flags))
+ if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
+ !test_bit(HCI_CONFIG, &hdev->dev_flags))
hci_dev_do_close(hdev);
} else {
clear_bit(HCI_RFKILLED, &hdev->dev_flags);
* valid, it is important to turn the device back off.
*/
if (test_bit(HCI_RFKILLED, &hdev->dev_flags) ||
+ test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) ||
(hdev->dev_type == HCI_BREDR &&
!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
!bacmp(&hdev->static_addr, BDADDR_ANY))) {
}
if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) {
- if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
- mgmt_index_added(hdev);
+ /* For unconfigured devices, set the HCI_RAW flag
+ * so that userspace can easily identify them.
+ */
+ if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
+ set_bit(HCI_RAW, &hdev->flags);
+
+ /* For fully configured devices, this will send
+ * the Index Added event. For unconfigured devices,
+ * it will send Unconfigued Index Added event.
+ *
+ * Devices with HCI_QUIRK_RAW_DEVICE are ignored
+ * and no event will be send.
+ */
+ mgmt_index_added(hdev);
+ } else if (test_and_clear_bit(HCI_CONFIG, &hdev->dev_flags)) {
+ /* When the controller is now configured, then it
+ * is important to clear the HCI_RAW flag.
+ */
+ if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
+ clear_bit(HCI_RAW, &hdev->flags);
+
+ /* Powering on the controller with HCI_CONFIG set only
+ * happens with the transition from unconfigured to
+ * configured. This will send the Index Added event.
+ */
+ mgmt_index_added(hdev);
}
}
return false;
}
-static bool ltk_type_master(u8 type)
+static u8 ltk_role(u8 type)
{
- return (type == SMP_LTK);
+ if (type == SMP_LTK)
+ return HCI_ROLE_MASTER;
+
+ return HCI_ROLE_SLAVE;
}
struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
- bool master)
+ u8 role)
{
struct smp_ltk *k;
if (k->ediv != ediv || k->rand != rand)
continue;
- if (ltk_type_master(k->type) != master)
+ if (ltk_role(k->type) != role)
continue;
return k;
}
struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 addr_type, bool master)
+ u8 addr_type, u8 role)
{
struct smp_ltk *k;
list_for_each_entry(k, &hdev->long_term_keys, list)
if (addr_type == k->bdaddr_type &&
bacmp(bdaddr, &k->bdaddr) == 0 &&
- ltk_type_master(k->type) == master)
+ ltk_role(k->type) == role)
return k;
return NULL;
u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand)
{
struct smp_ltk *key, *old_key;
- bool master = ltk_type_master(type);
+ u8 role = ltk_role(type);
- old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, master);
+ old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, role);
if (old_key)
key = old_key;
else {
return 0;
}
-struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
+struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list,
bdaddr_t *bdaddr, u8 type)
{
struct bdaddr_list *b;
- list_for_each_entry(b, &hdev->blacklist, list) {
+ list_for_each_entry(b, bdaddr_list, list) {
if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
return b;
}
return NULL;
}
-static void hci_blacklist_clear(struct hci_dev *hdev)
+void hci_bdaddr_list_clear(struct list_head *bdaddr_list)
{
struct list_head *p, *n;
- list_for_each_safe(p, n, &hdev->blacklist) {
+ list_for_each_safe(p, n, bdaddr_list) {
struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list);
list_del(p);
}
}
-int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
+int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type)
{
struct bdaddr_list *entry;
if (!bacmp(bdaddr, BDADDR_ANY))
return -EBADF;
- if (hci_blacklist_lookup(hdev, bdaddr, type))
+ if (hci_bdaddr_list_lookup(list, bdaddr, type))
return -EEXIST;
- entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
bacpy(&entry->bdaddr, bdaddr);
entry->bdaddr_type = type;
- list_add(&entry->list, &hdev->blacklist);
+ list_add(&entry->list, list);
return 0;
}
-int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
+int hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type)
{
struct bdaddr_list *entry;
if (!bacmp(bdaddr, BDADDR_ANY)) {
- hci_blacklist_clear(hdev);
+ hci_bdaddr_list_clear(list);
return 0;
}
- entry = hci_blacklist_lookup(hdev, bdaddr, type);
- if (!entry)
- return -ENOENT;
-
- list_del(&entry->list);
- kfree(entry);
-
- return 0;
-}
-
-struct bdaddr_list *hci_white_list_lookup(struct hci_dev *hdev,
- bdaddr_t *bdaddr, u8 type)
-{
- struct bdaddr_list *b;
-
- list_for_each_entry(b, &hdev->le_white_list, list) {
- if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
- return b;
- }
-
- return NULL;
-}
-
-void hci_white_list_clear(struct hci_dev *hdev)
-{
- struct list_head *p, *n;
-
- list_for_each_safe(p, n, &hdev->le_white_list) {
- struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list);
-
- list_del(p);
- kfree(b);
- }
-}
-
-int hci_white_list_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
-{
- struct bdaddr_list *entry;
-
- if (!bacmp(bdaddr, BDADDR_ANY))
- return -EBADF;
-
- entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
- if (!entry)
- return -ENOMEM;
-
- bacpy(&entry->bdaddr, bdaddr);
- entry->bdaddr_type = type;
-
- list_add(&entry->list, &hdev->le_white_list);
-
- return 0;
-}
-
-int hci_white_list_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
-{
- struct bdaddr_list *entry;
-
- if (!bacmp(bdaddr, BDADDR_ANY))
- return -EBADF;
-
- entry = hci_white_list_lookup(hdev, bdaddr, type);
+ entry = hci_bdaddr_list_lookup(list, bdaddr, type);
if (!entry)
return -ENOENT;
{
struct hci_conn_params *params;
+ /* The conn params list only contains identity addresses */
+ if (!hci_is_identity_address(addr, addr_type))
+ return NULL;
+
list_for_each_entry(params, &hdev->le_conn_params, list) {
if (bacmp(¶ms->addr, addr) == 0 &&
params->addr_type == addr_type) {
return true;
}
-static bool is_identity_address(bdaddr_t *addr, u8 addr_type)
-{
- if (addr_type == ADDR_LE_DEV_PUBLIC)
- return true;
-
- /* Check for Random Static address type */
- if ((addr->b[5] & 0xc0) == 0xc0)
- return true;
-
- return false;
-}
-
-/* This function requires the caller holds hdev->lock */
-struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev,
- bdaddr_t *addr, u8 addr_type)
-{
- struct bdaddr_list *entry;
-
- list_for_each_entry(entry, &hdev->pend_le_conns, list) {
- if (bacmp(&entry->bdaddr, addr) == 0 &&
- entry->bdaddr_type == addr_type)
- return entry;
- }
-
- return NULL;
-}
-
/* This function requires the caller holds hdev->lock */
-void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
+ bdaddr_t *addr, u8 addr_type)
{
- struct bdaddr_list *entry;
-
- entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
- if (entry)
- goto done;
+ struct hci_conn_params *param;
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry) {
- BT_ERR("Out of memory");
- return;
- }
-
- bacpy(&entry->bdaddr, addr);
- entry->bdaddr_type = addr_type;
-
- list_add(&entry->list, &hdev->pend_le_conns);
-
- BT_DBG("addr %pMR (type %u)", addr, addr_type);
-
-done:
- hci_update_background_scan(hdev);
-}
-
-/* This function requires the caller holds hdev->lock */
-void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
-{
- struct bdaddr_list *entry;
-
- entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
- if (!entry)
- goto done;
-
- list_del(&entry->list);
- kfree(entry);
-
- BT_DBG("addr %pMR (type %u)", addr, addr_type);
-
-done:
- hci_update_background_scan(hdev);
-}
-
-/* This function requires the caller holds hdev->lock */
-void hci_pend_le_conns_clear(struct hci_dev *hdev)
-{
- struct bdaddr_list *entry, *tmp;
+ /* The list only contains identity addresses */
+ if (!hci_is_identity_address(addr, addr_type))
+ return NULL;
- list_for_each_entry_safe(entry, tmp, &hdev->pend_le_conns, list) {
- list_del(&entry->list);
- kfree(entry);
+ list_for_each_entry(param, list, action) {
+ if (bacmp(¶m->addr, addr) == 0 &&
+ param->addr_type == addr_type)
+ return param;
}
- BT_DBG("All LE pending connections cleared");
-
- hci_update_background_scan(hdev);
+ return NULL;
}
/* This function requires the caller holds hdev->lock */
{
struct hci_conn_params *params;
- if (!is_identity_address(addr, addr_type))
+ if (!hci_is_identity_address(addr, addr_type))
return NULL;
params = hci_conn_params_lookup(hdev, addr, addr_type);
params->addr_type = addr_type;
list_add(¶ms->list, &hdev->le_conn_params);
+ INIT_LIST_HEAD(¶ms->action);
params->conn_min_interval = hdev->le_conn_min_interval;
params->conn_max_interval = hdev->le_conn_max_interval;
if (!params)
return -EIO;
- params->auto_connect = auto_connect;
+ if (params->auto_connect == auto_connect)
+ return 0;
+
+ list_del_init(¶ms->action);
switch (auto_connect) {
case HCI_AUTO_CONN_DISABLED:
case HCI_AUTO_CONN_LINK_LOSS:
- hci_pend_le_conn_del(hdev, addr, addr_type);
+ hci_update_background_scan(hdev);
break;
+ case HCI_AUTO_CONN_REPORT:
+ list_add(¶ms->action, &hdev->pend_le_reports);
+ hci_update_background_scan(hdev);
+ break;
+ case HCI_AUTO_CONN_DIRECT:
case HCI_AUTO_CONN_ALWAYS:
- if (!is_connected(hdev, addr, addr_type))
- hci_pend_le_conn_add(hdev, addr, addr_type);
+ if (!is_connected(hdev, addr, addr_type)) {
+ list_add(¶ms->action, &hdev->pend_le_conns);
+ hci_update_background_scan(hdev);
+ }
break;
}
+ params->auto_connect = auto_connect;
+
BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
auto_connect);
if (!params)
return;
- hci_pend_le_conn_del(hdev, addr, addr_type);
-
+ list_del(¶ms->action);
list_del(¶ms->list);
kfree(params);
+ hci_update_background_scan(hdev);
+
BT_DBG("addr %pMR (type %u)", addr, addr_type);
}
/* This function requires the caller holds hdev->lock */
-void hci_conn_params_clear(struct hci_dev *hdev)
+void hci_conn_params_clear_disabled(struct hci_dev *hdev)
{
struct hci_conn_params *params, *tmp;
list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
+ if (params->auto_connect != HCI_AUTO_CONN_DISABLED)
+ continue;
list_del(¶ms->list);
kfree(params);
}
- hci_pend_le_conns_clear(hdev);
+ BT_DBG("All LE disabled connection parameters were removed");
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_conn_params_clear_all(struct hci_dev *hdev)
+{
+ struct hci_conn_params *params, *tmp;
+
+ list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
+ list_del(¶ms->action);
+ list_del(¶ms->list);
+ kfree(params);
+ }
+
+ hci_update_background_scan(hdev);
BT_DBG("All LE connection parameters were removed");
}
* In this kind of scenario skip the update and let the random
* address be updated at the next cycle.
*/
- if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
+ if (test_bit(HCI_LE_ADV, &hdev->dev_flags) ||
hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
BT_DBG("Deferring random address update");
return;
{
struct hci_dev *hdev;
- hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL);
+ hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
if (!hdev)
return NULL;
hdev->link_mode = (HCI_LM_ACCEPT);
hdev->num_iac = 0x01; /* One IAC support is mandatory */
hdev->io_capability = 0x03; /* No Input No Output */
+ hdev->manufacturer = 0xffff; /* Default to internal use */
hdev->inq_tx_power = HCI_TX_POWER_INVALID;
hdev->adv_tx_power = HCI_TX_POWER_INVALID;
INIT_LIST_HEAD(&hdev->mgmt_pending);
INIT_LIST_HEAD(&hdev->blacklist);
+ INIT_LIST_HEAD(&hdev->whitelist);
INIT_LIST_HEAD(&hdev->uuids);
INIT_LIST_HEAD(&hdev->link_keys);
INIT_LIST_HEAD(&hdev->long_term_keys);
INIT_LIST_HEAD(&hdev->le_white_list);
INIT_LIST_HEAD(&hdev->le_conn_params);
INIT_LIST_HEAD(&hdev->pend_le_conns);
+ INIT_LIST_HEAD(&hdev->pend_le_reports);
INIT_LIST_HEAD(&hdev->conn_hash.list);
INIT_WORK(&hdev->rx_work, hci_rx_work);
{
int id, error;
- if (!hdev->open || !hdev->close)
+ if (!hdev->open || !hdev->close || !hdev->send)
return -EINVAL;
/* Do not allow HCI_AMP devices to register at index 0,
list_add(&hdev->list, &hci_dev_list);
write_unlock(&hci_dev_list_lock);
- /* Devices that are marked for raw-only usage need to set
- * the HCI_RAW flag to indicate that only user channel is
- * supported.
+ /* Devices that are marked for raw-only usage are unconfigured
+ * and should not be included in normal operation.
*/
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
- set_bit(HCI_RAW, &hdev->flags);
+ set_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
hci_notify(hdev, HCI_DEV_REG);
hci_dev_hold(hdev);
if (!test_bit(HCI_INIT, &hdev->flags) &&
!test_bit(HCI_SETUP, &hdev->dev_flags) &&
- !test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+ !test_bit(HCI_CONFIG, &hdev->dev_flags)) {
hci_dev_lock(hdev);
mgmt_index_removed(hdev);
hci_dev_unlock(hdev);
destroy_workqueue(hdev->req_workqueue);
hci_dev_lock(hdev);
- hci_blacklist_clear(hdev);
+ hci_bdaddr_list_clear(&hdev->blacklist);
+ hci_bdaddr_list_clear(&hdev->whitelist);
hci_uuids_clear(hdev);
hci_link_keys_clear(hdev);
hci_smp_ltks_clear(hdev);
hci_smp_irks_clear(hdev);
hci_remote_oob_data_clear(hdev);
- hci_white_list_clear(hdev);
- hci_conn_params_clear(hdev);
+ hci_bdaddr_list_clear(&hdev->le_white_list);
+ hci_conn_params_clear_all(hdev);
hci_dev_unlock(hdev);
hci_dev_put(hdev);
static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
+ int err;
+
BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
/* Time stamp */
/* Get rid of skb owner, prior to sending to the driver. */
skb_orphan(skb);
- if (hdev->send(hdev, skb) < 0)
- BT_ERR("%s sending frame failed", hdev->name);
+ err = hdev->send(hdev, skb);
+ if (err < 0) {
+ BT_ERR("%s sending frame failed (%d)", hdev->name, err);
+ kfree_skb(skb);
+ }
}
void hci_req_init(struct hci_request *req, struct hci_dev *hdev)
return 0;
}
+bool hci_req_pending(struct hci_dev *hdev)
+{
+ return (hdev->req_status == HCI_REQ_PEND);
+}
+
static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode,
u32 plen, const void *param)
{
static void __check_timeout(struct hci_dev *hdev, unsigned int cnt)
{
- if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+ if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
/* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if (!cnt && time_after(jiffies, hdev->acl_last_tx +
if (!hci_conn_num(hdev, LE_LINK))
return;
- if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+ if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
/* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if (!hdev->le_cnt && hdev->le_pkts &&
if (!test_bit(HCI_UP, &hdev->flags) ||
test_bit(HCI_INIT, &hdev->flags) ||
test_bit(HCI_SETUP, &hdev->dev_flags) ||
+ test_bit(HCI_CONFIG, &hdev->dev_flags) ||
test_bit(HCI_AUTO_OFF, &hdev->dev_flags) ||
test_bit(HCI_UNREGISTER, &hdev->dev_flags))
return;
+ /* No point in doing scanning if LE support hasn't been enabled */
+ if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+ return;
+
+ /* If discovery is active don't interfere with it */
+ if (hdev->discovery.state != DISCOVERY_STOPPED)
+ return;
+
hci_req_init(&req, hdev);
- if (list_empty(&hdev->pend_le_conns)) {
- /* If there is no pending LE connections, we should stop
- * the background scanning.
+ if (list_empty(&hdev->pend_le_conns) &&
+ list_empty(&hdev->pend_le_reports)) {
+ /* If there is no pending LE connections or devices
+ * to be scanned for, we should stop the background
+ * scanning.
*/
/* If controller is not scanning we are done. */