diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2012-06-26 10:13:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-07-09 16:42:20 -0400 |
commit | 5c0560b7a5c662ce5fef6ddd52f7bc8d38ad1907 (patch) | |
tree | c3ab7675d243ff884a59271463c089daa5654930 /net/nfc/llcp | |
parent | 8f50020ed9b81ba909ce9573f9d05263cdebf502 (diff) |
NFC: Handle LLCP Disconnected Mode frames
When receiving such frame, the sockets waiting for a connection to finish
should be woken up. Connecting to an unbound LLCP service will trigger a
DM as a response.
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc/llcp')
-rw-r--r-- | net/nfc/llcp/llcp.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 6094a2099bd6..f3bc0a9efb37 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -958,6 +958,45 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
958 | nfc_llcp_sock_put(llcp_sock); | 958 | nfc_llcp_sock_put(llcp_sock); |
959 | } | 959 | } |
960 | 960 | ||
961 | static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) | ||
962 | { | ||
963 | struct nfc_llcp_sock *llcp_sock; | ||
964 | struct sock *sk; | ||
965 | u8 dsap, ssap, reason; | ||
966 | |||
967 | dsap = nfc_llcp_dsap(skb); | ||
968 | ssap = nfc_llcp_ssap(skb); | ||
969 | reason = skb->data[2]; | ||
970 | |||
971 | pr_debug("%d %d reason %d\n", ssap, dsap, reason); | ||
972 | |||
973 | switch (reason) { | ||
974 | case LLCP_DM_NOBOUND: | ||
975 | case LLCP_DM_REJ: | ||
976 | llcp_sock = nfc_llcp_connecting_sock_get(local, dsap); | ||
977 | break; | ||
978 | |||
979 | default: | ||
980 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | ||
981 | break; | ||
982 | } | ||
983 | |||
984 | if (llcp_sock == NULL) { | ||
985 | pr_err("Invalid DM\n"); | ||
986 | return; | ||
987 | } | ||
988 | |||
989 | sk = &llcp_sock->sk; | ||
990 | |||
991 | sk->sk_err = ENXIO; | ||
992 | sk->sk_state = LLCP_CLOSED; | ||
993 | sk->sk_state_change(sk); | ||
994 | |||
995 | nfc_llcp_sock_put(llcp_sock); | ||
996 | |||
997 | return; | ||
998 | } | ||
999 | |||
961 | static void nfc_llcp_rx_work(struct work_struct *work) | 1000 | static void nfc_llcp_rx_work(struct work_struct *work) |
962 | { | 1001 | { |
963 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | 1002 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, |
@@ -1001,6 +1040,11 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1001 | nfc_llcp_recv_cc(local, skb); | 1040 | nfc_llcp_recv_cc(local, skb); |
1002 | break; | 1041 | break; |
1003 | 1042 | ||
1043 | case LLCP_PDU_DM: | ||
1044 | pr_debug("DM\n"); | ||
1045 | nfc_llcp_recv_dm(local, skb); | ||
1046 | break; | ||
1047 | |||
1004 | case LLCP_PDU_I: | 1048 | case LLCP_PDU_I: |
1005 | case LLCP_PDU_RR: | 1049 | case LLCP_PDU_RR: |
1006 | case LLCP_PDU_RNR: | 1050 | case LLCP_PDU_RNR: |