diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-06-02 23:19:47 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-06-13 13:55:33 -0400 |
commit | 89bc500e41fc5b48e0573e6b0d927fc97b8951dc (patch) | |
tree | a140691a2c96629f86ff554dbf6677d2057b69cd | |
parent | ba3bd0ee3946d9300512e685e8d5573dfa10c060 (diff) |
Bluetooth: Add state tracking to struct l2cap_chan
Now socket state is tracked by struct sock and channel state is tracked by
chan->state. At this point both says the same, but this is going to change
when we add AMP Support for example.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | include/net/bluetooth/l2cap.h | 3 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 113 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 12 |
3 files changed, 74 insertions, 54 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 0ad61d069686..68c87244eafc 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -287,6 +287,8 @@ struct l2cap_chan { | |||
287 | 287 | ||
288 | struct l2cap_conn *conn; | 288 | struct l2cap_conn *conn; |
289 | 289 | ||
290 | __u8 state; | ||
291 | |||
290 | __le16 psm; | 292 | __le16 psm; |
291 | __u16 dcid; | 293 | __u16 dcid; |
292 | __u16 scid; | 294 | __u16 scid; |
@@ -365,6 +367,7 @@ struct l2cap_ops { | |||
365 | struct l2cap_chan *(*new_connection) (void *data); | 367 | struct l2cap_chan *(*new_connection) (void *data); |
366 | int (*recv) (void *data, struct sk_buff *skb); | 368 | int (*recv) (void *data, struct sk_buff *skb); |
367 | void (*close) (void *data); | 369 | void (*close) (void *data); |
370 | void (*state_change) (void *data, int state); | ||
368 | }; | 371 | }; |
369 | 372 | ||
370 | struct l2cap_conn { | 373 | struct l2cap_conn { |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 3a121ac6b310..58fe03abee66 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -210,27 +210,33 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) | |||
210 | 210 | ||
211 | static void l2cap_chan_set_timer(struct l2cap_chan *chan, long timeout) | 211 | static void l2cap_chan_set_timer(struct l2cap_chan *chan, long timeout) |
212 | { | 212 | { |
213 | BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->sk->sk_state, | 213 | BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout); |
214 | timeout); | 214 | |
215 | if (!mod_timer(&chan->chan_timer, jiffies + timeout)) | 215 | if (!mod_timer(&chan->chan_timer, jiffies + timeout)) |
216 | sock_hold(chan->sk); | 216 | sock_hold(chan->sk); |
217 | } | 217 | } |
218 | 218 | ||
219 | static void l2cap_chan_clear_timer(struct l2cap_chan *chan) | 219 | static void l2cap_chan_clear_timer(struct l2cap_chan *chan) |
220 | { | 220 | { |
221 | BT_DBG("chan %p state %d", chan, chan->sk->sk_state); | 221 | BT_DBG("chan %p state %d", chan, chan->state); |
222 | 222 | ||
223 | if (timer_pending(&chan->chan_timer) && del_timer(&chan->chan_timer)) | 223 | if (timer_pending(&chan->chan_timer) && del_timer(&chan->chan_timer)) |
224 | __sock_put(chan->sk); | 224 | __sock_put(chan->sk); |
225 | } | 225 | } |
226 | 226 | ||
227 | static void l2cap_state_change(struct l2cap_chan *chan, int state) | ||
228 | { | ||
229 | chan->state = state; | ||
230 | chan->ops->state_change(chan->data, state); | ||
231 | } | ||
232 | |||
227 | static void l2cap_chan_timeout(unsigned long arg) | 233 | static void l2cap_chan_timeout(unsigned long arg) |
228 | { | 234 | { |
229 | struct l2cap_chan *chan = (struct l2cap_chan *) arg; | 235 | struct l2cap_chan *chan = (struct l2cap_chan *) arg; |
230 | struct sock *sk = chan->sk; | 236 | struct sock *sk = chan->sk; |
231 | int reason; | 237 | int reason; |
232 | 238 | ||
233 | BT_DBG("chan %p state %d", chan, sk->sk_state); | 239 | BT_DBG("chan %p state %d", chan, chan->state); |
234 | 240 | ||
235 | bh_lock_sock(sk); | 241 | bh_lock_sock(sk); |
236 | 242 | ||
@@ -242,9 +248,9 @@ static void l2cap_chan_timeout(unsigned long arg) | |||
242 | return; | 248 | return; |
243 | } | 249 | } |
244 | 250 | ||
245 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) | 251 | if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) |
246 | reason = ECONNREFUSED; | 252 | reason = ECONNREFUSED; |
247 | else if (sk->sk_state == BT_CONNECT && | 253 | else if (chan->state == BT_CONNECT && |
248 | chan->sec_level != BT_SECURITY_SDP) | 254 | chan->sec_level != BT_SECURITY_SDP) |
249 | reason = ECONNREFUSED; | 255 | reason = ECONNREFUSED; |
250 | else | 256 | else |
@@ -274,6 +280,8 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk) | |||
274 | 280 | ||
275 | setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan); | 281 | setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan); |
276 | 282 | ||
283 | chan->state = BT_OPEN; | ||
284 | |||
277 | return chan; | 285 | return chan; |
278 | } | 286 | } |
279 | 287 | ||
@@ -348,7 +356,7 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
348 | hci_conn_put(conn->hcon); | 356 | hci_conn_put(conn->hcon); |
349 | } | 357 | } |
350 | 358 | ||
351 | sk->sk_state = BT_CLOSED; | 359 | l2cap_state_change(chan, BT_CLOSED); |
352 | sock_set_flag(sk, SOCK_ZAPPED); | 360 | sock_set_flag(sk, SOCK_ZAPPED); |
353 | 361 | ||
354 | if (err) | 362 | if (err) |
@@ -398,9 +406,6 @@ static void l2cap_chan_cleanup_listen(struct sock *parent) | |||
398 | release_sock(sk); | 406 | release_sock(sk); |
399 | chan->ops->close(chan->data); | 407 | chan->ops->close(chan->data); |
400 | } | 408 | } |
401 | |||
402 | parent->sk_state = BT_CLOSED; | ||
403 | sock_set_flag(parent, SOCK_ZAPPED); | ||
404 | } | 409 | } |
405 | 410 | ||
406 | void l2cap_chan_close(struct l2cap_chan *chan, int reason) | 411 | void l2cap_chan_close(struct l2cap_chan *chan, int reason) |
@@ -408,11 +413,14 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
408 | struct l2cap_conn *conn = chan->conn; | 413 | struct l2cap_conn *conn = chan->conn; |
409 | struct sock *sk = chan->sk; | 414 | struct sock *sk = chan->sk; |
410 | 415 | ||
411 | BT_DBG("chan %p state %d socket %p", chan, sk->sk_state, sk->sk_socket); | 416 | BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket); |
412 | 417 | ||
413 | switch (sk->sk_state) { | 418 | switch (chan->state) { |
414 | case BT_LISTEN: | 419 | case BT_LISTEN: |
415 | l2cap_chan_cleanup_listen(sk); | 420 | l2cap_chan_cleanup_listen(sk); |
421 | |||
422 | l2cap_state_change(chan, BT_CLOSED); | ||
423 | sock_set_flag(sk, SOCK_ZAPPED); | ||
416 | break; | 424 | break; |
417 | 425 | ||
418 | case BT_CONNECTED: | 426 | case BT_CONNECTED: |
@@ -436,7 +444,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
436 | result = L2CAP_CR_SEC_BLOCK; | 444 | result = L2CAP_CR_SEC_BLOCK; |
437 | else | 445 | else |
438 | result = L2CAP_CR_BAD_PSM; | 446 | result = L2CAP_CR_BAD_PSM; |
439 | sk->sk_state = BT_DISCONN; | 447 | l2cap_state_change(chan, BT_DISCONN); |
440 | 448 | ||
441 | rsp.scid = cpu_to_le16(chan->dcid); | 449 | rsp.scid = cpu_to_le16(chan->dcid); |
442 | rsp.dcid = cpu_to_le16(chan->scid); | 450 | rsp.dcid = cpu_to_le16(chan->scid); |
@@ -548,13 +556,11 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) | |||
548 | { | 556 | { |
549 | struct sk_buff *skb; | 557 | struct sk_buff *skb; |
550 | struct l2cap_hdr *lh; | 558 | struct l2cap_hdr *lh; |
551 | struct l2cap_pinfo *pi = l2cap_pi(chan->sk); | ||
552 | struct l2cap_conn *conn = chan->conn; | 559 | struct l2cap_conn *conn = chan->conn; |
553 | struct sock *sk = (struct sock *)pi; | ||
554 | int count, hlen = L2CAP_HDR_SIZE + 2; | 560 | int count, hlen = L2CAP_HDR_SIZE + 2; |
555 | u8 flags; | 561 | u8 flags; |
556 | 562 | ||
557 | if (sk->sk_state != BT_CONNECTED) | 563 | if (chan->state != BT_CONNECTED) |
558 | return; | 564 | return; |
559 | 565 | ||
560 | if (chan->fcs == L2CAP_FCS_CRC16) | 566 | if (chan->fcs == L2CAP_FCS_CRC16) |
@@ -689,7 +695,7 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c | |||
689 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | 695 | l2cap_send_cmd(conn, l2cap_get_ident(conn), |
690 | L2CAP_DISCONN_REQ, sizeof(req), &req); | 696 | L2CAP_DISCONN_REQ, sizeof(req), &req); |
691 | 697 | ||
692 | sk->sk_state = BT_DISCONN; | 698 | l2cap_state_change(chan, BT_DISCONN); |
693 | sk->sk_err = err; | 699 | sk->sk_err = err; |
694 | } | 700 | } |
695 | 701 | ||
@@ -712,7 +718,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
712 | continue; | 718 | continue; |
713 | } | 719 | } |
714 | 720 | ||
715 | if (sk->sk_state == BT_CONNECT) { | 721 | if (chan->state == BT_CONNECT) { |
716 | struct l2cap_conn_req req; | 722 | struct l2cap_conn_req req; |
717 | 723 | ||
718 | if (!l2cap_check_security(chan) || | 724 | if (!l2cap_check_security(chan) || |
@@ -728,7 +734,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
728 | /* l2cap_chan_close() calls list_del(chan) | 734 | /* l2cap_chan_close() calls list_del(chan) |
729 | * so release the lock */ | 735 | * so release the lock */ |
730 | read_unlock_bh(&conn->chan_lock); | 736 | read_unlock_bh(&conn->chan_lock); |
731 | l2cap_chan_close(chan, ECONNRESET); | 737 | l2cap_chan_close(chan, ECONNRESET); |
732 | read_lock_bh(&conn->chan_lock); | 738 | read_lock_bh(&conn->chan_lock); |
733 | bh_unlock_sock(sk); | 739 | bh_unlock_sock(sk); |
734 | continue; | 740 | continue; |
@@ -743,7 +749,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
743 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, | 749 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, |
744 | sizeof(req), &req); | 750 | sizeof(req), &req); |
745 | 751 | ||
746 | } else if (sk->sk_state == BT_CONNECT2) { | 752 | } else if (chan->state == BT_CONNECT2) { |
747 | struct l2cap_conn_rsp rsp; | 753 | struct l2cap_conn_rsp rsp; |
748 | char buf[128]; | 754 | char buf[128]; |
749 | rsp.scid = cpu_to_le16(chan->dcid); | 755 | rsp.scid = cpu_to_le16(chan->dcid); |
@@ -757,7 +763,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
757 | parent->sk_data_ready(parent, 0); | 763 | parent->sk_data_ready(parent, 0); |
758 | 764 | ||
759 | } else { | 765 | } else { |
760 | sk->sk_state = BT_CONFIG; | 766 | l2cap_state_change(chan, BT_CONFIG); |
761 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); | 767 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); |
762 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); | 768 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
763 | } | 769 | } |
@@ -799,7 +805,7 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdadd | |||
799 | list_for_each_entry(c, &chan_list, global_l) { | 805 | list_for_each_entry(c, &chan_list, global_l) { |
800 | struct sock *sk = c->sk; | 806 | struct sock *sk = c->sk; |
801 | 807 | ||
802 | if (state && sk->sk_state != state) | 808 | if (state && c->state != state) |
803 | continue; | 809 | continue; |
804 | 810 | ||
805 | if (c->scid == cid) { | 811 | if (c->scid == cid) { |
@@ -862,7 +868,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
862 | 868 | ||
863 | l2cap_chan_set_timer(chan, sk->sk_sndtimeo); | 869 | l2cap_chan_set_timer(chan, sk->sk_sndtimeo); |
864 | 870 | ||
865 | sk->sk_state = BT_CONNECTED; | 871 | l2cap_state_change(chan, BT_CONNECTED); |
866 | parent->sk_data_ready(parent, 0); | 872 | parent->sk_data_ready(parent, 0); |
867 | 873 | ||
868 | write_unlock_bh(&conn->chan_lock); | 874 | write_unlock_bh(&conn->chan_lock); |
@@ -889,15 +895,15 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
889 | 895 | ||
890 | if (conn->hcon->type == LE_LINK) { | 896 | if (conn->hcon->type == LE_LINK) { |
891 | l2cap_chan_clear_timer(chan); | 897 | l2cap_chan_clear_timer(chan); |
892 | sk->sk_state = BT_CONNECTED; | 898 | l2cap_state_change(chan, BT_CONNECTED); |
893 | sk->sk_state_change(sk); | 899 | sk->sk_state_change(sk); |
894 | } | 900 | } |
895 | 901 | ||
896 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 902 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
897 | l2cap_chan_clear_timer(chan); | 903 | l2cap_chan_clear_timer(chan); |
898 | sk->sk_state = BT_CONNECTED; | 904 | l2cap_state_change(chan, BT_CONNECTED); |
899 | sk->sk_state_change(sk); | 905 | sk->sk_state_change(sk); |
900 | } else if (sk->sk_state == BT_CONNECT) | 906 | } else if (chan->state == BT_CONNECT) |
901 | l2cap_do_start(chan); | 907 | l2cap_do_start(chan); |
902 | 908 | ||
903 | bh_unlock_sock(sk); | 909 | bh_unlock_sock(sk); |
@@ -1025,7 +1031,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr | |||
1025 | list_for_each_entry(c, &chan_list, global_l) { | 1031 | list_for_each_entry(c, &chan_list, global_l) { |
1026 | struct sock *sk = c->sk; | 1032 | struct sock *sk = c->sk; |
1027 | 1033 | ||
1028 | if (state && sk->sk_state != state) | 1034 | if (state && c->state != state) |
1029 | continue; | 1035 | continue; |
1030 | 1036 | ||
1031 | if (c->psm == psm) { | 1037 | if (c->psm == psm) { |
@@ -1092,14 +1098,14 @@ int l2cap_chan_connect(struct l2cap_chan *chan) | |||
1092 | 1098 | ||
1093 | l2cap_chan_add(conn, chan); | 1099 | l2cap_chan_add(conn, chan); |
1094 | 1100 | ||
1095 | sk->sk_state = BT_CONNECT; | 1101 | l2cap_state_change(chan, BT_CONNECT); |
1096 | l2cap_chan_set_timer(chan, sk->sk_sndtimeo); | 1102 | l2cap_chan_set_timer(chan, sk->sk_sndtimeo); |
1097 | 1103 | ||
1098 | if (hcon->state == BT_CONNECTED) { | 1104 | if (hcon->state == BT_CONNECTED) { |
1099 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 1105 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
1100 | l2cap_chan_clear_timer(chan); | 1106 | l2cap_chan_clear_timer(chan); |
1101 | if (l2cap_check_security(chan)) | 1107 | if (l2cap_check_security(chan)) |
1102 | sk->sk_state = BT_CONNECTED; | 1108 | l2cap_state_change(chan, BT_CONNECTED); |
1103 | } else | 1109 | } else |
1104 | l2cap_do_start(chan); | 1110 | l2cap_do_start(chan); |
1105 | } | 1111 | } |
@@ -1288,11 +1294,10 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) | |||
1288 | int l2cap_ertm_send(struct l2cap_chan *chan) | 1294 | int l2cap_ertm_send(struct l2cap_chan *chan) |
1289 | { | 1295 | { |
1290 | struct sk_buff *skb, *tx_skb; | 1296 | struct sk_buff *skb, *tx_skb; |
1291 | struct sock *sk = chan->sk; | ||
1292 | u16 control, fcs; | 1297 | u16 control, fcs; |
1293 | int nsent = 0; | 1298 | int nsent = 0; |
1294 | 1299 | ||
1295 | if (sk->sk_state != BT_CONNECTED) | 1300 | if (chan->state != BT_CONNECTED) |
1296 | return -ENOTCONN; | 1301 | return -ENOTCONN; |
1297 | 1302 | ||
1298 | while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { | 1303 | while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { |
@@ -1668,7 +1673,7 @@ static void l2cap_chan_ready(struct sock *sk) | |||
1668 | /* Outgoing channel. | 1673 | /* Outgoing channel. |
1669 | * Wake up socket sleeping on connect. | 1674 | * Wake up socket sleeping on connect. |
1670 | */ | 1675 | */ |
1671 | sk->sk_state = BT_CONNECTED; | 1676 | l2cap_state_change(chan, BT_CONNECTED); |
1672 | sk->sk_state_change(sk); | 1677 | sk->sk_state_change(sk); |
1673 | } else { | 1678 | } else { |
1674 | /* Incoming channel. | 1679 | /* Incoming channel. |
@@ -2364,22 +2369,22 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2364 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { | 2369 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { |
2365 | if (l2cap_check_security(chan)) { | 2370 | if (l2cap_check_security(chan)) { |
2366 | if (bt_sk(sk)->defer_setup) { | 2371 | if (bt_sk(sk)->defer_setup) { |
2367 | sk->sk_state = BT_CONNECT2; | 2372 | l2cap_state_change(chan, BT_CONNECT2); |
2368 | result = L2CAP_CR_PEND; | 2373 | result = L2CAP_CR_PEND; |
2369 | status = L2CAP_CS_AUTHOR_PEND; | 2374 | status = L2CAP_CS_AUTHOR_PEND; |
2370 | parent->sk_data_ready(parent, 0); | 2375 | parent->sk_data_ready(parent, 0); |
2371 | } else { | 2376 | } else { |
2372 | sk->sk_state = BT_CONFIG; | 2377 | l2cap_state_change(chan, BT_CONFIG); |
2373 | result = L2CAP_CR_SUCCESS; | 2378 | result = L2CAP_CR_SUCCESS; |
2374 | status = L2CAP_CS_NO_INFO; | 2379 | status = L2CAP_CS_NO_INFO; |
2375 | } | 2380 | } |
2376 | } else { | 2381 | } else { |
2377 | sk->sk_state = BT_CONNECT2; | 2382 | l2cap_state_change(chan, BT_CONNECT2); |
2378 | result = L2CAP_CR_PEND; | 2383 | result = L2CAP_CR_PEND; |
2379 | status = L2CAP_CS_AUTHEN_PEND; | 2384 | status = L2CAP_CS_AUTHEN_PEND; |
2380 | } | 2385 | } |
2381 | } else { | 2386 | } else { |
2382 | sk->sk_state = BT_CONNECT2; | 2387 | l2cap_state_change(chan, BT_CONNECT2); |
2383 | result = L2CAP_CR_PEND; | 2388 | result = L2CAP_CR_PEND; |
2384 | status = L2CAP_CS_NO_INFO; | 2389 | status = L2CAP_CS_NO_INFO; |
2385 | } | 2390 | } |
@@ -2451,7 +2456,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2451 | 2456 | ||
2452 | switch (result) { | 2457 | switch (result) { |
2453 | case L2CAP_CR_SUCCESS: | 2458 | case L2CAP_CR_SUCCESS: |
2454 | sk->sk_state = BT_CONFIG; | 2459 | l2cap_state_change(chan, BT_CONFIG); |
2455 | chan->ident = 0; | 2460 | chan->ident = 0; |
2456 | chan->dcid = dcid; | 2461 | chan->dcid = dcid; |
2457 | chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND; | 2462 | chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND; |
@@ -2473,7 +2478,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2473 | default: | 2478 | default: |
2474 | /* don't delete l2cap channel if sk is owned by user */ | 2479 | /* don't delete l2cap channel if sk is owned by user */ |
2475 | if (sock_owned_by_user(sk)) { | 2480 | if (sock_owned_by_user(sk)) { |
2476 | sk->sk_state = BT_DISCONN; | 2481 | l2cap_state_change(chan, BT_DISCONN); |
2477 | l2cap_chan_clear_timer(chan); | 2482 | l2cap_chan_clear_timer(chan); |
2478 | l2cap_chan_set_timer(chan, HZ / 5); | 2483 | l2cap_chan_set_timer(chan, HZ / 5); |
2479 | break; | 2484 | break; |
@@ -2520,7 +2525,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2520 | 2525 | ||
2521 | sk = chan->sk; | 2526 | sk = chan->sk; |
2522 | 2527 | ||
2523 | if (sk->sk_state != BT_CONFIG) { | 2528 | if (chan->state != BT_CONFIG) { |
2524 | struct l2cap_cmd_rej rej; | 2529 | struct l2cap_cmd_rej rej; |
2525 | 2530 | ||
2526 | rej.reason = cpu_to_le16(0x0002); | 2531 | rej.reason = cpu_to_le16(0x0002); |
@@ -2569,7 +2574,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2569 | if (chan->conf_state & L2CAP_CONF_INPUT_DONE) { | 2574 | if (chan->conf_state & L2CAP_CONF_INPUT_DONE) { |
2570 | set_default_fcs(chan); | 2575 | set_default_fcs(chan); |
2571 | 2576 | ||
2572 | sk->sk_state = BT_CONNECTED; | 2577 | l2cap_state_change(chan, BT_CONNECTED); |
2573 | 2578 | ||
2574 | chan->next_tx_seq = 0; | 2579 | chan->next_tx_seq = 0; |
2575 | chan->expected_tx_seq = 0; | 2580 | chan->expected_tx_seq = 0; |
@@ -2661,7 +2666,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2661 | if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) { | 2666 | if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) { |
2662 | set_default_fcs(chan); | 2667 | set_default_fcs(chan); |
2663 | 2668 | ||
2664 | sk->sk_state = BT_CONNECTED; | 2669 | l2cap_state_change(chan, BT_CONNECTED); |
2665 | chan->next_tx_seq = 0; | 2670 | chan->next_tx_seq = 0; |
2666 | chan->expected_tx_seq = 0; | 2671 | chan->expected_tx_seq = 0; |
2667 | skb_queue_head_init(&chan->tx_q); | 2672 | skb_queue_head_init(&chan->tx_q); |
@@ -2703,7 +2708,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
2703 | 2708 | ||
2704 | /* don't delete l2cap channel if sk is owned by user */ | 2709 | /* don't delete l2cap channel if sk is owned by user */ |
2705 | if (sock_owned_by_user(sk)) { | 2710 | if (sock_owned_by_user(sk)) { |
2706 | sk->sk_state = BT_DISCONN; | 2711 | l2cap_state_change(chan, BT_DISCONN); |
2707 | l2cap_chan_clear_timer(chan); | 2712 | l2cap_chan_clear_timer(chan); |
2708 | l2cap_chan_set_timer(chan, HZ / 5); | 2713 | l2cap_chan_set_timer(chan, HZ / 5); |
2709 | bh_unlock_sock(sk); | 2714 | bh_unlock_sock(sk); |
@@ -2737,7 +2742,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
2737 | 2742 | ||
2738 | /* don't delete l2cap channel if sk is owned by user */ | 2743 | /* don't delete l2cap channel if sk is owned by user */ |
2739 | if (sock_owned_by_user(sk)) { | 2744 | if (sock_owned_by_user(sk)) { |
2740 | sk->sk_state = BT_DISCONN; | 2745 | l2cap_state_change(chan,BT_DISCONN); |
2741 | l2cap_chan_clear_timer(chan); | 2746 | l2cap_chan_clear_timer(chan); |
2742 | l2cap_chan_set_timer(chan, HZ / 5); | 2747 | l2cap_chan_set_timer(chan, HZ / 5); |
2743 | bh_unlock_sock(sk); | 2748 | bh_unlock_sock(sk); |
@@ -3874,7 +3879,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3874 | 3879 | ||
3875 | BT_DBG("chan %p, len %d", chan, skb->len); | 3880 | BT_DBG("chan %p, len %d", chan, skb->len); |
3876 | 3881 | ||
3877 | if (sk->sk_state != BT_CONNECTED) | 3882 | if (chan->state != BT_CONNECTED) |
3878 | goto drop; | 3883 | goto drop; |
3879 | 3884 | ||
3880 | switch (chan->mode) { | 3885 | switch (chan->mode) { |
@@ -3959,7 +3964,7 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str | |||
3959 | 3964 | ||
3960 | BT_DBG("sk %p, len %d", sk, skb->len); | 3965 | BT_DBG("sk %p, len %d", sk, skb->len); |
3961 | 3966 | ||
3962 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) | 3967 | if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) |
3963 | goto drop; | 3968 | goto drop; |
3964 | 3969 | ||
3965 | if (l2cap_pi(sk)->chan->imtu < skb->len) | 3970 | if (l2cap_pi(sk)->chan->imtu < skb->len) |
@@ -3992,7 +3997,7 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct | |||
3992 | 3997 | ||
3993 | BT_DBG("sk %p, len %d", sk, skb->len); | 3998 | BT_DBG("sk %p, len %d", sk, skb->len); |
3994 | 3999 | ||
3995 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) | 4000 | if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) |
3996 | goto drop; | 4001 | goto drop; |
3997 | 4002 | ||
3998 | if (l2cap_pi(sk)->chan->imtu < skb->len) | 4003 | if (l2cap_pi(sk)->chan->imtu < skb->len) |
@@ -4066,7 +4071,7 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
4066 | list_for_each_entry(c, &chan_list, global_l) { | 4071 | list_for_each_entry(c, &chan_list, global_l) { |
4067 | struct sock *sk = c->sk; | 4072 | struct sock *sk = c->sk; |
4068 | 4073 | ||
4069 | if (sk->sk_state != BT_LISTEN) | 4074 | if (c->state != BT_LISTEN) |
4070 | continue; | 4075 | continue; |
4071 | 4076 | ||
4072 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { | 4077 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { |
@@ -4167,14 +4172,14 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4167 | continue; | 4172 | continue; |
4168 | } | 4173 | } |
4169 | 4174 | ||
4170 | if (!status && (sk->sk_state == BT_CONNECTED || | 4175 | if (!status && (chan->state == BT_CONNECTED || |
4171 | sk->sk_state == BT_CONFIG)) { | 4176 | chan->state == BT_CONFIG)) { |
4172 | l2cap_check_encryption(chan, encrypt); | 4177 | l2cap_check_encryption(chan, encrypt); |
4173 | bh_unlock_sock(sk); | 4178 | bh_unlock_sock(sk); |
4174 | continue; | 4179 | continue; |
4175 | } | 4180 | } |
4176 | 4181 | ||
4177 | if (sk->sk_state == BT_CONNECT) { | 4182 | if (chan->state == BT_CONNECT) { |
4178 | if (!status) { | 4183 | if (!status) { |
4179 | struct l2cap_conn_req req; | 4184 | struct l2cap_conn_req req; |
4180 | req.scid = cpu_to_le16(chan->scid); | 4185 | req.scid = cpu_to_le16(chan->scid); |
@@ -4189,15 +4194,15 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4189 | l2cap_chan_clear_timer(chan); | 4194 | l2cap_chan_clear_timer(chan); |
4190 | l2cap_chan_set_timer(chan, HZ / 10); | 4195 | l2cap_chan_set_timer(chan, HZ / 10); |
4191 | } | 4196 | } |
4192 | } else if (sk->sk_state == BT_CONNECT2) { | 4197 | } else if (chan->state == BT_CONNECT2) { |
4193 | struct l2cap_conn_rsp rsp; | 4198 | struct l2cap_conn_rsp rsp; |
4194 | __u16 result; | 4199 | __u16 result; |
4195 | 4200 | ||
4196 | if (!status) { | 4201 | if (!status) { |
4197 | sk->sk_state = BT_CONFIG; | 4202 | l2cap_state_change(chan, BT_CONFIG); |
4198 | result = L2CAP_CR_SUCCESS; | 4203 | result = L2CAP_CR_SUCCESS; |
4199 | } else { | 4204 | } else { |
4200 | sk->sk_state = BT_DISCONN; | 4205 | l2cap_state_change(chan, BT_DISCONN); |
4201 | l2cap_chan_set_timer(chan, HZ / 10); | 4206 | l2cap_chan_set_timer(chan, HZ / 10); |
4202 | result = L2CAP_CR_SEC_BLOCK; | 4207 | result = L2CAP_CR_SEC_BLOCK; |
4203 | } | 4208 | } |
@@ -4341,7 +4346,7 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) | |||
4341 | seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", | 4346 | seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", |
4342 | batostr(&bt_sk(sk)->src), | 4347 | batostr(&bt_sk(sk)->src), |
4343 | batostr(&bt_sk(sk)->dst), | 4348 | batostr(&bt_sk(sk)->dst), |
4344 | sk->sk_state, __le16_to_cpu(c->psm), | 4349 | c->state, __le16_to_cpu(c->psm), |
4345 | c->scid, c->dcid, c->imtu, c->omtu, | 4350 | c->scid, c->dcid, c->imtu, c->omtu, |
4346 | c->sec_level, c->mode); | 4351 | c->sec_level, c->mode); |
4347 | } | 4352 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 9f15a164993a..1d9c36509d7b 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -89,6 +89,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
89 | chan->sec_level = BT_SECURITY_SDP; | 89 | chan->sec_level = BT_SECURITY_SDP; |
90 | 90 | ||
91 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); | 91 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); |
92 | |||
93 | chan->state = BT_BOUND; | ||
92 | sk->sk_state = BT_BOUND; | 94 | sk->sk_state = BT_BOUND; |
93 | 95 | ||
94 | done: | 96 | done: |
@@ -214,6 +216,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) | |||
214 | 216 | ||
215 | sk->sk_max_ack_backlog = backlog; | 217 | sk->sk_max_ack_backlog = backlog; |
216 | sk->sk_ack_backlog = 0; | 218 | sk->sk_ack_backlog = 0; |
219 | |||
220 | chan->state = BT_LISTEN; | ||
217 | sk->sk_state = BT_LISTEN; | 221 | sk->sk_state = BT_LISTEN; |
218 | 222 | ||
219 | done: | 223 | done: |
@@ -803,11 +807,19 @@ static void l2cap_sock_close_cb(void *data) | |||
803 | l2cap_sock_kill(sk); | 807 | l2cap_sock_kill(sk); |
804 | } | 808 | } |
805 | 809 | ||
810 | static void l2cap_sock_state_change_cb(void *data, int state) | ||
811 | { | ||
812 | struct sock *sk = data; | ||
813 | |||
814 | sk->sk_state = state; | ||
815 | } | ||
816 | |||
806 | static struct l2cap_ops l2cap_chan_ops = { | 817 | static struct l2cap_ops l2cap_chan_ops = { |
807 | .name = "L2CAP Socket Interface", | 818 | .name = "L2CAP Socket Interface", |
808 | .new_connection = l2cap_sock_new_connection_cb, | 819 | .new_connection = l2cap_sock_new_connection_cb, |
809 | .recv = l2cap_sock_recv_cb, | 820 | .recv = l2cap_sock_recv_cb, |
810 | .close = l2cap_sock_close_cb, | 821 | .close = l2cap_sock_close_cb, |
822 | .state_change = l2cap_sock_state_change_cb, | ||
811 | }; | 823 | }; |
812 | 824 | ||
813 | static void l2cap_sock_destruct(struct sock *sk) | 825 | static void l2cap_sock_destruct(struct sock *sk) |