Commit 5d38745f authored by John W. Linville's avatar John W. Linville

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents e56b04ef a3d09356
...@@ -86,6 +86,7 @@ struct bdaddr_list { ...@@ -86,6 +86,7 @@ struct bdaddr_list {
struct bt_uuid { struct bt_uuid {
struct list_head list; struct list_head list;
u8 uuid[16]; u8 uuid[16];
u8 size;
u8 svc_hint; u8 svc_hint;
}; };
......
...@@ -1183,14 +1183,10 @@ static void hci_discov_off(struct work_struct *work) ...@@ -1183,14 +1183,10 @@ static void hci_discov_off(struct work_struct *work)
int hci_uuids_clear(struct hci_dev *hdev) int hci_uuids_clear(struct hci_dev *hdev)
{ {
struct list_head *p, *n; struct bt_uuid *uuid, *tmp;
list_for_each_safe(p, n, &hdev->uuids) {
struct bt_uuid *uuid;
uuid = list_entry(p, struct bt_uuid, list); list_for_each_entry_safe(uuid, tmp, &hdev->uuids, list) {
list_del(&uuid->list);
list_del(p);
kfree(uuid); kfree(uuid);
} }
......
...@@ -3988,8 +3988,6 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3988,8 +3988,6 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
void *ptr = &skb->data[1]; void *ptr = &skb->data[1];
s8 rssi; s8 rssi;
hci_dev_lock(hdev);
while (num_reports--) { while (num_reports--) {
struct hci_ev_le_advertising_info *ev = ptr; struct hci_ev_le_advertising_info *ev = ptr;
...@@ -3999,8 +3997,6 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3999,8 +3997,6 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
ptr += sizeof(*ev) + ev->length + 1; ptr += sizeof(*ev) + ev->length + 1;
} }
hci_dev_unlock(hdev);
} }
static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
bool enable_hs; bool enable_hs;
#define MGMT_VERSION 1 #define MGMT_VERSION 1
#define MGMT_REVISION 2 #define MGMT_REVISION 3
static const u16 mgmt_commands[] = { static const u16 mgmt_commands[] = {
MGMT_OP_READ_INDEX_LIST, MGMT_OP_READ_INDEX_LIST,
...@@ -435,35 +435,117 @@ static u32 get_current_settings(struct hci_dev *hdev) ...@@ -435,35 +435,117 @@ static u32 get_current_settings(struct hci_dev *hdev)
#define PNP_INFO_SVCLASS_ID 0x1200 #define PNP_INFO_SVCLASS_ID 0x1200
static u8 bluetooth_base_uuid[] = { static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, {
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, u8 *ptr = data, *uuids_start = NULL;
}; struct bt_uuid *uuid;
if (len < 4)
return ptr;
list_for_each_entry(uuid, &hdev->uuids, list) {
u16 uuid16;
if (uuid->size != 16)
continue;
uuid16 = get_unaligned_le16(&uuid->uuid[12]);
if (uuid16 < 0x1100)
continue;
if (uuid16 == PNP_INFO_SVCLASS_ID)
continue;
if (!uuids_start) {
uuids_start = ptr;
uuids_start[0] = 1;
uuids_start[1] = EIR_UUID16_ALL;
ptr += 2;
}
/* Stop if not enough space to put next UUID */
if ((ptr - data) + sizeof(u16) > len) {
uuids_start[1] = EIR_UUID16_SOME;
break;
}
*ptr++ = (uuid16 & 0x00ff);
*ptr++ = (uuid16 & 0xff00) >> 8;
uuids_start[0] += sizeof(uuid16);
}
return ptr;
}
static u16 get_uuid16(u8 *uuid128) static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
{ {
u32 val; u8 *ptr = data, *uuids_start = NULL;
int i; struct bt_uuid *uuid;
if (len < 6)
return ptr;
list_for_each_entry(uuid, &hdev->uuids, list) {
if (uuid->size != 32)
continue;
if (!uuids_start) {
uuids_start = ptr;
uuids_start[0] = 1;
uuids_start[1] = EIR_UUID32_ALL;
ptr += 2;
}
/* Stop if not enough space to put next UUID */
if ((ptr - data) + sizeof(u32) > len) {
uuids_start[1] = EIR_UUID32_SOME;
break;
}
for (i = 0; i < 12; i++) { memcpy(ptr, &uuid->uuid[12], sizeof(u32));
if (bluetooth_base_uuid[i] != uuid128[i]) ptr += sizeof(u32);
return 0; uuids_start[0] += sizeof(u32);
} }
val = get_unaligned_le32(&uuid128[12]); return ptr;
if (val > 0xffff) }
return 0;
static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
{
u8 *ptr = data, *uuids_start = NULL;
struct bt_uuid *uuid;
if (len < 18)
return ptr;
list_for_each_entry(uuid, &hdev->uuids, list) {
if (uuid->size != 128)
continue;
if (!uuids_start) {
uuids_start = ptr;
uuids_start[0] = 1;
uuids_start[1] = EIR_UUID128_ALL;
ptr += 2;
}
return (u16) val; /* Stop if not enough space to put next UUID */
if ((ptr - data) + 16 > len) {
uuids_start[1] = EIR_UUID128_SOME;
break;
}
memcpy(ptr, uuid->uuid, 16);
ptr += 16;
uuids_start[0] += 16;
}
return ptr;
} }
static void create_eir(struct hci_dev *hdev, u8 *data) static void create_eir(struct hci_dev *hdev, u8 *data)
{ {
u8 *ptr = data; u8 *ptr = data;
u16 eir_len = 0;
u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
int i, truncated = 0;
struct bt_uuid *uuid;
size_t name_len; size_t name_len;
name_len = strlen(hdev->dev_name); name_len = strlen(hdev->dev_name);
...@@ -481,7 +563,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data) ...@@ -481,7 +563,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
memcpy(ptr + 2, hdev->dev_name, name_len); memcpy(ptr + 2, hdev->dev_name, name_len);
eir_len += (name_len + 2);
ptr += (name_len + 2); ptr += (name_len + 2);
} }
...@@ -490,7 +571,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data) ...@@ -490,7 +571,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
ptr[1] = EIR_TX_POWER; ptr[1] = EIR_TX_POWER;
ptr[2] = (u8) hdev->inq_tx_power; ptr[2] = (u8) hdev->inq_tx_power;
eir_len += 3;
ptr += 3; ptr += 3;
} }
...@@ -503,60 +583,12 @@ static void create_eir(struct hci_dev *hdev, u8 *data) ...@@ -503,60 +583,12 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
put_unaligned_le16(hdev->devid_product, ptr + 6); put_unaligned_le16(hdev->devid_product, ptr + 6);
put_unaligned_le16(hdev->devid_version, ptr + 8); put_unaligned_le16(hdev->devid_version, ptr + 8);
eir_len += 10;
ptr += 10; ptr += 10;
} }
memset(uuid16_list, 0, sizeof(uuid16_list)); ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
/* Group all UUID16 types */ ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
list_for_each_entry(uuid, &hdev->uuids, list) {
u16 uuid16;
uuid16 = get_uuid16(uuid->uuid);
if (uuid16 == 0)
return;
if (uuid16 < 0x1100)
continue;
if (uuid16 == PNP_INFO_SVCLASS_ID)
continue;
/* Stop if not enough space to put next UUID */
if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
truncated = 1;
break;
}
/* Check for duplicates */
for (i = 0; uuid16_list[i] != 0; i++)
if (uuid16_list[i] == uuid16)
break;
if (uuid16_list[i] == 0) {
uuid16_list[i] = uuid16;
eir_len += sizeof(u16);
}
}
if (uuid16_list[0] != 0) {
u8 *length = ptr;
/* EIR Data type */
ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
ptr += 2;
eir_len += 2;
for (i = 0; uuid16_list[i] != 0; i++) {
*ptr++ = (uuid16_list[i] & 0x00ff);
*ptr++ = (uuid16_list[i] & 0xff00) >> 8;
}
/* EIR Data length */
*length = (i * sizeof(u16)) + 1;
}
} }
static int update_eir(struct hci_dev *hdev) static int update_eir(struct hci_dev *hdev)
...@@ -728,13 +760,9 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, ...@@ -728,13 +760,9 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
void *data), void *data),
void *data) void *data)
{ {
struct list_head *p, *n; struct pending_cmd *cmd, *tmp;
list_for_each_safe(p, n, &hdev->mgmt_pending) {
struct pending_cmd *cmd;
cmd = list_entry(p, struct pending_cmd, list);
list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
if (opcode > 0 && cmd->opcode != opcode) if (opcode > 0 && cmd->opcode != opcode)
continue; continue;
...@@ -1304,6 +1332,25 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -1304,6 +1332,25 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
return err; return err;
} }
static const u8 bluetooth_base_uuid[] = {
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static u8 get_uuid_size(const u8 *uuid)
{
u32 val;
if (memcmp(uuid, bluetooth_base_uuid, 12))
return 128;
val = get_unaligned_le32(&uuid[12]);
if (val > 0xffff)
return 32;
return 16;
}
static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{ {
struct mgmt_cp_add_uuid *cp = data; struct mgmt_cp_add_uuid *cp = data;
...@@ -1329,8 +1376,9 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -1329,8 +1376,9 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
memcpy(uuid->uuid, cp->uuid, 16); memcpy(uuid->uuid, cp->uuid, 16);
uuid->svc_hint = cp->svc_hint; uuid->svc_hint = cp->svc_hint;
uuid->size = get_uuid_size(cp->uuid);
list_add(&uuid->list, &hdev->uuids); list_add_tail(&uuid->list, &hdev->uuids);
err = update_class(hdev); err = update_class(hdev);
if (err < 0) if (err < 0)
...@@ -1374,7 +1422,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1374,7 +1422,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
{ {
struct mgmt_cp_remove_uuid *cp = data; struct mgmt_cp_remove_uuid *cp = data;
struct pending_cmd *cmd; struct pending_cmd *cmd;
struct list_head *p, *n; struct bt_uuid *match, *tmp;
u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int err, found; int err, found;
...@@ -1402,9 +1450,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1402,9 +1450,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
found = 0; found = 0;
list_for_each_safe(p, n, &hdev->uuids) { list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
if (memcmp(match->uuid, cp->uuid, 16) != 0) if (memcmp(match->uuid, cp->uuid, 16) != 0)
continue; continue;
...@@ -3023,6 +3069,8 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) ...@@ -3023,6 +3069,8 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
if (powered) { if (powered) {
u8 link_sec;
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
!lmp_host_ssp_capable(hdev)) { !lmp_host_ssp_capable(hdev)) {
u8 ssp = 1; u8 ssp = 1;
...@@ -3046,6 +3094,11 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) ...@@ -3046,6 +3094,11 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
sizeof(cp), &cp); sizeof(cp), &cp);
} }
link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
sizeof(link_sec), &link_sec);
if (lmp_bredr_capable(hdev)) { if (lmp_bredr_capable(hdev)) {
set_bredr_scan(hdev); set_bredr_scan(hdev);
update_class(hdev); update_class(hdev);
......
...@@ -900,8 +900,6 @@ static void sco_conn_ready(struct sco_conn *conn) ...@@ -900,8 +900,6 @@ static void sco_conn_ready(struct sco_conn *conn)
BT_DBG("conn %p", conn); BT_DBG("conn %p", conn);
sco_conn_lock(conn);
if (sk) { if (sk) {
sco_sock_clear_timer(sk); sco_sock_clear_timer(sk);
bh_lock_sock(sk); bh_lock_sock(sk);
...@@ -909,9 +907,13 @@ static void sco_conn_ready(struct sco_conn *conn) ...@@ -909,9 +907,13 @@ static void sco_conn_ready(struct sco_conn *conn)
sk->sk_state_change(sk); sk->sk_state_change(sk);
bh_unlock_sock(sk); bh_unlock_sock(sk);
} else { } else {
sco_conn_lock(conn);
parent = sco_get_sock_listen(conn->src); parent = sco_get_sock_listen(conn->src);
if (!parent) if (!parent) {
goto done; sco_conn_unlock(conn);
return;
}
bh_lock_sock(parent); bh_lock_sock(parent);
...@@ -919,7 +921,8 @@ static void sco_conn_ready(struct sco_conn *conn) ...@@ -919,7 +921,8 @@ static void sco_conn_ready(struct sco_conn *conn)
BTPROTO_SCO, GFP_ATOMIC); BTPROTO_SCO, GFP_ATOMIC);
if (!sk) { if (!sk) {
bh_unlock_sock(parent); bh_unlock_sock(parent);
goto done; sco_conn_unlock(conn);
return;
} }
sco_sock_init(sk, parent); sco_sock_init(sk, parent);
...@@ -939,10 +942,9 @@ static void sco_conn_ready(struct sco_conn *conn) ...@@ -939,10 +942,9 @@ static void sco_conn_ready(struct sco_conn *conn)
parent->sk_data_ready(parent, 1); parent->sk_data_ready(parent, 1);
bh_unlock_sock(parent); bh_unlock_sock(parent);
}
done: sco_conn_unlock(conn);
sco_conn_unlock(conn); }
} }
/* ----- SCO interface with lower layer (HCI) ----- */ /* ----- SCO interface with lower layer (HCI) ----- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment