Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 103668
b: refs/heads/master
c: 769be97
h: refs/heads/master
v: v3
  • Loading branch information
Marcel Holtmann committed Jul 14, 2008
1 parent d81fc89 commit 7652c0a
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a8bd28baf21b9ee6b8486666b771283e566c0d31
refs/heads/master: 769be974d0c7b4fe1a52f9cdaad22259b60953f7
2 changes: 2 additions & 0 deletions trunk/include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ enum {

#define LMP_SNIFF_SUBR 0x02

#define LMP_SIMPLE_PAIR 0x08

/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
#define HCI_CM_HOLD 0x0001
Expand Down
3 changes: 2 additions & 1 deletion trunk/include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ static inline void hci_conn_put(struct hci_conn *conn)
if (conn->state == BT_CONNECTED) {
timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
if (!conn->out)
timeo *= 2;
timeo *= 5;
} else
timeo = msecs_to_jiffies(10);
} else
Expand Down Expand Up @@ -463,6 +463,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)

/* ----- HCI protocols ----- */
struct hci_proto {
Expand Down
2 changes: 2 additions & 0 deletions trunk/net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,13 @@ static void hci_conn_timeout(unsigned long arg)

switch (conn->state) {
case BT_CONNECT:
case BT_CONNECT2:
if (conn->type == ACL_LINK)
hci_acl_connect_cancel(conn);
else
hci_acl_disconn(conn, 0x13);
break;
case BT_CONFIG:
case BT_CONNECTED:
hci_acl_disconn(conn, 0x13);
break;
Expand Down
7 changes: 5 additions & 2 deletions trunk/net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1283,9 +1283,12 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
struct hci_conn *c;
c = list_entry(p, struct hci_conn, list);

if (c->type != type || c->state != BT_CONNECTED
|| skb_queue_empty(&c->data_q))
if (c->type != type || skb_queue_empty(&c->data_q))
continue;

if (c->state != BT_CONNECTED && c->state != BT_CONFIG)
continue;

num++;

if (c->sent < min) {
Expand Down
127 changes: 107 additions & 20 deletions trunk/net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,62 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
BT_DBG("%s status 0x%x", hdev->name, status);
}

static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_read_remote_features *cp;
struct hci_conn *conn;

BT_DBG("%s status 0x%x", hdev->name, status);

if (!status)
return;

cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
if (!cp)
return;

hci_dev_lock(hdev);

conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, status);
hci_conn_put(conn);
}
}

hci_dev_unlock(hdev);
}

static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_read_remote_ext_features *cp;
struct hci_conn *conn;

BT_DBG("%s status 0x%x", hdev->name, status);

if (!status)
return;

cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
if (!cp)
return;

hci_dev_lock(hdev);

conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, status);
hci_conn_put(conn);
}
}

hci_dev_unlock(hdev);
}

static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_setup_sync_conn *cp;
Expand Down Expand Up @@ -759,7 +815,12 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s

if (!ev->status) {
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;

if (conn->type == ACL_LINK) {
conn->state = BT_CONFIG;
hci_conn_hold(conn);
} else
conn->state = BT_CONNECTED;

if (test_bit(HCI_AUTH, &hdev->flags))
conn->link_mode |= HCI_LM_AUTH;
Expand All @@ -771,7 +832,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (conn->type == ACL_LINK) {
struct hci_cp_read_remote_features cp;
cp.handle = ev->handle;
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, sizeof(cp), &cp);
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
sizeof(cp), &cp);
}

/* Set packet type for incoming connection */
Expand All @@ -781,10 +843,6 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
cp.pkt_type = cpu_to_le16(conn->pkt_type);
hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
sizeof(cp), &cp);
} else {
/* Update disconnect timer */
hci_conn_hold(conn);
hci_conn_put(conn);
}
} else
conn->state = BT_CLOSED;
Expand All @@ -804,9 +862,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
}
}

hci_proto_connect_cfm(conn, ev->status);
if (ev->status)
if (ev->status) {
hci_proto_connect_cfm(conn, ev->status);
hci_conn_del(conn);
}

unlock:
hci_dev_unlock(hdev);
Expand Down Expand Up @@ -1006,14 +1065,29 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff

BT_DBG("%s status %d", hdev->name, ev->status);

if (ev->status)
return;

hci_dev_lock(hdev);

conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn)
memcpy(conn->features, ev->features, 8);
if (conn) {
if (!ev->status)
memcpy(conn->features, ev->features, 8);

if (conn->state == BT_CONFIG) {
if (!ev->status && lmp_ssp_capable(hdev) &&
lmp_ssp_capable(conn)) {
struct hci_cp_read_remote_ext_features cp;
cp.handle = ev->handle;
cp.page = 0x01;
hci_send_cmd(hdev,
HCI_OP_READ_REMOTE_EXT_FEATURES,
sizeof(cp), &cp);
} else {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
}
}
}

hci_dev_unlock(hdev);
}
Expand Down Expand Up @@ -1180,6 +1254,14 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_remote_name_req(hdev, ev->status);
break;

case HCI_OP_READ_REMOTE_FEATURES:
hci_cs_read_remote_features(hdev, ev->status);
break;

case HCI_OP_READ_REMOTE_EXT_FEATURES:
hci_cs_read_remote_ext_features(hdev, ev->status);
break;

case HCI_OP_SETUP_SYNC_CONN:
hci_cs_setup_sync_conn(hdev, ev->status);
break;
Expand Down Expand Up @@ -1422,19 +1504,24 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b

BT_DBG("%s", hdev->name);

if (ev->status || ev->page != 0x01)
return;

hci_dev_lock(hdev);

conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) {
struct inquiry_entry *ie;
if (!ev->status && ev->page == 0x01) {
struct inquiry_entry *ie;

if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
ie->data.ssp_mode = (ev->features[0] & 0x01);
if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
ie->data.ssp_mode = (ev->features[0] & 0x01);

conn->ssp_mode = (ev->features[0] & 0x01);
conn->ssp_mode = (ev->features[0] & 0x01);
}

if (conn->state == BT_CONFIG) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
}
}

hci_dev_unlock(hdev);
Expand Down

0 comments on commit 7652c0a

Please sign in to comment.