diff options
author | Ville Tervo <ville.tervo@nokia.com> | 2011-02-10 20:38:49 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-02-16 14:32:55 -0500 |
commit | acd7d3708555b3da7522e23c183cc21efc785f72 (patch) | |
tree | 41a15cea1207308c26c344a2bc585175be432fae /net/bluetooth | |
parent | 6ed58ec520ad2b2fe3f955c8a5fd0eecafccebdf (diff) |
Bluetooth: Add LE connection support to L2CAP
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>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 23 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 7 |
2 files changed, 23 insertions, 7 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a72d6e4eab4f..123c1bfa0ce6 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -593,6 +593,12 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
593 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 593 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { |
594 | bh_lock_sock(sk); | 594 | bh_lock_sock(sk); |
595 | 595 | ||
596 | if (conn->hcon->type == LE_LINK) { | ||
597 | l2cap_sock_clear_timer(sk); | ||
598 | sk->sk_state = BT_CONNECTED; | ||
599 | sk->sk_state_change(sk); | ||
600 | } | ||
601 | |||
596 | if (sk->sk_type != SOCK_SEQPACKET && | 602 | if (sk->sk_type != SOCK_SEQPACKET && |
597 | sk->sk_type != SOCK_STREAM) { | 603 | sk->sk_type != SOCK_STREAM) { |
598 | l2cap_sock_clear_timer(sk); | 604 | l2cap_sock_clear_timer(sk); |
@@ -651,7 +657,11 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | |||
651 | 657 | ||
652 | BT_DBG("hcon %p conn %p", hcon, conn); | 658 | BT_DBG("hcon %p conn %p", hcon, conn); |
653 | 659 | ||
654 | conn->mtu = hcon->hdev->acl_mtu; | 660 | if (hcon->hdev->le_mtu && hcon->type == LE_LINK) |
661 | conn->mtu = hcon->hdev->le_mtu; | ||
662 | else | ||
663 | conn->mtu = hcon->hdev->acl_mtu; | ||
664 | |||
655 | conn->src = &hcon->hdev->bdaddr; | 665 | conn->src = &hcon->hdev->bdaddr; |
656 | conn->dst = &hcon->dst; | 666 | conn->dst = &hcon->dst; |
657 | 667 | ||
@@ -758,8 +768,13 @@ int l2cap_do_connect(struct sock *sk) | |||
758 | 768 | ||
759 | auth_type = l2cap_get_auth_type(sk); | 769 | auth_type = l2cap_get_auth_type(sk); |
760 | 770 | ||
761 | hcon = hci_connect(hdev, ACL_LINK, dst, | 771 | if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA) |
772 | hcon = hci_connect(hdev, LE_LINK, dst, | ||
762 | l2cap_pi(sk)->sec_level, auth_type); | 773 | l2cap_pi(sk)->sec_level, auth_type); |
774 | else | ||
775 | hcon = hci_connect(hdev, ACL_LINK, dst, | ||
776 | l2cap_pi(sk)->sec_level, auth_type); | ||
777 | |||
763 | if (!hcon) | 778 | if (!hcon) |
764 | goto done; | 779 | goto done; |
765 | 780 | ||
@@ -3520,7 +3535,7 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) | |||
3520 | 3535 | ||
3521 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | 3536 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); |
3522 | 3537 | ||
3523 | if (hcon->type != ACL_LINK) | 3538 | if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK)) |
3524 | return -EINVAL; | 3539 | return -EINVAL; |
3525 | 3540 | ||
3526 | if (!status) { | 3541 | if (!status) { |
@@ -3549,7 +3564,7 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) | |||
3549 | { | 3564 | { |
3550 | BT_DBG("hcon %p reason %d", hcon, reason); | 3565 | BT_DBG("hcon %p reason %d", hcon, reason); |
3551 | 3566 | ||
3552 | if (hcon->type != ACL_LINK) | 3567 | if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK)) |
3553 | return -EINVAL; | 3568 | return -EINVAL; |
3554 | 3569 | ||
3555 | l2cap_conn_del(hcon, bt_err(reason)); | 3570 | l2cap_conn_del(hcon, bt_err(reason)); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 21f5385ca24d..f45d361e84d1 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -168,13 +168,13 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
168 | len = min_t(unsigned int, sizeof(la), alen); | 168 | len = min_t(unsigned int, sizeof(la), alen); |
169 | memcpy(&la, addr, len); | 169 | memcpy(&la, addr, len); |
170 | 170 | ||
171 | if (la.l2_cid) | 171 | if (la.l2_cid && la.l2_psm) |
172 | return -EINVAL; | 172 | return -EINVAL; |
173 | 173 | ||
174 | lock_sock(sk); | 174 | lock_sock(sk); |
175 | 175 | ||
176 | if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) | 176 | if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) |
177 | && !la.l2_psm) { | 177 | && !(la.l2_psm || la.l2_cid)) { |
178 | err = -EINVAL; | 178 | err = -EINVAL; |
179 | goto done; | 179 | goto done; |
180 | } | 180 | } |
@@ -216,7 +216,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
216 | 216 | ||
217 | /* PSM must be odd and lsb of upper byte must be 0 */ | 217 | /* PSM must be odd and lsb of upper byte must be 0 */ |
218 | if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 && | 218 | if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 && |
219 | sk->sk_type != SOCK_RAW) { | 219 | sk->sk_type != SOCK_RAW && !la.l2_cid) { |
220 | err = -EINVAL; | 220 | err = -EINVAL; |
221 | goto done; | 221 | goto done; |
222 | } | 222 | } |
@@ -224,6 +224,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
224 | /* Set destination address and psm */ | 224 | /* Set destination address and psm */ |
225 | bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr); | 225 | bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr); |
226 | l2cap_pi(sk)->psm = la.l2_psm; | 226 | l2cap_pi(sk)->psm = la.l2_psm; |
227 | l2cap_pi(sk)->dcid = la.l2_cid; | ||
227 | 228 | ||
228 | err = l2cap_do_connect(sk); | 229 | err = l2cap_do_connect(sk); |
229 | if (err) | 230 | if (err) |