Skip to content

Commit

Permalink
Bluetooth: Add LE connection support to L2CAP
Browse files Browse the repository at this point in the history
Add basic LE connection support to L2CAP. LE
connection can be created by specifying cid
in struct sockaddr_l2

Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
  • Loading branch information
Ville Tervo authored and Gustavo F. Padovan committed Feb 16, 2011
1 parent 6ed58ec commit acd7d37
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 7 deletions.
3 changes: 3 additions & 0 deletions include/net/bluetooth/l2cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ struct l2cap_conn_rsp {
/* channel indentifier */
#define L2CAP_CID_SIGNALING 0x0001
#define L2CAP_CID_CONN_LESS 0x0002
#define L2CAP_CID_LE_DATA 0x0004
#define L2CAP_CID_LE_SIGNALING 0x0005
#define L2CAP_CID_SMP 0x0006
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff

Expand Down
23 changes: 19 additions & 4 deletions net/bluetooth/l2cap_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,12 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
bh_lock_sock(sk);

if (conn->hcon->type == LE_LINK) {
l2cap_sock_clear_timer(sk);
sk->sk_state = BT_CONNECTED;
sk->sk_state_change(sk);
}

if (sk->sk_type != SOCK_SEQPACKET &&
sk->sk_type != SOCK_STREAM) {
l2cap_sock_clear_timer(sk);
Expand Down Expand Up @@ -651,7 +657,11 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)

BT_DBG("hcon %p conn %p", hcon, conn);

conn->mtu = hcon->hdev->acl_mtu;
if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
conn->mtu = hcon->hdev->le_mtu;
else
conn->mtu = hcon->hdev->acl_mtu;

conn->src = &hcon->hdev->bdaddr;
conn->dst = &hcon->dst;

Expand Down Expand Up @@ -758,8 +768,13 @@ int l2cap_do_connect(struct sock *sk)

auth_type = l2cap_get_auth_type(sk);

hcon = hci_connect(hdev, ACL_LINK, dst,
if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
hcon = hci_connect(hdev, LE_LINK, dst,
l2cap_pi(sk)->sec_level, auth_type);
else
hcon = hci_connect(hdev, ACL_LINK, dst,
l2cap_pi(sk)->sec_level, auth_type);

if (!hcon)
goto done;

Expand Down Expand Up @@ -3520,7 +3535,7 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)

BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);

if (hcon->type != ACL_LINK)
if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
return -EINVAL;

if (!status) {
Expand Down Expand Up @@ -3549,7 +3564,7 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
{
BT_DBG("hcon %p reason %d", hcon, reason);

if (hcon->type != ACL_LINK)
if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
return -EINVAL;

l2cap_conn_del(hcon, bt_err(reason));
Expand Down
7 changes: 4 additions & 3 deletions net/bluetooth/l2cap_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,13 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
len = min_t(unsigned int, sizeof(la), alen);
memcpy(&la, addr, len);

if (la.l2_cid)
if (la.l2_cid && la.l2_psm)
return -EINVAL;

lock_sock(sk);

if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
&& !la.l2_psm) {
&& !(la.l2_psm || la.l2_cid)) {
err = -EINVAL;
goto done;
}
Expand Down Expand Up @@ -216,14 +216,15 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al

/* PSM must be odd and lsb of upper byte must be 0 */
if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
sk->sk_type != SOCK_RAW) {
sk->sk_type != SOCK_RAW && !la.l2_cid) {
err = -EINVAL;
goto done;
}

/* Set destination address and psm */
bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
l2cap_pi(sk)->psm = la.l2_psm;
l2cap_pi(sk)->dcid = la.l2_cid;

err = l2cap_do_connect(sk);
if (err)
Expand Down

0 comments on commit acd7d37

Please sign in to comment.