|
@@ -35,10 +35,9 @@
|
|
|
#include <net/bluetooth/smp.h>
|
|
|
|
|
|
bool enable_hs;
|
|
|
-bool enable_le;
|
|
|
|
|
|
#define MGMT_VERSION 1
|
|
|
-#define MGMT_REVISION 0
|
|
|
+#define MGMT_REVISION 1
|
|
|
|
|
|
static const u16 mgmt_commands[] = {
|
|
|
MGMT_OP_READ_INDEX_LIST,
|
|
@@ -78,6 +77,7 @@ static const u16 mgmt_commands[] = {
|
|
|
MGMT_OP_CONFIRM_NAME,
|
|
|
MGMT_OP_BLOCK_DEVICE,
|
|
|
MGMT_OP_UNBLOCK_DEVICE,
|
|
|
+ MGMT_OP_SET_DEVICE_ID,
|
|
|
};
|
|
|
|
|
|
static const u16 mgmt_events[] = {
|
|
@@ -224,7 +224,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
|
|
|
|
|
|
ev = (void *) skb_put(skb, sizeof(*ev));
|
|
|
ev->status = status;
|
|
|
- put_unaligned_le16(cmd, &ev->opcode);
|
|
|
+ ev->opcode = cpu_to_le16(cmd);
|
|
|
|
|
|
err = sock_queue_rcv_skb(sk, skb);
|
|
|
if (err < 0)
|
|
@@ -254,7 +254,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
|
|
|
hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
|
|
|
|
|
|
ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
|
|
|
- put_unaligned_le16(cmd, &ev->opcode);
|
|
|
+ ev->opcode = cpu_to_le16(cmd);
|
|
|
ev->status = status;
|
|
|
|
|
|
if (rp)
|
|
@@ -275,7 +275,7 @@ static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
BT_DBG("sock %p", sk);
|
|
|
|
|
|
rp.version = MGMT_VERSION;
|
|
|
- put_unaligned_le16(MGMT_REVISION, &rp.revision);
|
|
|
+ rp.revision = __constant_cpu_to_le16(MGMT_REVISION);
|
|
|
|
|
|
return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
|
|
|
sizeof(rp));
|
|
@@ -285,9 +285,9 @@ static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
u16 data_len)
|
|
|
{
|
|
|
struct mgmt_rp_read_commands *rp;
|
|
|
- u16 num_commands = ARRAY_SIZE(mgmt_commands);
|
|
|
- u16 num_events = ARRAY_SIZE(mgmt_events);
|
|
|
- u16 *opcode;
|
|
|
+ const u16 num_commands = ARRAY_SIZE(mgmt_commands);
|
|
|
+ const u16 num_events = ARRAY_SIZE(mgmt_events);
|
|
|
+ __le16 *opcode;
|
|
|
size_t rp_size;
|
|
|
int i, err;
|
|
|
|
|
@@ -299,8 +299,8 @@ static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
if (!rp)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- put_unaligned_le16(num_commands, &rp->num_commands);
|
|
|
- put_unaligned_le16(num_events, &rp->num_events);
|
|
|
+ rp->num_commands = __constant_cpu_to_le16(num_commands);
|
|
|
+ rp->num_events = __constant_cpu_to_le16(num_events);
|
|
|
|
|
|
for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
|
|
|
put_unaligned_le16(mgmt_commands[i], opcode);
|
|
@@ -341,14 +341,14 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- put_unaligned_le16(count, &rp->num_controllers);
|
|
|
+ rp->num_controllers = cpu_to_le16(count);
|
|
|
|
|
|
i = 0;
|
|
|
list_for_each_entry(d, &hci_dev_list, list) {
|
|
|
if (test_bit(HCI_SETUP, &d->dev_flags))
|
|
|
continue;
|
|
|
|
|
|
- put_unaligned_le16(d->id, &rp->index[i++]);
|
|
|
+ rp->index[i++] = cpu_to_le16(d->id);
|
|
|
BT_DBG("Added hci%u", d->id);
|
|
|
}
|
|
|
|
|
@@ -383,10 +383,8 @@ static u32 get_supported_settings(struct hci_dev *hdev)
|
|
|
if (enable_hs)
|
|
|
settings |= MGMT_SETTING_HS;
|
|
|
|
|
|
- if (enable_le) {
|
|
|
- if (hdev->features[4] & LMP_LE)
|
|
|
- settings |= MGMT_SETTING_LE;
|
|
|
- }
|
|
|
+ if (hdev->features[4] & LMP_LE)
|
|
|
+ settings |= MGMT_SETTING_LE;
|
|
|
|
|
|
return settings;
|
|
|
}
|
|
@@ -442,9 +440,7 @@ static u16 get_uuid16(u8 *uuid128)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- memcpy(&val, &uuid128[12], 4);
|
|
|
-
|
|
|
- val = le32_to_cpu(val);
|
|
|
+ val = get_unaligned_le32(&uuid128[12]);
|
|
|
if (val > 0xffff)
|
|
|
return 0;
|
|
|
|
|
@@ -479,6 +475,28 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
|
|
|
ptr += (name_len + 2);
|
|
|
}
|
|
|
|
|
|
+ if (hdev->inq_tx_power) {
|
|
|
+ ptr[0] = 2;
|
|
|
+ ptr[1] = EIR_TX_POWER;
|
|
|
+ ptr[2] = (u8) hdev->inq_tx_power;
|
|
|
+
|
|
|
+ eir_len += 3;
|
|
|
+ ptr += 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hdev->devid_source > 0) {
|
|
|
+ ptr[0] = 9;
|
|
|
+ ptr[1] = EIR_DEVICE_ID;
|
|
|
+
|
|
|
+ put_unaligned_le16(hdev->devid_source, ptr + 2);
|
|
|
+ put_unaligned_le16(hdev->devid_vendor, ptr + 4);
|
|
|
+ put_unaligned_le16(hdev->devid_product, ptr + 6);
|
|
|
+ put_unaligned_le16(hdev->devid_version, ptr + 8);
|
|
|
+
|
|
|
+ eir_len += 10;
|
|
|
+ ptr += 10;
|
|
|
+ }
|
|
|
+
|
|
|
memset(uuid16_list, 0, sizeof(uuid16_list));
|
|
|
|
|
|
/* Group all UUID16 types */
|
|
@@ -642,8 +660,7 @@ static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
|
|
|
bacpy(&rp.bdaddr, &hdev->bdaddr);
|
|
|
|
|
|
rp.version = hdev->hci_ver;
|
|
|
-
|
|
|
- put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
|
|
|
+ rp.manufacturer = cpu_to_le16(hdev->manufacturer);
|
|
|
|
|
|
rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
|
|
|
rp.current_settings = cpu_to_le32(get_current_settings(hdev));
|
|
@@ -840,7 +857,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
|
|
|
BT_DBG("request for %s", hdev->name);
|
|
|
|
|
|
- timeout = get_unaligned_le16(&cp->timeout);
|
|
|
+ timeout = __le16_to_cpu(cp->timeout);
|
|
|
if (!cp->val && timeout > 0)
|
|
|
return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
|
|
|
MGMT_STATUS_INVALID_PARAMS);
|
|
@@ -1122,8 +1139,8 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
|
|
}
|
|
|
|
|
|
if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
|
|
|
- err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
|
|
|
- MGMT_STATUS_BUSY);
|
|
|
+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
|
|
|
+ MGMT_STATUS_BUSY);
|
|
|
goto failed;
|
|
|
}
|
|
|
|
|
@@ -1179,7 +1196,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
|
|
|
|
|
hci_dev_lock(hdev);
|
|
|
|
|
|
- if (!enable_le || !(hdev->features[4] & LMP_LE)) {
|
|
|
+ if (!(hdev->features[4] & LMP_LE)) {
|
|
|
err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
|
|
|
MGMT_STATUS_NOT_SUPPORTED);
|
|
|
goto unlock;
|
|
@@ -1227,10 +1244,8 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
|
|
|
|
|
err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
|
|
|
&hci_cp);
|
|
|
- if (err < 0) {
|
|
|
+ if (err < 0)
|
|
|
mgmt_pending_remove(cmd);
|
|
|
- goto unlock;
|
|
|
- }
|
|
|
|
|
|
unlock:
|
|
|
hci_dev_unlock(hdev);
|
|
@@ -1280,10 +1295,8 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
|
|
}
|
|
|
|
|
|
cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
|
|
|
- if (!cmd) {
|
|
|
+ if (!cmd)
|
|
|
err = -ENOMEM;
|
|
|
- goto failed;
|
|
|
- }
|
|
|
|
|
|
failed:
|
|
|
hci_dev_unlock(hdev);
|
|
@@ -1368,10 +1381,8 @@ update_class:
|
|
|
}
|
|
|
|
|
|
cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
|
|
|
- if (!cmd) {
|
|
|
+ if (!cmd)
|
|
|
err = -ENOMEM;
|
|
|
- goto unlock;
|
|
|
- }
|
|
|
|
|
|
unlock:
|
|
|
hci_dev_unlock(hdev);
|
|
@@ -1422,10 +1433,8 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
}
|
|
|
|
|
|
cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
|
|
|
- if (!cmd) {
|
|
|
+ if (!cmd)
|
|
|
err = -ENOMEM;
|
|
|
- goto unlock;
|
|
|
- }
|
|
|
|
|
|
unlock:
|
|
|
hci_dev_unlock(hdev);
|
|
@@ -1439,7 +1448,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
u16 key_count, expected_len;
|
|
|
int i;
|
|
|
|
|
|
- key_count = get_unaligned_le16(&cp->key_count);
|
|
|
+ key_count = __le16_to_cpu(cp->key_count);
|
|
|
|
|
|
expected_len = sizeof(*cp) + key_count *
|
|
|
sizeof(struct mgmt_link_key_info);
|
|
@@ -1512,7 +1521,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
goto unlock;
|
|
|
}
|
|
|
|
|
|
- if (cp->addr.type == MGMT_ADDR_BREDR)
|
|
|
+ if (cp->addr.type == BDADDR_BREDR)
|
|
|
err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
|
|
|
else
|
|
|
err = hci_remove_ltk(hdev, &cp->addr.bdaddr);
|
|
@@ -1524,7 +1533,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
}
|
|
|
|
|
|
if (cp->disconnect) {
|
|
|
- if (cp->addr.type == MGMT_ADDR_BREDR)
|
|
|
+ if (cp->addr.type == BDADDR_BREDR)
|
|
|
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
|
|
|
&cp->addr.bdaddr);
|
|
|
else
|
|
@@ -1548,7 +1557,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
goto unlock;
|
|
|
}
|
|
|
|
|
|
- put_unaligned_le16(conn->handle, &dc.handle);
|
|
|
+ dc.handle = cpu_to_le16(conn->handle);
|
|
|
dc.reason = 0x13; /* Remote User Terminated Connection */
|
|
|
err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
|
|
|
if (err < 0)
|
|
@@ -1584,7 +1593,7 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
goto failed;
|
|
|
}
|
|
|
|
|
|
- if (cp->addr.type == MGMT_ADDR_BREDR)
|
|
|
+ if (cp->addr.type == BDADDR_BREDR)
|
|
|
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
|
|
|
else
|
|
|
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
|
|
@@ -1601,7 +1610,7 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
goto failed;
|
|
|
}
|
|
|
|
|
|
- put_unaligned_le16(conn->handle, &dc.handle);
|
|
|
+ dc.handle = cpu_to_le16(conn->handle);
|
|
|
dc.reason = 0x13; /* Remote User Terminated Connection */
|
|
|
|
|
|
err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
|
|
@@ -1613,22 +1622,22 @@ failed:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static u8 link_to_mgmt(u8 link_type, u8 addr_type)
|
|
|
+static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
|
|
|
{
|
|
|
switch (link_type) {
|
|
|
case LE_LINK:
|
|
|
switch (addr_type) {
|
|
|
case ADDR_LE_DEV_PUBLIC:
|
|
|
- return MGMT_ADDR_LE_PUBLIC;
|
|
|
- case ADDR_LE_DEV_RANDOM:
|
|
|
- return MGMT_ADDR_LE_RANDOM;
|
|
|
+ return BDADDR_LE_PUBLIC;
|
|
|
+
|
|
|
default:
|
|
|
- return MGMT_ADDR_INVALID;
|
|
|
+ /* Fallback to LE Random address type */
|
|
|
+ return BDADDR_LE_RANDOM;
|
|
|
}
|
|
|
- case ACL_LINK:
|
|
|
- return MGMT_ADDR_BREDR;
|
|
|
+
|
|
|
default:
|
|
|
- return MGMT_ADDR_INVALID;
|
|
|
+ /* Fallback to BR/EDR type */
|
|
|
+ return BDADDR_BREDR;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1669,13 +1678,13 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
|
|
|
continue;
|
|
|
bacpy(&rp->addr[i].bdaddr, &c->dst);
|
|
|
- rp->addr[i].type = link_to_mgmt(c->type, c->dst_type);
|
|
|
- if (rp->addr[i].type == MGMT_ADDR_INVALID)
|
|
|
+ rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
|
|
|
+ if (c->type == SCO_LINK || c->type == ESCO_LINK)
|
|
|
continue;
|
|
|
i++;
|
|
|
}
|
|
|
|
|
|
- put_unaligned_le16(i, &rp->conn_count);
|
|
|
+ rp->conn_count = cpu_to_le16(i);
|
|
|
|
|
|
/* Recalculate length in case of filtered SCO connections, etc */
|
|
|
rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
|
|
@@ -1836,7 +1845,7 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status)
|
|
|
struct hci_conn *conn = cmd->user_data;
|
|
|
|
|
|
bacpy(&rp.addr.bdaddr, &conn->dst);
|
|
|
- rp.addr.type = link_to_mgmt(conn->type, conn->dst_type);
|
|
|
+ rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
|
|
|
|
|
|
cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
|
|
|
&rp, sizeof(rp));
|
|
@@ -1890,12 +1899,12 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
else
|
|
|
auth_type = HCI_AT_DEDICATED_BONDING_MITM;
|
|
|
|
|
|
- if (cp->addr.type == MGMT_ADDR_BREDR)
|
|
|
- conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr, sec_level,
|
|
|
- auth_type);
|
|
|
+ if (cp->addr.type == BDADDR_BREDR)
|
|
|
+ conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr,
|
|
|
+ cp->addr.type, sec_level, auth_type);
|
|
|
else
|
|
|
- conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, sec_level,
|
|
|
- auth_type);
|
|
|
+ conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr,
|
|
|
+ cp->addr.type, sec_level, auth_type);
|
|
|
|
|
|
memset(&rp, 0, sizeof(rp));
|
|
|
bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
|
|
@@ -1923,7 +1932,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
}
|
|
|
|
|
|
/* For LE, just connecting isn't a proof that the pairing finished */
|
|
|
- if (cp->addr.type == MGMT_ADDR_BREDR)
|
|
|
+ if (cp->addr.type == BDADDR_BREDR)
|
|
|
conn->connect_cfm_cb = pairing_complete_cb;
|
|
|
|
|
|
conn->security_cfm_cb = pairing_complete_cb;
|
|
@@ -2000,7 +2009,7 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
- if (type == MGMT_ADDR_BREDR)
|
|
|
+ if (type == BDADDR_BREDR)
|
|
|
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
|
|
|
else
|
|
|
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
|
|
@@ -2011,7 +2020,7 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
- if (type == MGMT_ADDR_LE_PUBLIC || type == MGMT_ADDR_LE_RANDOM) {
|
|
|
+ if (type == BDADDR_LE_PUBLIC || type == BDADDR_LE_RANDOM) {
|
|
|
/* Continue with pairing via SMP */
|
|
|
err = smp_user_confirm_reply(conn, mgmt_op, passkey);
|
|
|
|
|
@@ -2295,6 +2304,12 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
|
|
|
goto failed;
|
|
|
}
|
|
|
|
|
|
+ if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
|
|
|
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
|
|
|
+ MGMT_STATUS_BUSY);
|
|
|
+ goto failed;
|
|
|
+ }
|
|
|
+
|
|
|
if (hdev->discovery.state != DISCOVERY_STOPPED) {
|
|
|
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
|
|
|
MGMT_STATUS_BUSY);
|
|
@@ -2381,27 +2396,39 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
goto unlock;
|
|
|
}
|
|
|
|
|
|
- if (hdev->discovery.state == DISCOVERY_FINDING) {
|
|
|
- err = hci_cancel_inquiry(hdev);
|
|
|
- if (err < 0)
|
|
|
- mgmt_pending_remove(cmd);
|
|
|
+ switch (hdev->discovery.state) {
|
|
|
+ case DISCOVERY_FINDING:
|
|
|
+ if (test_bit(HCI_INQUIRY, &hdev->flags))
|
|
|
+ err = hci_cancel_inquiry(hdev);
|
|
|
else
|
|
|
- hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
|
|
|
- goto unlock;
|
|
|
- }
|
|
|
+ err = hci_cancel_le_scan(hdev);
|
|
|
|
|
|
- e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_PENDING);
|
|
|
- if (!e) {
|
|
|
- mgmt_pending_remove(cmd);
|
|
|
- err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
|
|
|
- &mgmt_cp->type, sizeof(mgmt_cp->type));
|
|
|
- hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
|
|
|
- goto unlock;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DISCOVERY_RESOLVING:
|
|
|
+ e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
|
|
|
+ NAME_PENDING);
|
|
|
+ if (!e) {
|
|
|
+ mgmt_pending_remove(cmd);
|
|
|
+ err = cmd_complete(sk, hdev->id,
|
|
|
+ MGMT_OP_STOP_DISCOVERY, 0,
|
|
|
+ &mgmt_cp->type,
|
|
|
+ sizeof(mgmt_cp->type));
|
|
|
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ bacpy(&cp.bdaddr, &e->data.bdaddr);
|
|
|
+ err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ_CANCEL,
|
|
|
+ sizeof(cp), &cp);
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ BT_DBG("unknown discovery state %u", hdev->discovery.state);
|
|
|
+ err = -EFAULT;
|
|
|
}
|
|
|
|
|
|
- bacpy(&cp.bdaddr, &e->data.bdaddr);
|
|
|
- err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
|
|
|
- &cp);
|
|
|
if (err < 0)
|
|
|
mgmt_pending_remove(cmd);
|
|
|
else
|
|
@@ -2501,6 +2528,37 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
+ u16 len)
|
|
|
+{
|
|
|
+ struct mgmt_cp_set_device_id *cp = data;
|
|
|
+ int err;
|
|
|
+ __u16 source;
|
|
|
+
|
|
|
+ BT_DBG("%s", hdev->name);
|
|
|
+
|
|
|
+ source = __le16_to_cpu(cp->source);
|
|
|
+
|
|
|
+ if (source > 0x0002)
|
|
|
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
|
|
|
+ MGMT_STATUS_INVALID_PARAMS);
|
|
|
+
|
|
|
+ hci_dev_lock(hdev);
|
|
|
+
|
|
|
+ hdev->devid_source = source;
|
|
|
+ hdev->devid_vendor = __le16_to_cpu(cp->vendor);
|
|
|
+ hdev->devid_product = __le16_to_cpu(cp->product);
|
|
|
+ hdev->devid_version = __le16_to_cpu(cp->version);
|
|
|
+
|
|
|
+ err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
|
|
|
+
|
|
|
+ update_eir(hdev);
|
|
|
+
|
|
|
+ hci_dev_unlock(hdev);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
|
|
|
void *data, u16 len)
|
|
|
{
|
|
@@ -2565,7 +2623,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
|
|
|
u16 key_count, expected_len;
|
|
|
int i;
|
|
|
|
|
|
- key_count = get_unaligned_le16(&cp->key_count);
|
|
|
+ key_count = __le16_to_cpu(cp->key_count);
|
|
|
|
|
|
expected_len = sizeof(*cp) + key_count *
|
|
|
sizeof(struct mgmt_ltk_info);
|
|
@@ -2591,7 +2649,8 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
|
|
|
else
|
|
|
type = HCI_SMP_LTK_SLAVE;
|
|
|
|
|
|
- hci_add_ltk(hdev, &key->addr.bdaddr, key->addr.type,
|
|
|
+ hci_add_ltk(hdev, &key->addr.bdaddr,
|
|
|
+ bdaddr_to_le(key->addr.type),
|
|
|
type, 0, key->authenticated, key->val,
|
|
|
key->enc_size, key->ediv, key->rand);
|
|
|
}
|
|
@@ -2601,7 +2660,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-struct mgmt_handler {
|
|
|
+static const struct mgmt_handler {
|
|
|
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
u16 data_len);
|
|
|
bool var_len;
|
|
@@ -2647,6 +2706,7 @@ struct mgmt_handler {
|
|
|
{ confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
|
|
|
{ block_device, false, MGMT_BLOCK_DEVICE_SIZE },
|
|
|
{ unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
|
|
|
+ { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
|
|
|
};
|
|
|
|
|
|
|
|
@@ -2657,7 +2717,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
|
|
|
struct mgmt_hdr *hdr;
|
|
|
u16 opcode, index, len;
|
|
|
struct hci_dev *hdev = NULL;
|
|
|
- struct mgmt_handler *handler;
|
|
|
+ const struct mgmt_handler *handler;
|
|
|
int err;
|
|
|
|
|
|
BT_DBG("got %zu bytes", msglen);
|
|
@@ -2675,9 +2735,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
|
|
|
}
|
|
|
|
|
|
hdr = buf;
|
|
|
- opcode = get_unaligned_le16(&hdr->opcode);
|
|
|
- index = get_unaligned_le16(&hdr->index);
|
|
|
- len = get_unaligned_le16(&hdr->len);
|
|
|
+ opcode = __le16_to_cpu(hdr->opcode);
|
|
|
+ index = __le16_to_cpu(hdr->index);
|
|
|
+ len = __le16_to_cpu(hdr->len);
|
|
|
|
|
|
if (len != msglen - sizeof(*hdr)) {
|
|
|
err = -EINVAL;
|
|
@@ -2884,7 +2944,8 @@ int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, bool persistent)
|
|
|
+int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
|
|
|
+ bool persistent)
|
|
|
{
|
|
|
struct mgmt_ev_new_link_key ev;
|
|
|
|
|
@@ -2892,7 +2953,7 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, bool persisten
|
|
|
|
|
|
ev.store_hint = persistent;
|
|
|
bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
|
|
|
- ev.key.addr.type = MGMT_ADDR_BREDR;
|
|
|
+ ev.key.addr.type = BDADDR_BREDR;
|
|
|
ev.key.type = key->type;
|
|
|
memcpy(ev.key.val, key->val, 16);
|
|
|
ev.key.pin_len = key->pin_len;
|
|
@@ -2908,7 +2969,7 @@ int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent)
|
|
|
|
|
|
ev.store_hint = persistent;
|
|
|
bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
|
|
|
- ev.key.addr.type = key->bdaddr_type;
|
|
|
+ ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
|
|
|
ev.key.authenticated = key->authenticated;
|
|
|
ev.key.enc_size = key->enc_size;
|
|
|
ev.key.ediv = key->ediv;
|
|
@@ -2932,7 +2993,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|
|
u16 eir_len = 0;
|
|
|
|
|
|
bacpy(&ev->addr.bdaddr, bdaddr);
|
|
|
- ev->addr.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ ev->addr.type = link_to_bdaddr(link_type, addr_type);
|
|
|
|
|
|
ev->flags = __cpu_to_le32(flags);
|
|
|
|
|
@@ -2944,7 +3005,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|
|
eir_len = eir_append_data(ev->eir, eir_len,
|
|
|
EIR_CLASS_OF_DEV, dev_class, 3);
|
|
|
|
|
|
- put_unaligned_le16(eir_len, &ev->eir_len);
|
|
|
+ ev->eir_len = cpu_to_le16(eir_len);
|
|
|
|
|
|
return mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
|
|
|
sizeof(*ev) + eir_len, NULL);
|
|
@@ -2995,13 +3056,13 @@ int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
|
|
|
|
|
|
bacpy(&ev.bdaddr, bdaddr);
|
|
|
- ev.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ ev.type = link_to_bdaddr(link_type, addr_type);
|
|
|
|
|
|
err = mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev),
|
|
|
sk);
|
|
|
|
|
|
if (sk)
|
|
|
- sock_put(sk);
|
|
|
+ sock_put(sk);
|
|
|
|
|
|
mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
|
|
|
hdev);
|
|
@@ -3021,7 +3082,7 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
return -ENOENT;
|
|
|
|
|
|
bacpy(&rp.addr.bdaddr, bdaddr);
|
|
|
- rp.addr.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ rp.addr.type = link_to_bdaddr(link_type, addr_type);
|
|
|
|
|
|
err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
|
|
|
mgmt_status(status), &rp, sizeof(rp));
|
|
@@ -3039,7 +3100,7 @@ int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|
|
struct mgmt_ev_connect_failed ev;
|
|
|
|
|
|
bacpy(&ev.addr.bdaddr, bdaddr);
|
|
|
- ev.addr.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ ev.addr.type = link_to_bdaddr(link_type, addr_type);
|
|
|
ev.status = mgmt_status(status);
|
|
|
|
|
|
return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
|
|
@@ -3050,7 +3111,7 @@ int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
|
|
|
struct mgmt_ev_pin_code_request ev;
|
|
|
|
|
|
bacpy(&ev.addr.bdaddr, bdaddr);
|
|
|
- ev.addr.type = MGMT_ADDR_BREDR;
|
|
|
+ ev.addr.type = BDADDR_BREDR;
|
|
|
ev.secure = secure;
|
|
|
|
|
|
return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev),
|
|
@@ -3069,7 +3130,7 @@ int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
return -ENOENT;
|
|
|
|
|
|
bacpy(&rp.addr.bdaddr, bdaddr);
|
|
|
- rp.addr.type = MGMT_ADDR_BREDR;
|
|
|
+ rp.addr.type = BDADDR_BREDR;
|
|
|
|
|
|
err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
|
|
|
mgmt_status(status), &rp, sizeof(rp));
|
|
@@ -3091,7 +3152,7 @@ int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
return -ENOENT;
|
|
|
|
|
|
bacpy(&rp.addr.bdaddr, bdaddr);
|
|
|
- rp.addr.type = MGMT_ADDR_BREDR;
|
|
|
+ rp.addr.type = BDADDR_BREDR;
|
|
|
|
|
|
err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
|
|
|
mgmt_status(status), &rp, sizeof(rp));
|
|
@@ -3110,9 +3171,9 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
|
bacpy(&ev.addr.bdaddr, bdaddr);
|
|
|
- ev.addr.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ ev.addr.type = link_to_bdaddr(link_type, addr_type);
|
|
|
ev.confirm_hint = confirm_hint;
|
|
|
- put_unaligned_le32(value, &ev.value);
|
|
|
+ ev.value = value;
|
|
|
|
|
|
return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
|
|
|
NULL);
|
|
@@ -3126,7 +3187,7 @@ int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
|
bacpy(&ev.addr.bdaddr, bdaddr);
|
|
|
- ev.addr.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ ev.addr.type = link_to_bdaddr(link_type, addr_type);
|
|
|
|
|
|
return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
|
|
|
NULL);
|
|
@@ -3145,7 +3206,7 @@ static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
return -ENOENT;
|
|
|
|
|
|
bacpy(&rp.addr.bdaddr, bdaddr);
|
|
|
- rp.addr.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ rp.addr.type = link_to_bdaddr(link_type, addr_type);
|
|
|
err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
|
|
|
&rp, sizeof(rp));
|
|
|
|
|
@@ -3188,7 +3249,7 @@ int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|
|
struct mgmt_ev_auth_failed ev;
|
|
|
|
|
|
bacpy(&ev.addr.bdaddr, bdaddr);
|
|
|
- ev.addr.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ ev.addr.type = link_to_bdaddr(link_type, addr_type);
|
|
|
ev.status = mgmt_status(status);
|
|
|
|
|
|
return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
|
|
@@ -3413,10 +3474,10 @@ int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
|
|
|
|
|
|
if (enable && test_and_clear_bit(HCI_LE_ENABLED,
|
|
|
&hdev->dev_flags))
|
|
|
- err = new_settings(hdev, NULL);
|
|
|
+ err = new_settings(hdev, NULL);
|
|
|
|
|
|
- mgmt_pending_foreach(MGMT_OP_SET_LE, hdev,
|
|
|
- cmd_status_rsp, &mgmt_err);
|
|
|
+ mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
|
|
|
+ &mgmt_err);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -3455,7 +3516,7 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
|
|
bacpy(&ev->addr.bdaddr, bdaddr);
|
|
|
- ev->addr.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ ev->addr.type = link_to_bdaddr(link_type, addr_type);
|
|
|
ev->rssi = rssi;
|
|
|
if (cfm_name)
|
|
|
ev->flags[0] |= MGMT_DEV_FOUND_CONFIRM_NAME;
|
|
@@ -3469,7 +3530,7 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|
|
eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
|
|
|
dev_class, 3);
|
|
|
|
|
|
- put_unaligned_le16(eir_len, &ev->eir_len);
|
|
|
+ ev->eir_len = cpu_to_le16(eir_len);
|
|
|
|
|
|
ev_size = sizeof(*ev) + eir_len;
|
|
|
|
|
@@ -3488,13 +3549,13 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
|
|
bacpy(&ev->addr.bdaddr, bdaddr);
|
|
|
- ev->addr.type = link_to_mgmt(link_type, addr_type);
|
|
|
+ ev->addr.type = link_to_bdaddr(link_type, addr_type);
|
|
|
ev->rssi = rssi;
|
|
|
|
|
|
eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
|
|
|
name_len);
|
|
|
|
|
|
- put_unaligned_le16(eir_len, &ev->eir_len);
|
|
|
+ ev->eir_len = cpu_to_le16(eir_len);
|
|
|
|
|
|
return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev,
|
|
|
sizeof(*ev) + eir_len, NULL);
|
|
@@ -3594,6 +3655,3 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
|
|
|
|
|
|
module_param(enable_hs, bool, 0644);
|
|
|
MODULE_PARM_DESC(enable_hs, "Enable High Speed support");
|
|
|
-
|
|
|
-module_param(enable_le, bool, 0644);
|
|
|
-MODULE_PARM_DESC(enable_le, "Enable Low Energy support");
|