struct hci_dev *hdev = file->private_data;
char buf[3];
- buf[0] = test_bit(HCI_DUT_MODE, &hdev->dbg_flags) ? 'Y': 'N';
+ buf[0] = hci_dev_test_flag(hdev, HCI_DUT_MODE) ? 'Y': 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
if (strtobool(buf, &enable))
return -EINVAL;
- if (enable == test_bit(HCI_DUT_MODE, &hdev->dbg_flags))
+ if (enable == hci_dev_test_flag(hdev, HCI_DUT_MODE))
return -EALREADY;
hci_req_lock(hdev);
if (err < 0)
return err;
- change_bit(HCI_DUT_MODE, &hdev->dbg_flags);
+ hci_dev_change_flag(hdev, HCI_DUT_MODE);
return count;
}
/* ---- HCI requests ---- */
-static void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode)
+static void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
+ struct sk_buff *skb)
{
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;
+ if (skb)
+ hdev->req_skb = skb_get(skb);
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;
+ struct sk_buff *skb;
int err = 0;
BT_DBG("%s", hdev->name);
add_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
- err = hci_req_run(&req, hci_req_sync_complete);
+ err = hci_req_run_skb(&req, hci_req_sync_complete);
if (err < 0) {
remove_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_RUNNING);
}
hdev->req_status = hdev->req_result = 0;
+ skb = hdev->req_skb;
+ hdev->req_skb = NULL;
BT_DBG("%s end: err %d", hdev->name, err);
- if (err < 0)
+ if (err < 0) {
+ kfree_skb(skb);
return ERR_PTR(err);
+ }
+
+ if (!skb)
+ return ERR_PTR(-ENODATA);
- return hci_get_cmd_complete(hdev, opcode, event);
+ return skb;
}
EXPORT_SYMBOL(__hci_cmd_sync_ev);
add_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
- err = hci_req_run(&req, hci_req_sync_complete);
+ err = hci_req_run_skb(&req, hci_req_sync_complete);
if (err < 0) {
hdev->req_status = 0;
/* LE-only controllers have LE implicitly enabled */
if (!lmp_bredr_capable(hdev))
- set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
+ hci_dev_set_flag(hdev, HCI_LE_ENABLED);
}
static void hci_setup_event_mask(struct hci_request *req)
if (lmp_bredr_capable(hdev))
bredr_setup(req);
else
- clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
+ hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
if (lmp_le_capable(hdev))
le_setup(req);
*/
hdev->max_page = 0x01;
- if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
u8 mode = 0x01;
hci_req_add(req, HCI_OP_WRITE_SSP_MODE,
sizeof(cp), &cp);
}
- if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
u8 enable = 1;
hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
&enable);
memset(&cp, 0, sizeof(cp));
- if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
cp.le = 0x01;
cp.simul = 0x00;
}
hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
/* Enable Secure Connections if supported and configured */
- if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
+ if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
bredr_sc_enabled(hdev)) {
u8 support = 0x01;
/* 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)) {
+ if (hci_dev_test_flag(hdev, HCI_SETUP)) {
debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev,
&dut_mode_fops);
}
* 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) &&
- !test_bit(HCI_CONFIG, &hdev->dev_flags))
+ if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
+ !hci_dev_test_flag(hdev, HCI_CONFIG))
return 0;
hci_debugfs_create_common(hdev);
if (!hdev)
return -ENODEV;
- if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EBUSY;
goto done;
}
- if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
err = -EOPNOTSUPP;
goto done;
}
goto done;
}
- if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
+ if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
err = -EOPNOTSUPP;
goto done;
}
hci_req_lock(hdev);
- if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
ret = -ENODEV;
goto done;
}
- if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
- !test_bit(HCI_CONFIG, &hdev->dev_flags)) {
+ if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
+ !hci_dev_test_flag(hdev, HCI_CONFIG)) {
/* 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)) {
+ if (hci_dev_test_flag(hdev, HCI_RFKILLED)) {
ret = -ERFKILL;
goto done;
}
* 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) &&
+ if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
hdev->dev_type == HCI_BREDR &&
!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
!bacmp(&hdev->static_addr, BDADDR_ANY)) {
atomic_set(&hdev->cmd_cnt, 1);
set_bit(HCI_INIT, &hdev->flags);
- if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_SETUP)) {
if (hdev->setup)
ret = hdev->setup(hdev);
*/
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks))
- set_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
+ hci_dev_set_flag(hdev, HCI_UNCONFIGURED);
/* For an unconfigured controller it is required to
* read at least the version information provided by
* also the original Bluetooth public device address
* will be read using the Read BD Address command.
*/
- if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
+ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
ret = __hci_unconf_init(hdev);
}
- if (test_bit(HCI_CONFIG, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_CONFIG)) {
/* 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
}
if (!ret) {
- if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
- !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
+ if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
+ !hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
ret = __hci_init(hdev);
}
if (!ret) {
hci_dev_hold(hdev);
- set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
+ hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
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) &&
+ if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
+ !hci_dev_test_flag(hdev, HCI_CONFIG) &&
+ !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
+ !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
hdev->dev_type == HCI_BREDR) {
hci_dev_lock(hdev);
mgmt_powered(hdev, 1);
* HCI_USER_CHANNEL will be set first before attempting to
* open the device.
*/
- if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
- !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
+ !hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EOPNOTSUPP;
goto done;
}
* particularly important if the setup procedure has not yet
* completed.
*/
- if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+ if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
cancel_delayed_work(&hdev->power_off);
/* After this call it is guaranteed that the setup procedure
* 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_BONDABLE, &hdev->dev_flags);
+ if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
+ !hci_dev_test_flag(hdev, HCI_MGMT))
+ hci_dev_set_flag(hdev, HCI_BONDABLE);
err = hci_dev_do_open(hdev);
{
BT_DBG("%s %p", hdev->name, hdev);
- if (!test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
+ if (!hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
/* Execute vendor specific shutdown routine */
if (hdev->shutdown)
hdev->shutdown(hdev);
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);
+ hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
+ hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
}
- if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
+ if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
cancel_delayed_work(&hdev->service_cache);
cancel_delayed_work_sync(&hdev->le_scan_disable);
cancel_delayed_work_sync(&hdev->le_scan_restart);
- if (test_bit(HCI_MGMT, &hdev->dev_flags))
+ if (hci_dev_test_flag(hdev, HCI_MGMT))
cancel_delayed_work_sync(&hdev->rpa_expired);
/* Avoid potential lockdep warnings from the *_flush() calls by
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
- if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
+ if (!hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
if (hdev->dev_type == HCI_BREDR)
mgmt_powered(hdev, 0);
}
/* Reset device */
skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1);
- if (!test_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
- !test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
+ if (!hci_dev_test_flag(hdev, HCI_AUTO_OFF) &&
+ !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
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);
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 &= BIT(HCI_RAW);
- hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
+ hci_dev_clear_volatile_flags(hdev);
/* Controller radio is available but is currently powered down */
hdev->amp_status = AMP_STATUS_POWERED_DOWN;
if (!hdev)
return -ENODEV;
- if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EBUSY;
goto done;
}
- if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+ if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
cancel_delayed_work(&hdev->power_off);
err = hci_dev_do_close(hdev);
goto done;
}
- if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EBUSY;
goto done;
}
- if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
err = -EOPNOTSUPP;
goto done;
}
if (!hdev)
return -ENODEV;
- if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
ret = -EBUSY;
goto done;
}
- if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
ret = -EOPNOTSUPP;
goto done;
}
BT_DBG("%s scan 0x%02x", hdev->name, scan);
if ((scan & SCAN_PAGE))
- conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
- &hdev->dev_flags);
+ conn_changed = !hci_dev_test_and_set_flag(hdev,
+ HCI_CONNECTABLE);
else
- conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
- &hdev->dev_flags);
+ conn_changed = hci_dev_test_and_clear_flag(hdev,
+ HCI_CONNECTABLE);
if ((scan & SCAN_INQUIRY)) {
- discov_changed = !test_and_set_bit(HCI_DISCOVERABLE,
- &hdev->dev_flags);
+ discov_changed = !hci_dev_test_and_set_flag(hdev,
+ HCI_DISCOVERABLE);
} else {
- clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
- discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
- &hdev->dev_flags);
+ hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
+ discov_changed = hci_dev_test_and_clear_flag(hdev,
+ HCI_DISCOVERABLE);
}
- if (!test_bit(HCI_MGMT, &hdev->dev_flags))
+ if (!hci_dev_test_flag(hdev, HCI_MGMT))
return;
if (conn_changed || discov_changed) {
/* In case this was disabled through mgmt */
- set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
+ hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
- if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+ if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
mgmt_update_adv_data(hdev);
mgmt_new_settings(hdev);
if (!hdev)
return -ENODEV;
- if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
err = -EBUSY;
goto done;
}
- if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
err = -EOPNOTSUPP;
goto done;
}
goto done;
}
- if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
+ if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
err = -EOPNOTSUPP;
goto done;
}
* is running, but in that case still indicate that the
* device is actually down.
*/
- if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+ if (hci_dev_test_flag(hdev, HCI_AUTO_OFF))
flags &= ~BIT(HCI_UP);
(dr + n)->dev_id = hdev->id;
* is running, but in that case still indicate that the
* device is actually down.
*/
- if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+ if (hci_dev_test_flag(hdev, HCI_AUTO_OFF))
flags = hdev->flags & ~BIT(HCI_UP);
else
flags = hdev->flags;
BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
- if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
+ if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
return -EBUSY;
if (blocked) {
- set_bit(HCI_RFKILLED, &hdev->dev_flags);
- if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
- !test_bit(HCI_CONFIG, &hdev->dev_flags))
+ hci_dev_set_flag(hdev, HCI_RFKILLED);
+ if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
+ !hci_dev_test_flag(hdev, HCI_CONFIG))
hci_dev_do_close(hdev);
} else {
- clear_bit(HCI_RFKILLED, &hdev->dev_flags);
+ hci_dev_clear_flag(hdev, HCI_RFKILLED);
}
return 0;
* ignored and they need to be checked now. If they are still
* 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) ||
+ if (hci_dev_test_flag(hdev, HCI_RFKILLED) ||
+ hci_dev_test_flag(hdev, HCI_UNCONFIGURED) ||
(hdev->dev_type == HCI_BREDR &&
!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
!bacmp(&hdev->static_addr, BDADDR_ANY))) {
- clear_bit(HCI_AUTO_OFF, &hdev->dev_flags);
+ hci_dev_clear_flag(hdev, HCI_AUTO_OFF);
hci_dev_do_close(hdev);
- } else if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
+ } else if (hci_dev_test_flag(hdev, HCI_AUTO_OFF)) {
queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
HCI_AUTO_OFF_TIMEOUT);
}
- if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) {
+ if (hci_dev_test_and_clear_flag(hdev, HCI_SETUP)) {
/* For unconfigured devices, set the HCI_RAW flag
* so that userspace can easily identify them.
*/
- if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
+ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
set_bit(HCI_RAW, &hdev->flags);
/* For fully configured devices, this will send
* and no event will be send.
*/
mgmt_index_added(hdev);
- } else if (test_and_clear_bit(HCI_CONFIG, &hdev->dev_flags)) {
+ } else if (hci_dev_test_and_clear_flag(hdev, HCI_CONFIG)) {
/* When the controller is now configured, then it
* is important to clear the HCI_RAW flag.
*/
- if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
+ if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
clear_bit(HCI_RAW, &hdev->flags);
/* Powering on the controller with HCI_CONFIG set only
}
}
+bool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
+{
+ struct smp_ltk *k;
+ struct smp_irk *irk;
+ u8 addr_type;
+
+ if (type == BDADDR_BREDR) {
+ if (hci_find_link_key(hdev, bdaddr))
+ return true;
+ return false;
+ }
+
+ /* Convert to HCI addr type which struct smp_ltk uses */
+ if (type == BDADDR_LE_PUBLIC)
+ addr_type = ADDR_LE_DEV_PUBLIC;
+ else
+ addr_type = ADDR_LE_DEV_RANDOM;
+
+ irk = hci_get_irk(hdev, bdaddr, addr_type);
+ if (irk) {
+ bdaddr = &irk->bdaddr;
+ addr_type = irk->addr_type;
+ }
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
+ if (k->bdaddr_type == addr_type && !bacmp(bdaddr, &k->bdaddr)) {
+ rcu_read_unlock();
+ return true;
+ }
+ }
+ rcu_read_unlock();
+
+ return false;
+}
+
/* HCI command timer function */
static void hci_cmd_timeout(struct work_struct *work)
{
{
/* General inquiry access code (GIAC) */
u8 lap[3] = { 0x33, 0x8b, 0x9e };
- struct hci_request req;
struct hci_cp_inquiry cp;
int err;
break;
case DISCOV_TYPE_INTERLEAVED:
- hci_req_init(&req, hdev);
+ hci_dev_lock(hdev);
- memset(&cp, 0, sizeof(cp));
- memcpy(&cp.lap, lap, sizeof(cp.lap));
- cp.length = DISCOV_INTERLEAVED_INQUIRY_LEN;
- hci_req_add(&req, HCI_OP_INQUIRY, sizeof(cp), &cp);
+ if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
+ &hdev->quirks)) {
+ /* If we were running LE only scan, change discovery
+ * state. If we were running both LE and BR/EDR inquiry
+ * simultaneously, and BR/EDR inquiry is already
+ * finished, stop discovery, otherwise BR/EDR inquiry
+ * will stop discovery when finished.
+ */
+ if (!test_bit(HCI_INQUIRY, &hdev->flags))
+ hci_discovery_set_state(hdev,
+ DISCOVERY_STOPPED);
+ } else {
+ struct hci_request req;
- hci_dev_lock(hdev);
+ hci_inquiry_cache_flush(hdev);
- hci_inquiry_cache_flush(hdev);
+ hci_req_init(&req, hdev);
- err = hci_req_run(&req, inquiry_complete);
- if (err) {
- BT_ERR("Inquiry request failed: err %d", err);
- hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+ memset(&cp, 0, sizeof(cp));
+ memcpy(&cp.lap, lap, sizeof(cp.lap));
+ cp.length = DISCOV_INTERLEAVED_INQUIRY_LEN;
+ hci_req_add(&req, HCI_OP_INQUIRY, sizeof(cp), &cp);
+
+ err = hci_req_run(&req, inquiry_complete);
+ if (err) {
+ BT_ERR("Inquiry request failed: err %d", err);
+ hci_discovery_set_state(hdev,
+ DISCOVERY_STOPPED);
+ }
}
hci_dev_unlock(hdev);
BT_DBG("%s", hdev->name);
/* If controller is not scanning we are done. */
- if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
return;
hci_req_init(&req, hdev);
void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 *bdaddr_type)
{
- if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ||
+ if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
!bacmp(&hdev->bdaddr, BDADDR_ANY) ||
- (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
+ (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
bacmp(&hdev->static_addr, BDADDR_ANY))) {
bacpy(bdaddr, &hdev->static_addr);
*bdaddr_type = ADDR_LE_DEV_RANDOM;
hci_init_sysfs(hdev);
discovery_init(hdev);
+ adv_info_init(hdev);
return hdev;
}
}
if (hdev->rfkill && rfkill_blocked(hdev->rfkill))
- set_bit(HCI_RFKILLED, &hdev->dev_flags);
+ hci_dev_set_flag(hdev, HCI_RFKILLED);
- set_bit(HCI_SETUP, &hdev->dev_flags);
- set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
+ hci_dev_set_flag(hdev, HCI_SETUP);
+ hci_dev_set_flag(hdev, HCI_AUTO_OFF);
if (hdev->dev_type == HCI_BREDR) {
/* Assume BR/EDR support until proven otherwise (such as
* through reading supported features during init.
*/
- set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
+ hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
}
write_lock(&hci_dev_list_lock);
* and should not be included in normal operation.
*/
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
- set_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
+ hci_dev_set_flag(hdev, HCI_UNCONFIGURED);
hci_notify(hdev, HCI_DEV_REG);
hci_dev_hold(hdev);
/* Unregister HCI device */
void hci_unregister_dev(struct hci_dev *hdev)
{
- int i, id;
+ int id;
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
- set_bit(HCI_UNREGISTER, &hdev->dev_flags);
+ hci_dev_set_flag(hdev, HCI_UNREGISTER);
id = hdev->id;
hci_dev_do_close(hdev);
- for (i = 0; i < NUM_REASSEMBLY; i++)
- kfree_skb(hdev->reassembly[i]);
-
cancel_work_sync(&hdev->power_on);
if (!test_bit(HCI_INIT, &hdev->flags) &&
- !test_bit(HCI_SETUP, &hdev->dev_flags) &&
- !test_bit(HCI_CONFIG, &hdev->dev_flags)) {
+ !hci_dev_test_flag(hdev, HCI_SETUP) &&
+ !hci_dev_test_flag(hdev, HCI_CONFIG)) {
hci_dev_lock(hdev);
mgmt_index_removed(hdev);
hci_dev_unlock(hdev);
}
EXPORT_SYMBOL(hci_recv_frame);
-static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
- int count, __u8 index)
-{
- int len = 0;
- int hlen = 0;
- int remain = count;
- struct sk_buff *skb;
- struct bt_skb_cb *scb;
-
- if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ||
- index >= NUM_REASSEMBLY)
- return -EILSEQ;
-
- skb = hdev->reassembly[index];
-
- if (!skb) {
- switch (type) {
- case HCI_ACLDATA_PKT:
- len = HCI_MAX_FRAME_SIZE;
- hlen = HCI_ACL_HDR_SIZE;
- break;
- case HCI_EVENT_PKT:
- len = HCI_MAX_EVENT_SIZE;
- hlen = HCI_EVENT_HDR_SIZE;
- break;
- case HCI_SCODATA_PKT:
- len = HCI_MAX_SCO_SIZE;
- hlen = HCI_SCO_HDR_SIZE;
- break;
- }
-
- skb = bt_skb_alloc(len, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- scb = (void *) skb->cb;
- scb->expect = hlen;
- scb->pkt_type = type;
-
- hdev->reassembly[index] = skb;
- }
-
- while (count) {
- scb = (void *) skb->cb;
- len = min_t(uint, scb->expect, count);
-
- memcpy(skb_put(skb, len), data, len);
-
- count -= len;
- data += len;
- scb->expect -= len;
- remain = count;
-
- switch (type) {
- case HCI_EVENT_PKT:
- if (skb->len == HCI_EVENT_HDR_SIZE) {
- struct hci_event_hdr *h = hci_event_hdr(skb);
- scb->expect = h->plen;
-
- if (skb_tailroom(skb) < scb->expect) {
- kfree_skb(skb);
- hdev->reassembly[index] = NULL;
- return -ENOMEM;
- }
- }
- break;
-
- case HCI_ACLDATA_PKT:
- if (skb->len == HCI_ACL_HDR_SIZE) {
- struct hci_acl_hdr *h = hci_acl_hdr(skb);
- scb->expect = __le16_to_cpu(h->dlen);
-
- if (skb_tailroom(skb) < scb->expect) {
- kfree_skb(skb);
- hdev->reassembly[index] = NULL;
- return -ENOMEM;
- }
- }
- break;
-
- case HCI_SCODATA_PKT:
- if (skb->len == HCI_SCO_HDR_SIZE) {
- struct hci_sco_hdr *h = hci_sco_hdr(skb);
- scb->expect = h->dlen;
-
- if (skb_tailroom(skb) < scb->expect) {
- kfree_skb(skb);
- hdev->reassembly[index] = NULL;
- return -ENOMEM;
- }
- }
- break;
- }
-
- if (scb->expect == 0) {
- /* Complete frame */
-
- bt_cb(skb)->pkt_type = type;
- hci_recv_frame(hdev, skb);
-
- hdev->reassembly[index] = NULL;
- return remain;
- }
- }
-
- return remain;
-}
-
-#define STREAM_REASSEMBLY 0
-
-int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
-{
- int type;
- int rem = 0;
-
- while (count) {
- struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY];
-
- if (!skb) {
- struct { char type; } *pkt;
-
- /* Start of the frame */
- pkt = data;
- type = pkt->type;
-
- data++;
- count--;
- } else
- type = bt_cb(skb)->pkt_type;
-
- rem = hci_reassembly(hdev, type, data, count,
- STREAM_REASSEMBLY);
- if (rem < 0)
- return rem;
-
- data += (count - rem);
- count = rem;
- }
-
- return rem;
-}
-EXPORT_SYMBOL(hci_recv_stream_fragment);
-
/* ---- Interface to upper protocols ---- */
int hci_register_cb(struct hci_cb *cb)
}
}
-bool hci_req_pending(struct hci_dev *hdev)
-{
- return (hdev->req_status == HCI_REQ_PEND);
-}
-
/* Send HCI command */
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen,
const void *param)
/* Stand-alone HCI commands must be flagged as
* single-command requests.
*/
- bt_cb(skb)->req_start = 1;
+ bt_cb(skb)->req.start = true;
skb_queue_tail(&hdev->cmd_q, skb);
queue_work(hdev->workqueue, &hdev->cmd_work);
static void __check_timeout(struct hci_dev *hdev, unsigned int cnt)
{
- if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
+ if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
/* 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_UNCONFIGURED, &hdev->dev_flags)) {
+ if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
/* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if (!hdev->le_cnt && hdev->le_pkts &&
BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
hdev->sco_cnt, hdev->le_cnt);
- if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
/* Schedule queues and send stuff to HCI driver */
hci_sched_acl(hdev);
hci_sched_sco(hdev);
if (!skb)
return true;
- return bt_cb(skb)->req_start;
+ return bt_cb(skb)->req.start;
}
static void hci_resend_last(struct hci_dev *hdev)
queue_work(hdev->workqueue, &hdev->cmd_work);
}
-void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status)
+void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
+ hci_req_complete_t *req_complete,
+ hci_req_complete_skb_t *req_complete_skb)
{
- hci_req_complete_t req_complete = NULL;
struct sk_buff *skb;
unsigned long flags;
* callback would be found in hdev->sent_cmd instead of the
* command queue (hdev->cmd_q).
*/
- if (hdev->sent_cmd) {
- req_complete = bt_cb(hdev->sent_cmd)->req_complete;
-
- if (req_complete) {
- /* We must set the complete callback to NULL to
- * avoid calling the callback more than once if
- * this function gets called again.
- */
- bt_cb(hdev->sent_cmd)->req_complete = NULL;
+ if (bt_cb(hdev->sent_cmd)->req.complete) {
+ *req_complete = bt_cb(hdev->sent_cmd)->req.complete;
+ return;
+ }
- goto call_complete;
- }
+ if (bt_cb(hdev->sent_cmd)->req.complete_skb) {
+ *req_complete_skb = bt_cb(hdev->sent_cmd)->req.complete_skb;
+ return;
}
/* Remove all pending commands belonging to this request */
spin_lock_irqsave(&hdev->cmd_q.lock, flags);
while ((skb = __skb_dequeue(&hdev->cmd_q))) {
- if (bt_cb(skb)->req_start) {
+ if (bt_cb(skb)->req.start) {
__skb_queue_head(&hdev->cmd_q, skb);
break;
}
- req_complete = bt_cb(skb)->req_complete;
+ *req_complete = bt_cb(skb)->req.complete;
+ *req_complete_skb = bt_cb(skb)->req.complete_skb;
kfree_skb(skb);
}
spin_unlock_irqrestore(&hdev->cmd_q.lock, flags);
-
-call_complete:
- if (req_complete)
- req_complete(hdev, status, status ? opcode : HCI_OP_NOP);
}
static void hci_rx_work(struct work_struct *work)
hci_send_to_sock(hdev, skb);
}
- if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
kfree_skb(skb);
continue;
}