#include <linux/crypto.h>
#include <net/sock.h>
-#include <asm/system.h>
#include <linux/uaccess.h>
#include <asm/unaligned.h>
/* If this is the init phase check if the completed command matches
* the last init command, and if not just return.
*/
- if (test_bit(HCI_INIT, &hdev->flags) && hdev->init_last_cmd != cmd)
+ if (test_bit(HCI_INIT, &hdev->flags) && hdev->init_last_cmd != cmd) {
+ struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data;
+ struct sk_buff *skb;
+
+ /* Some CSR based controllers generate a spontaneous
+ * reset complete event during init and any pending
+ * command will never be completed. In such a case we
+ * need to resend whatever was the last sent
+ * command.
+ */
+
+ if (cmd != HCI_OP_RESET || sent->opcode == HCI_OP_RESET)
+ return;
+
+ skb = skb_clone(hdev->sent_cmd, GFP_ATOMIC);
+ if (skb) {
+ skb_queue_head(&hdev->cmd_q, skb);
+ queue_work(hdev->workqueue, &hdev->cmd_work);
+ }
+
return;
+ }
if (hdev->req_status == HCI_REQ_PEND) {
hdev->req_result = result;
INIT_LIST_HEAD(&cache->unknown);
INIT_LIST_HEAD(&cache->resolve);
- cache->state = DISCOVERY_STOPPED;
}
struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
}
struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
- bdaddr_t *bdaddr)
+ bdaddr_t *bdaddr)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
}
struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
- bdaddr_t *bdaddr,
- int state)
+ bdaddr_t *bdaddr,
+ int state)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
}
void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
- struct inquiry_entry *ie)
+ struct inquiry_entry *ie)
{
struct discovery_state *cache = &hdev->discovery;
struct list_head *pos = &cache->resolve;
}
bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
- bool name_known)
+ bool name_known, bool *ssp)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *ie;
BT_DBG("cache %p, %s", cache, batostr(&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_req_lock(hdev);
+ if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
+ ret = -ENODEV;
+ goto done;
+ }
+
if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
ret = -ERFKILL;
goto done;
hdev->flags = 0;
memset(hdev->eir, 0, sizeof(hdev->eir));
+ memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
hci_req_unlock(hdev);
return NULL;
}
-static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
+static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
u8 key_type, u8 old_key_type)
{
/* Legacy key */
if (key_type < 0x03)
- return 1;
+ return true;
/* Debug keys are insecure so don't store them persistently */
if (key_type == HCI_LK_DEBUG_COMBINATION)
- return 0;
+ return false;
/* Changed combination key and there's no previous one */
if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
- return 0;
+ return false;
/* Security mode 3 case */
if (!conn)
- return 1;
+ return true;
/* Neither local nor remote side had no-bonding as requirement */
if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
- return 1;
+ return true;
/* Local side had dedicated bonding as requirement */
if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
- return 1;
+ return true;
/* Remote side had dedicated bonding as requirement */
if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
- return 1;
+ return true;
/* If none of the above criteria match, then don't store the key
* persistently */
- return 0;
+ return false;
}
struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
EXPORT_SYMBOL(hci_find_ltk);
struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 addr_type)
+ u8 addr_type)
{
struct smp_ltk *k;
EXPORT_SYMBOL(hci_find_ltk_by_addr);
int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
- bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
+ bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
{
struct link_key *key, *old_key;
- u8 old_key_type, persistent;
+ u8 old_key_type;
+ bool persistent;
old_key = hci_find_link_key(hdev, bdaddr);
if (old_key) {
mgmt_new_link_key(hdev, key, persistent);
- if (!persistent) {
- list_del(&key->list);
- kfree(key);
- }
+ if (conn)
+ conn->flush_key = !persistent;
return 0;
}
int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
- int new_key, u8 authenticated, u8 tk[16],
- u8 enc_size, u16 ediv, u8 rand[8])
+ int new_key, u8 authenticated, u8 tk[16], u8 enc_size, u16
+ ediv, u8 rand[8])
{
struct smp_ltk *key, *old_key;
}
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
- bdaddr_t *bdaddr)
+ bdaddr_t *bdaddr)
{
struct oob_data *data;
}
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
- u8 *randomizer)
+ u8 *randomizer)
{
struct oob_data *data;
return 0;
}
-struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
- bdaddr_t *bdaddr)
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct bdaddr_list *b;
static void hci_clear_adv_cache(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev,
- adv_work.work);
+ adv_work.work);
hci_dev_lock(hdev);
}
int hci_add_adv_entry(struct hci_dev *hdev,
- struct hci_ev_le_advertising_info *ev)
-{
- struct adv_entry *entry;
-
- if (!is_connectable_adv(ev->evt_type))
+ struct hci_ev_le_advertising_info *ev) { struct adv_entry *entry; if (!is_connectable_adv(ev->evt_type))
return -EINVAL;
/* Only new entries should be added to adv_entries. So, if
}
static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
- u16 window, int timeout)
+ u16 window, int timeout)
{
long timeo = msecs_to_jiffies(3000);
struct le_scan_params param;
hci_req_lock(hdev);
err = __hci_request(hdev, le_scan_param_req, (unsigned long) ¶m,
- timeo);
+ timeo);
if (!err)
err = __hci_request(hdev, le_scan_enable_req, 0, timeo);
return err;
schedule_delayed_work(&hdev->le_scan_disable,
- msecs_to_jiffies(timeout));
+ msecs_to_jiffies(timeout));
return 0;
}
static void le_scan_disable_work(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev,
- le_scan_disable.work);
+ le_scan_disable.work);
struct hci_cp_le_set_scan_enable cp;
BT_DBG("%s", hdev->name);
BT_DBG("%s", hdev->name);
- hci_do_le_scan(hdev, param->type, param->interval,
- param->window, param->timeout);
+ hci_do_le_scan(hdev, param->type, param->interval, param->window,
+ param->timeout);
}
int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
- int timeout)
+ int timeout)
{
struct le_scan_params *param = &hdev->le_scan_params;
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
+ set_bit(HCI_UNREGISTER, &hdev->dev_flags);
+
write_lock(&hci_dev_list_lock);
list_del(&hdev->list);
write_unlock(&hci_dev_list_lock);
while (count) {
scb = (void *) skb->cb;
- len = min_t(__u16, scb->expect, count);
+ len = min_t(uint, scb->expect, count);
memcpy(skb_put(skb, len), data, len);
skb = skb_dequeue(&chan->data_q);
hci_conn_enter_active_mode(chan->conn,
- bt_cb(skb)->force_active);
+ bt_cb(skb)->force_active);
hci_send_frame(skb);
hdev->acl_last_tx = jiffies;
if (conn) {
hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
+ hci_dev_lock(hdev);
+ if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
+ !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+ mgmt_device_connected(hdev, &conn->dst, conn->type,
+ conn->dst_type, 0, NULL, 0,
+ conn->dev_class);
+ hci_dev_unlock(hdev);
+
/* Send to upper protocol */
l2cap_recv_acldata(conn, skb, flags);
return;