diff options
Diffstat (limited to 'net/nfc/llcp')
-rw-r--r-- | net/nfc/llcp/commands.c | 4 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.c | 7 | ||||
-rw-r--r-- | net/nfc/llcp/sock.c | 57 |
3 files changed, 64 insertions, 4 deletions
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index 11a3b7d98dc5..bf8ae4f0b90c 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -488,7 +488,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
488 | 488 | ||
489 | memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len); | 489 | memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len); |
490 | 490 | ||
491 | skb_queue_head(&sock->tx_queue, pdu); | 491 | skb_queue_tail(&sock->tx_queue, pdu); |
492 | 492 | ||
493 | lock_sock(sk); | 493 | lock_sock(sk); |
494 | 494 | ||
@@ -502,7 +502,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
502 | 502 | ||
503 | kfree(msg_data); | 503 | kfree(msg_data); |
504 | 504 | ||
505 | return 0; | 505 | return len; |
506 | } | 506 | } |
507 | 507 | ||
508 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) | 508 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 92988aa620dc..42994fac26d6 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -448,6 +448,8 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | |||
448 | { | 448 | { |
449 | struct nfc_llcp_sock *sock, *llcp_sock, *n; | 449 | struct nfc_llcp_sock *sock, *llcp_sock, *n; |
450 | 450 | ||
451 | pr_debug("ssap dsap %d %d\n", ssap, dsap); | ||
452 | |||
451 | if (ssap == 0 && dsap == 0) | 453 | if (ssap == 0 && dsap == 0) |
452 | return NULL; | 454 | return NULL; |
453 | 455 | ||
@@ -783,6 +785,7 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, | |||
783 | static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | 785 | static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) |
784 | { | 786 | { |
785 | struct nfc_llcp_sock *llcp_sock; | 787 | struct nfc_llcp_sock *llcp_sock; |
788 | struct sock *sk; | ||
786 | u8 dsap, ssap; | 789 | u8 dsap, ssap; |
787 | 790 | ||
788 | dsap = nfc_llcp_dsap(skb); | 791 | dsap = nfc_llcp_dsap(skb); |
@@ -801,10 +804,14 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
801 | } | 804 | } |
802 | 805 | ||
803 | llcp_sock->dsap = ssap; | 806 | llcp_sock->dsap = ssap; |
807 | sk = &llcp_sock->sk; | ||
804 | 808 | ||
805 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | 809 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], |
806 | skb->len - LLCP_HEADER_SIZE); | 810 | skb->len - LLCP_HEADER_SIZE); |
807 | 811 | ||
812 | sk->sk_state = LLCP_CONNECTED; | ||
813 | sk->sk_state_change(sk); | ||
814 | |||
808 | nfc_llcp_sock_put(llcp_sock); | 815 | nfc_llcp_sock_put(llcp_sock); |
809 | } | 816 | } |
810 | 817 | ||
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index c13e02ebdef9..3f339b19d140 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -27,6 +27,42 @@ | |||
27 | #include "../nfc.h" | 27 | #include "../nfc.h" |
28 | #include "llcp.h" | 28 | #include "llcp.h" |
29 | 29 | ||
30 | static int sock_wait_state(struct sock *sk, int state, unsigned long timeo) | ||
31 | { | ||
32 | DECLARE_WAITQUEUE(wait, current); | ||
33 | int err = 0; | ||
34 | |||
35 | pr_debug("sk %p", sk); | ||
36 | |||
37 | add_wait_queue(sk_sleep(sk), &wait); | ||
38 | set_current_state(TASK_INTERRUPTIBLE); | ||
39 | |||
40 | while (sk->sk_state != state) { | ||
41 | if (!timeo) { | ||
42 | err = -EINPROGRESS; | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | if (signal_pending(current)) { | ||
47 | err = sock_intr_errno(timeo); | ||
48 | break; | ||
49 | } | ||
50 | |||
51 | release_sock(sk); | ||
52 | timeo = schedule_timeout(timeo); | ||
53 | lock_sock(sk); | ||
54 | set_current_state(TASK_INTERRUPTIBLE); | ||
55 | |||
56 | err = sock_error(sk); | ||
57 | if (err) | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | __set_current_state(TASK_RUNNING); | ||
62 | remove_wait_queue(sk_sleep(sk), &wait); | ||
63 | return err; | ||
64 | } | ||
65 | |||
30 | static struct proto llcp_sock_proto = { | 66 | static struct proto llcp_sock_proto = { |
31 | .name = "NFC_LLCP", | 67 | .name = "NFC_LLCP", |
32 | .owner = THIS_MODULE, | 68 | .owner = THIS_MODULE, |
@@ -304,11 +340,24 @@ static unsigned int llcp_sock_poll(struct file *file, struct socket *sock, | |||
304 | mask |= POLLERR; | 340 | mask |= POLLERR; |
305 | 341 | ||
306 | if (!skb_queue_empty(&sk->sk_receive_queue)) | 342 | if (!skb_queue_empty(&sk->sk_receive_queue)) |
307 | mask |= POLLIN; | 343 | mask |= POLLIN | POLLRDNORM; |
308 | 344 | ||
309 | if (sk->sk_state == LLCP_CLOSED) | 345 | if (sk->sk_state == LLCP_CLOSED) |
310 | mask |= POLLHUP; | 346 | mask |= POLLHUP; |
311 | 347 | ||
348 | if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
349 | mask |= POLLRDHUP | POLLIN | POLLRDNORM; | ||
350 | |||
351 | if (sk->sk_shutdown == SHUTDOWN_MASK) | ||
352 | mask |= POLLHUP; | ||
353 | |||
354 | if (sock_writeable(sk)) | ||
355 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | ||
356 | else | ||
357 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | ||
358 | |||
359 | pr_debug("mask 0x%x\n", mask); | ||
360 | |||
312 | return mask; | 361 | return mask; |
313 | } | 362 | } |
314 | 363 | ||
@@ -462,9 +511,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
462 | if (ret) | 511 | if (ret) |
463 | goto put_dev; | 512 | goto put_dev; |
464 | 513 | ||
465 | sk->sk_state = LLCP_CONNECTED; | 514 | ret = sock_wait_state(sk, LLCP_CONNECTED, |
515 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | ||
516 | if (ret) | ||
517 | goto put_dev; | ||
466 | 518 | ||
467 | release_sock(sk); | 519 | release_sock(sk); |
520 | |||
468 | return 0; | 521 | return 0; |
469 | 522 | ||
470 | put_dev: | 523 | put_dev: |