diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-07-12 13:44:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-07-12 13:44:50 -0400 |
commit | 38a00840638b4932152bca48098dbfa069d942a2 (patch) | |
tree | dd12897854f6df8aac237d5fd46551c74be8153a /net/nfc | |
parent | 391e5c22f5f4e55817f8ba18a08ea717ed2d4a1f (diff) | |
parent | 2f8684ce7a47c91da7e0ccba2686277c103d02b6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/core.c | 38 | ||||
-rw-r--r-- | net/nfc/hci/command.c | 26 | ||||
-rw-r--r-- | net/nfc/hci/core.c | 104 | ||||
-rw-r--r-- | net/nfc/hci/hci.h | 12 | ||||
-rw-r--r-- | net/nfc/hci/shdlc.c | 38 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.c | 342 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.h | 5 | ||||
-rw-r--r-- | net/nfc/llcp/sock.c | 31 | ||||
-rw-r--r-- | net/nfc/nci/core.c | 5 | ||||
-rw-r--r-- | net/nfc/nci/ntf.c | 5 | ||||
-rw-r--r-- | net/nfc/netlink.c | 9 |
11 files changed, 392 insertions, 223 deletions
diff --git a/net/nfc/core.c b/net/nfc/core.c index 4177bb5104b9..ff749794bc5b 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/nfc.h> | 30 | #include <linux/nfc.h> |
31 | 31 | ||
32 | #include <net/genetlink.h> | ||
33 | |||
32 | #include "nfc.h" | 34 | #include "nfc.h" |
33 | 35 | ||
34 | #define VERSION "0.1" | 36 | #define VERSION "0.1" |
@@ -560,6 +562,8 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb); | |||
560 | * The device driver must call this function when one or many nfc targets | 562 | * The device driver must call this function when one or many nfc targets |
561 | * are found. After calling this function, the device driver must stop | 563 | * are found. After calling this function, the device driver must stop |
562 | * polling for targets. | 564 | * polling for targets. |
565 | * NOTE: This function can be called with targets=NULL and n_targets=0 to | ||
566 | * notify a driver error, meaning that the polling operation cannot complete. | ||
563 | * IMPORTANT: this function must not be called from an atomic context. | 567 | * IMPORTANT: this function must not be called from an atomic context. |
564 | * In addition, it must also not be called from a context that would prevent | 568 | * In addition, it must also not be called from a context that would prevent |
565 | * the NFC Core to call other nfc ops entry point concurrently. | 569 | * the NFC Core to call other nfc ops entry point concurrently. |
@@ -571,23 +575,33 @@ int nfc_targets_found(struct nfc_dev *dev, | |||
571 | 575 | ||
572 | pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); | 576 | pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); |
573 | 577 | ||
574 | dev->polling = false; | ||
575 | |||
576 | for (i = 0; i < n_targets; i++) | 578 | for (i = 0; i < n_targets; i++) |
577 | targets[i].idx = dev->target_next_idx++; | 579 | targets[i].idx = dev->target_next_idx++; |
578 | 580 | ||
579 | device_lock(&dev->dev); | 581 | device_lock(&dev->dev); |
580 | 582 | ||
583 | if (dev->polling == false) { | ||
584 | device_unlock(&dev->dev); | ||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | dev->polling = false; | ||
589 | |||
581 | dev->targets_generation++; | 590 | dev->targets_generation++; |
582 | 591 | ||
583 | kfree(dev->targets); | 592 | kfree(dev->targets); |
584 | dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target), | 593 | dev->targets = NULL; |
585 | GFP_ATOMIC); | ||
586 | 594 | ||
587 | if (!dev->targets) { | 595 | if (targets) { |
588 | dev->n_targets = 0; | 596 | dev->targets = kmemdup(targets, |
589 | device_unlock(&dev->dev); | 597 | n_targets * sizeof(struct nfc_target), |
590 | return -ENOMEM; | 598 | GFP_ATOMIC); |
599 | |||
600 | if (!dev->targets) { | ||
601 | dev->n_targets = 0; | ||
602 | device_unlock(&dev->dev); | ||
603 | return -ENOMEM; | ||
604 | } | ||
591 | } | 605 | } |
592 | 606 | ||
593 | dev->n_targets = n_targets; | 607 | dev->n_targets = n_targets; |
@@ -651,6 +665,12 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx) | |||
651 | } | 665 | } |
652 | EXPORT_SYMBOL(nfc_target_lost); | 666 | EXPORT_SYMBOL(nfc_target_lost); |
653 | 667 | ||
668 | inline void nfc_driver_failure(struct nfc_dev *dev, int err) | ||
669 | { | ||
670 | nfc_targets_found(dev, NULL, 0); | ||
671 | } | ||
672 | EXPORT_SYMBOL(nfc_driver_failure); | ||
673 | |||
654 | static void nfc_release(struct device *d) | 674 | static void nfc_release(struct device *d) |
655 | { | 675 | { |
656 | struct nfc_dev *dev = to_nfc_dev(d); | 676 | struct nfc_dev *dev = to_nfc_dev(d); |
@@ -906,3 +926,5 @@ MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>"); | |||
906 | MODULE_DESCRIPTION("NFC Core ver " VERSION); | 926 | MODULE_DESCRIPTION("NFC Core ver " VERSION); |
907 | MODULE_VERSION(VERSION); | 927 | MODULE_VERSION(VERSION); |
908 | MODULE_LICENSE("GPL"); | 928 | MODULE_LICENSE("GPL"); |
929 | MODULE_ALIAS_NETPROTO(PF_NFC); | ||
930 | MODULE_ALIAS_GENL_FAMILY(NFC_GENL_NAME); | ||
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 8729abf5f18b..46362ef979db 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c | |||
@@ -28,26 +28,14 @@ | |||
28 | 28 | ||
29 | #include "hci.h" | 29 | #include "hci.h" |
30 | 30 | ||
31 | static int nfc_hci_result_to_errno(u8 result) | 31 | static void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, int err, |
32 | { | ||
33 | switch (result) { | ||
34 | case NFC_HCI_ANY_OK: | ||
35 | return 0; | ||
36 | case NFC_HCI_ANY_E_TIMEOUT: | ||
37 | return -ETIMEDOUT; | ||
38 | default: | ||
39 | return -1; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | static void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, u8 result, | ||
44 | struct sk_buff *skb, void *cb_data) | 32 | struct sk_buff *skb, void *cb_data) |
45 | { | 33 | { |
46 | struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)cb_data; | 34 | struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)cb_data; |
47 | 35 | ||
48 | pr_debug("HCI Cmd completed with HCI result=%d\n", result); | 36 | pr_debug("HCI Cmd completed with result=%d\n", err); |
49 | 37 | ||
50 | hcp_ew->exec_result = nfc_hci_result_to_errno(result); | 38 | hcp_ew->exec_result = err; |
51 | if (hcp_ew->exec_result == 0) | 39 | if (hcp_ew->exec_result == 0) |
52 | hcp_ew->result_skb = skb; | 40 | hcp_ew->result_skb = skb; |
53 | else | 41 | else |
@@ -311,9 +299,9 @@ int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev) | |||
311 | } | 299 | } |
312 | EXPORT_SYMBOL(nfc_hci_disconnect_all_gates); | 300 | EXPORT_SYMBOL(nfc_hci_disconnect_all_gates); |
313 | 301 | ||
314 | int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate) | 302 | int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, |
303 | u8 pipe) | ||
315 | { | 304 | { |
316 | u8 pipe = NFC_HCI_INVALID_PIPE; | ||
317 | bool pipe_created = false; | 305 | bool pipe_created = false; |
318 | int r; | 306 | int r; |
319 | 307 | ||
@@ -322,6 +310,9 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate) | |||
322 | if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) | 310 | if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) |
323 | return -EADDRINUSE; | 311 | return -EADDRINUSE; |
324 | 312 | ||
313 | if (pipe != NFC_HCI_INVALID_PIPE) | ||
314 | goto pipe_is_open; | ||
315 | |||
325 | switch (dest_gate) { | 316 | switch (dest_gate) { |
326 | case NFC_HCI_LINK_MGMT_GATE: | 317 | case NFC_HCI_LINK_MGMT_GATE: |
327 | pipe = NFC_HCI_LINK_MGMT_PIPE; | 318 | pipe = NFC_HCI_LINK_MGMT_PIPE; |
@@ -347,6 +338,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate) | |||
347 | return r; | 338 | return r; |
348 | } | 339 | } |
349 | 340 | ||
341 | pipe_is_open: | ||
350 | hdev->gate2pipe[dest_gate] = pipe; | 342 | hdev->gate2pipe[dest_gate] = pipe; |
351 | 343 | ||
352 | return 0; | 344 | return 0; |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index a8b0b71e8f86..36717cebfbb6 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -32,6 +32,18 @@ | |||
32 | /* Largest headroom needed for outgoing HCI commands */ | 32 | /* Largest headroom needed for outgoing HCI commands */ |
33 | #define HCI_CMDS_HEADROOM 1 | 33 | #define HCI_CMDS_HEADROOM 1 |
34 | 34 | ||
35 | static int nfc_hci_result_to_errno(u8 result) | ||
36 | { | ||
37 | switch (result) { | ||
38 | case NFC_HCI_ANY_OK: | ||
39 | return 0; | ||
40 | case NFC_HCI_ANY_E_TIMEOUT: | ||
41 | return -ETIME; | ||
42 | default: | ||
43 | return -1; | ||
44 | } | ||
45 | } | ||
46 | |||
35 | static void nfc_hci_msg_tx_work(struct work_struct *work) | 47 | static void nfc_hci_msg_tx_work(struct work_struct *work) |
36 | { | 48 | { |
37 | struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev, | 49 | struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev, |
@@ -46,7 +58,7 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) | |||
46 | if (timer_pending(&hdev->cmd_timer) == 0) { | 58 | if (timer_pending(&hdev->cmd_timer) == 0) { |
47 | if (hdev->cmd_pending_msg->cb) | 59 | if (hdev->cmd_pending_msg->cb) |
48 | hdev->cmd_pending_msg->cb(hdev, | 60 | hdev->cmd_pending_msg->cb(hdev, |
49 | NFC_HCI_ANY_E_TIMEOUT, | 61 | -ETIME, |
50 | NULL, | 62 | NULL, |
51 | hdev-> | 63 | hdev-> |
52 | cmd_pending_msg-> | 64 | cmd_pending_msg-> |
@@ -71,8 +83,7 @@ next_msg: | |||
71 | kfree_skb(skb); | 83 | kfree_skb(skb); |
72 | skb_queue_purge(&msg->msg_frags); | 84 | skb_queue_purge(&msg->msg_frags); |
73 | if (msg->cb) | 85 | if (msg->cb) |
74 | msg->cb(hdev, NFC_HCI_ANY_E_NOK, NULL, | 86 | msg->cb(hdev, r, NULL, msg->cb_context); |
75 | msg->cb_context); | ||
76 | kfree(msg); | 87 | kfree(msg); |
77 | break; | 88 | break; |
78 | } | 89 | } |
@@ -116,20 +127,13 @@ static void nfc_hci_msg_rx_work(struct work_struct *work) | |||
116 | } | 127 | } |
117 | } | 128 | } |
118 | 129 | ||
119 | void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, | 130 | static void __nfc_hci_cmd_completion(struct nfc_hci_dev *hdev, int err, |
120 | struct sk_buff *skb) | 131 | struct sk_buff *skb) |
121 | { | 132 | { |
122 | mutex_lock(&hdev->msg_tx_mutex); | ||
123 | |||
124 | if (hdev->cmd_pending_msg == NULL) { | ||
125 | kfree_skb(skb); | ||
126 | goto exit; | ||
127 | } | ||
128 | |||
129 | del_timer_sync(&hdev->cmd_timer); | 133 | del_timer_sync(&hdev->cmd_timer); |
130 | 134 | ||
131 | if (hdev->cmd_pending_msg->cb) | 135 | if (hdev->cmd_pending_msg->cb) |
132 | hdev->cmd_pending_msg->cb(hdev, result, skb, | 136 | hdev->cmd_pending_msg->cb(hdev, err, skb, |
133 | hdev->cmd_pending_msg->cb_context); | 137 | hdev->cmd_pending_msg->cb_context); |
134 | else | 138 | else |
135 | kfree_skb(skb); | 139 | kfree_skb(skb); |
@@ -138,6 +142,19 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, | |||
138 | hdev->cmd_pending_msg = NULL; | 142 | hdev->cmd_pending_msg = NULL; |
139 | 143 | ||
140 | queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); | 144 | queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); |
145 | } | ||
146 | |||
147 | void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, | ||
148 | struct sk_buff *skb) | ||
149 | { | ||
150 | mutex_lock(&hdev->msg_tx_mutex); | ||
151 | |||
152 | if (hdev->cmd_pending_msg == NULL) { | ||
153 | kfree_skb(skb); | ||
154 | goto exit; | ||
155 | } | ||
156 | |||
157 | __nfc_hci_cmd_completion(hdev, nfc_hci_result_to_errno(result), skb); | ||
141 | 158 | ||
142 | exit: | 159 | exit: |
143 | mutex_unlock(&hdev->msg_tx_mutex); | 160 | mutex_unlock(&hdev->msg_tx_mutex); |
@@ -213,7 +230,7 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) | |||
213 | } | 230 | } |
214 | break; | 231 | break; |
215 | case NFC_HCI_RF_READER_B_GATE: | 232 | case NFC_HCI_RF_READER_B_GATE: |
216 | targets->supported_protocols = NFC_PROTO_ISO14443_MASK; | 233 | targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK; |
217 | break; | 234 | break; |
218 | default: | 235 | default: |
219 | if (hdev->ops->target_from_gate) | 236 | if (hdev->ops->target_from_gate) |
@@ -298,15 +315,15 @@ static void nfc_hci_cmd_timeout(unsigned long data) | |||
298 | } | 315 | } |
299 | 316 | ||
300 | static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count, | 317 | static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count, |
301 | u8 gates[]) | 318 | struct nfc_hci_gate *gates) |
302 | { | 319 | { |
303 | int r; | 320 | int r; |
304 | u8 *p = gates; | ||
305 | while (gate_count--) { | 321 | while (gate_count--) { |
306 | r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, *p); | 322 | r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, |
323 | gates->gate, gates->pipe); | ||
307 | if (r < 0) | 324 | if (r < 0) |
308 | return r; | 325 | return r; |
309 | p++; | 326 | gates++; |
310 | } | 327 | } |
311 | 328 | ||
312 | return 0; | 329 | return 0; |
@@ -316,14 +333,13 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev) | |||
316 | { | 333 | { |
317 | struct sk_buff *skb = NULL; | 334 | struct sk_buff *skb = NULL; |
318 | int r; | 335 | int r; |
319 | u8 hci_gates[] = { /* NFC_HCI_ADMIN_GATE MUST be first */ | 336 | |
320 | NFC_HCI_ADMIN_GATE, NFC_HCI_LOOPBACK_GATE, | 337 | if (hdev->init_data.gates[0].gate != NFC_HCI_ADMIN_GATE) |
321 | NFC_HCI_ID_MGMT_GATE, NFC_HCI_LINK_MGMT_GATE, | 338 | return -EPROTO; |
322 | NFC_HCI_RF_READER_B_GATE, NFC_HCI_RF_READER_A_GATE | ||
323 | }; | ||
324 | 339 | ||
325 | r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, | 340 | r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, |
326 | NFC_HCI_ADMIN_GATE); | 341 | hdev->init_data.gates[0].gate, |
342 | hdev->init_data.gates[0].pipe); | ||
327 | if (r < 0) | 343 | if (r < 0) |
328 | goto exit; | 344 | goto exit; |
329 | 345 | ||
@@ -351,10 +367,6 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev) | |||
351 | if (r < 0) | 367 | if (r < 0) |
352 | goto exit; | 368 | goto exit; |
353 | 369 | ||
354 | r = hci_dev_connect_gates(hdev, sizeof(hci_gates), hci_gates); | ||
355 | if (r < 0) | ||
356 | goto disconnect_all; | ||
357 | |||
358 | r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, | 370 | r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, |
359 | hdev->init_data.gates); | 371 | hdev->init_data.gates); |
360 | if (r < 0) | 372 | if (r < 0) |
@@ -717,6 +729,27 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev) | |||
717 | } | 729 | } |
718 | EXPORT_SYMBOL(nfc_hci_get_clientdata); | 730 | EXPORT_SYMBOL(nfc_hci_get_clientdata); |
719 | 731 | ||
732 | static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err) | ||
733 | { | ||
734 | mutex_lock(&hdev->msg_tx_mutex); | ||
735 | |||
736 | if (hdev->cmd_pending_msg == NULL) { | ||
737 | nfc_driver_failure(hdev->ndev, err); | ||
738 | goto exit; | ||
739 | } | ||
740 | |||
741 | __nfc_hci_cmd_completion(hdev, err, NULL); | ||
742 | |||
743 | exit: | ||
744 | mutex_unlock(&hdev->msg_tx_mutex); | ||
745 | } | ||
746 | |||
747 | void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err) | ||
748 | { | ||
749 | nfc_hci_failure(hdev, err); | ||
750 | } | ||
751 | EXPORT_SYMBOL(nfc_hci_driver_failure); | ||
752 | |||
720 | void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) | 753 | void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
721 | { | 754 | { |
722 | struct hcp_packet *packet; | 755 | struct hcp_packet *packet; |
@@ -727,16 +760,6 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |||
727 | struct sk_buff *frag_skb; | 760 | struct sk_buff *frag_skb; |
728 | int msg_len; | 761 | int msg_len; |
729 | 762 | ||
730 | if (skb == NULL) { | ||
731 | /* TODO ELa: lower layer had permanent failure, need to | ||
732 | * propagate that up | ||
733 | */ | ||
734 | |||
735 | skb_queue_purge(&hdev->rx_hcp_frags); | ||
736 | |||
737 | return; | ||
738 | } | ||
739 | |||
740 | packet = (struct hcp_packet *)skb->data; | 763 | packet = (struct hcp_packet *)skb->data; |
741 | if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) { | 764 | if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) { |
742 | skb_queue_tail(&hdev->rx_hcp_frags, skb); | 765 | skb_queue_tail(&hdev->rx_hcp_frags, skb); |
@@ -757,9 +780,8 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |||
757 | hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN + | 780 | hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN + |
758 | msg_len, GFP_KERNEL); | 781 | msg_len, GFP_KERNEL); |
759 | if (hcp_skb == NULL) { | 782 | if (hcp_skb == NULL) { |
760 | /* TODO ELa: cannot deliver HCP message. How to | 783 | nfc_hci_failure(hdev, -ENOMEM); |
761 | * propagate error up? | 784 | return; |
762 | */ | ||
763 | } | 785 | } |
764 | 786 | ||
765 | *skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe; | 787 | *skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe; |
diff --git a/net/nfc/hci/hci.h b/net/nfc/hci/hci.h index 45f2fe4fd486..fa9a21e92239 100644 --- a/net/nfc/hci/hci.h +++ b/net/nfc/hci/hci.h | |||
@@ -37,10 +37,11 @@ struct hcp_packet { | |||
37 | 37 | ||
38 | /* | 38 | /* |
39 | * HCI command execution completion callback. | 39 | * HCI command execution completion callback. |
40 | * result will be one of the HCI response codes. | 40 | * result will be a standard linux error (may be converted from HCI response) |
41 | * skb contains the response data and must be disposed. | 41 | * skb contains the response data and must be disposed, or may be NULL if |
42 | * an error occured | ||
42 | */ | 43 | */ |
43 | typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, u8 result, | 44 | typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, int result, |
44 | struct sk_buff *skb, void *cb_data); | 45 | struct sk_buff *skb, void *cb_data); |
45 | 46 | ||
46 | struct hcp_exec_waiter { | 47 | struct hcp_exec_waiter { |
@@ -131,9 +132,4 @@ void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type, | |||
131 | #define NFC_HCI_ANY_E_REG_ACCESS_DENIED 0x0a | 132 | #define NFC_HCI_ANY_E_REG_ACCESS_DENIED 0x0a |
132 | #define NFC_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b | 133 | #define NFC_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b |
133 | 134 | ||
134 | /* Pipes */ | ||
135 | #define NFC_HCI_INVALID_PIPE 0x80 | ||
136 | #define NFC_HCI_LINK_MGMT_PIPE 0x00 | ||
137 | #define NFC_HCI_ADMIN_PIPE 0x01 | ||
138 | |||
139 | #endif /* __LOCAL_HCI_H */ | 135 | #endif /* __LOCAL_HCI_H */ |
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c index 6b836e6242b7..6f840c18c892 100644 --- a/net/nfc/hci/shdlc.c +++ b/net/nfc/hci/shdlc.c | |||
@@ -340,15 +340,6 @@ static void nfc_shdlc_connect_complete(struct nfc_shdlc *shdlc, int r) | |||
340 | shdlc->state = SHDLC_CONNECTED; | 340 | shdlc->state = SHDLC_CONNECTED; |
341 | } else { | 341 | } else { |
342 | shdlc->state = SHDLC_DISCONNECTED; | 342 | shdlc->state = SHDLC_DISCONNECTED; |
343 | |||
344 | /* | ||
345 | * TODO: Could it be possible that there are pending | ||
346 | * executing commands that are waiting for connect to complete | ||
347 | * before they can be carried? As connect is a blocking | ||
348 | * operation, it would require that the userspace process can | ||
349 | * send commands on the same device from a second thread before | ||
350 | * the device is up. I don't think that is possible, is it? | ||
351 | */ | ||
352 | } | 343 | } |
353 | 344 | ||
354 | shdlc->connect_result = r; | 345 | shdlc->connect_result = r; |
@@ -413,12 +404,12 @@ static void nfc_shdlc_rcv_u_frame(struct nfc_shdlc *shdlc, | |||
413 | r = nfc_shdlc_connect_send_ua(shdlc); | 404 | r = nfc_shdlc_connect_send_ua(shdlc); |
414 | nfc_shdlc_connect_complete(shdlc, r); | 405 | nfc_shdlc_connect_complete(shdlc, r); |
415 | } | 406 | } |
416 | } else if (shdlc->state > SHDLC_NEGOCIATING) { | 407 | } else if (shdlc->state == SHDLC_CONNECTED) { |
417 | /* | 408 | /* |
418 | * TODO: Chip wants to reset link | 409 | * Chip wants to reset link. This is unexpected and |
419 | * send ua, empty skb lists, reset counters | 410 | * unsupported. |
420 | * propagate info to HCI layer | ||
421 | */ | 411 | */ |
412 | shdlc->hard_fault = -ECONNRESET; | ||
422 | } | 413 | } |
423 | break; | 414 | break; |
424 | case U_FRAME_UA: | 415 | case U_FRAME_UA: |
@@ -523,10 +514,6 @@ static void nfc_shdlc_handle_send_queue(struct nfc_shdlc *shdlc) | |||
523 | 514 | ||
524 | r = shdlc->ops->xmit(shdlc, skb); | 515 | r = shdlc->ops->xmit(shdlc, skb); |
525 | if (r < 0) { | 516 | if (r < 0) { |
526 | /* | ||
527 | * TODO: Cannot send, shdlc machine is dead, we | ||
528 | * must propagate the information up to HCI. | ||
529 | */ | ||
530 | shdlc->hard_fault = r; | 517 | shdlc->hard_fault = r; |
531 | break; | 518 | break; |
532 | } | 519 | } |
@@ -590,6 +577,11 @@ static void nfc_shdlc_sm_work(struct work_struct *work) | |||
590 | skb_queue_purge(&shdlc->ack_pending_q); | 577 | skb_queue_purge(&shdlc->ack_pending_q); |
591 | break; | 578 | break; |
592 | case SHDLC_CONNECTING: | 579 | case SHDLC_CONNECTING: |
580 | if (shdlc->hard_fault) { | ||
581 | nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault); | ||
582 | break; | ||
583 | } | ||
584 | |||
593 | if (shdlc->connect_tries++ < 5) | 585 | if (shdlc->connect_tries++ < 5) |
594 | r = nfc_shdlc_connect_initiate(shdlc); | 586 | r = nfc_shdlc_connect_initiate(shdlc); |
595 | else | 587 | else |
@@ -610,6 +602,11 @@ static void nfc_shdlc_sm_work(struct work_struct *work) | |||
610 | } | 602 | } |
611 | 603 | ||
612 | nfc_shdlc_handle_rcv_queue(shdlc); | 604 | nfc_shdlc_handle_rcv_queue(shdlc); |
605 | |||
606 | if (shdlc->hard_fault) { | ||
607 | nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault); | ||
608 | break; | ||
609 | } | ||
613 | break; | 610 | break; |
614 | case SHDLC_CONNECTED: | 611 | case SHDLC_CONNECTED: |
615 | nfc_shdlc_handle_rcv_queue(shdlc); | 612 | nfc_shdlc_handle_rcv_queue(shdlc); |
@@ -637,10 +634,7 @@ static void nfc_shdlc_sm_work(struct work_struct *work) | |||
637 | } | 634 | } |
638 | 635 | ||
639 | if (shdlc->hard_fault) { | 636 | if (shdlc->hard_fault) { |
640 | /* | 637 | nfc_hci_driver_failure(shdlc->hdev, shdlc->hard_fault); |
641 | * TODO: Handle hard_fault that occured during | ||
642 | * this invocation of the shdlc worker | ||
643 | */ | ||
644 | } | 638 | } |
645 | break; | 639 | break; |
646 | default: | 640 | default: |
@@ -923,8 +917,6 @@ void nfc_shdlc_free(struct nfc_shdlc *shdlc) | |||
923 | { | 917 | { |
924 | pr_debug("\n"); | 918 | pr_debug("\n"); |
925 | 919 | ||
926 | /* TODO: Check that this cannot be called while still in use */ | ||
927 | |||
928 | nfc_hci_unregister_device(shdlc->hdev); | 920 | nfc_hci_unregister_device(shdlc->hdev); |
929 | nfc_hci_free_device(shdlc->hdev); | 921 | nfc_hci_free_device(shdlc->hdev); |
930 | 922 | ||
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 5d503eeb15a1..82f0f7588b46 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -45,7 +45,7 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) | |||
45 | write_unlock(&l->lock); | 45 | write_unlock(&l->lock); |
46 | } | 46 | } |
47 | 47 | ||
48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | 48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) |
49 | { | 49 | { |
50 | struct sock *sk; | 50 | struct sock *sk; |
51 | struct hlist_node *node, *tmp; | 51 | struct hlist_node *node, *tmp; |
@@ -78,6 +78,11 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
78 | 78 | ||
79 | sock_orphan(accept_sk); | 79 | sock_orphan(accept_sk); |
80 | } | 80 | } |
81 | |||
82 | if (listen == true) { | ||
83 | release_sock(sk); | ||
84 | continue; | ||
85 | } | ||
81 | } | 86 | } |
82 | 87 | ||
83 | sk->sk_state = LLCP_CLOSED; | 88 | sk->sk_state = LLCP_CLOSED; |
@@ -106,7 +111,7 @@ static void local_release(struct kref *ref) | |||
106 | local = container_of(ref, struct nfc_llcp_local, ref); | 111 | local = container_of(ref, struct nfc_llcp_local, ref); |
107 | 112 | ||
108 | list_del(&local->list); | 113 | list_del(&local->list); |
109 | nfc_llcp_socket_release(local); | 114 | nfc_llcp_socket_release(local, false); |
110 | del_timer_sync(&local->link_timer); | 115 | del_timer_sync(&local->link_timer); |
111 | skb_queue_purge(&local->tx_queue); | 116 | skb_queue_purge(&local->tx_queue); |
112 | destroy_workqueue(local->tx_wq); | 117 | destroy_workqueue(local->tx_wq); |
@@ -118,23 +123,48 @@ static void local_release(struct kref *ref) | |||
118 | 123 | ||
119 | int nfc_llcp_local_put(struct nfc_llcp_local *local) | 124 | int nfc_llcp_local_put(struct nfc_llcp_local *local) |
120 | { | 125 | { |
121 | WARN_ON(local == NULL); | ||
122 | |||
123 | if (local == NULL) | 126 | if (local == NULL) |
124 | return 0; | 127 | return 0; |
125 | 128 | ||
126 | return kref_put(&local->ref, local_release); | 129 | return kref_put(&local->ref, local_release); |
127 | } | 130 | } |
128 | 131 | ||
129 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) | 132 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, |
133 | u8 ssap, u8 dsap) | ||
130 | { | 134 | { |
131 | mutex_lock(&local->sdp_lock); | 135 | struct sock *sk; |
136 | struct hlist_node *node; | ||
137 | struct nfc_llcp_sock *llcp_sock; | ||
132 | 138 | ||
133 | local->local_wks = 0; | 139 | pr_debug("ssap dsap %d %d\n", ssap, dsap); |
134 | local->local_sdp = 0; | ||
135 | local->local_sap = 0; | ||
136 | 140 | ||
137 | mutex_unlock(&local->sdp_lock); | 141 | if (ssap == 0 && dsap == 0) |
142 | return NULL; | ||
143 | |||
144 | read_lock(&local->sockets.lock); | ||
145 | |||
146 | llcp_sock = NULL; | ||
147 | |||
148 | sk_for_each(sk, node, &local->sockets.head) { | ||
149 | llcp_sock = nfc_llcp_sock(sk); | ||
150 | |||
151 | if (llcp_sock->ssap == ssap && llcp_sock->dsap == dsap) | ||
152 | break; | ||
153 | } | ||
154 | |||
155 | read_unlock(&local->sockets.lock); | ||
156 | |||
157 | if (llcp_sock == NULL) | ||
158 | return NULL; | ||
159 | |||
160 | sock_hold(&llcp_sock->sk); | ||
161 | |||
162 | return llcp_sock; | ||
163 | } | ||
164 | |||
165 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) | ||
166 | { | ||
167 | sock_put(&sock->sk); | ||
138 | } | 168 | } |
139 | 169 | ||
140 | static void nfc_llcp_timeout_work(struct work_struct *work) | 170 | static void nfc_llcp_timeout_work(struct work_struct *work) |
@@ -197,6 +227,51 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len) | |||
197 | return -EINVAL; | 227 | return -EINVAL; |
198 | } | 228 | } |
199 | 229 | ||
230 | static | ||
231 | struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local, | ||
232 | u8 *sn, size_t sn_len) | ||
233 | { | ||
234 | struct sock *sk; | ||
235 | struct hlist_node *node; | ||
236 | struct nfc_llcp_sock *llcp_sock, *tmp_sock; | ||
237 | |||
238 | pr_debug("sn %zd %p\n", sn_len, sn); | ||
239 | |||
240 | if (sn == NULL || sn_len == 0) | ||
241 | return NULL; | ||
242 | |||
243 | read_lock(&local->sockets.lock); | ||
244 | |||
245 | llcp_sock = NULL; | ||
246 | |||
247 | sk_for_each(sk, node, &local->sockets.head) { | ||
248 | tmp_sock = nfc_llcp_sock(sk); | ||
249 | |||
250 | pr_debug("llcp sock %p\n", tmp_sock); | ||
251 | |||
252 | if (tmp_sock->sk.sk_state != LLCP_LISTEN) | ||
253 | continue; | ||
254 | |||
255 | if (tmp_sock->service_name == NULL || | ||
256 | tmp_sock->service_name_len == 0) | ||
257 | continue; | ||
258 | |||
259 | if (tmp_sock->service_name_len != sn_len) | ||
260 | continue; | ||
261 | |||
262 | if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) { | ||
263 | llcp_sock = tmp_sock; | ||
264 | break; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | read_unlock(&local->sockets.lock); | ||
269 | |||
270 | pr_debug("Found llcp sock %p\n", llcp_sock); | ||
271 | |||
272 | return llcp_sock; | ||
273 | } | ||
274 | |||
200 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | 275 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, |
201 | struct nfc_llcp_sock *sock) | 276 | struct nfc_llcp_sock *sock) |
202 | { | 277 | { |
@@ -223,41 +298,26 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | |||
223 | } | 298 | } |
224 | 299 | ||
225 | /* | 300 | /* |
226 | * This is not a well known service, | 301 | * Check if there already is a non WKS socket bound |
227 | * we should try to find a local SDP free spot | 302 | * to this service name. |
228 | */ | 303 | */ |
229 | ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP); | 304 | if (nfc_llcp_sock_from_sn(local, sock->service_name, |
230 | if (ssap == LLCP_SDP_NUM_SAP) { | 305 | sock->service_name_len) != NULL) { |
231 | mutex_unlock(&local->sdp_lock); | 306 | mutex_unlock(&local->sdp_lock); |
232 | 307 | ||
233 | return LLCP_SAP_MAX; | 308 | return LLCP_SAP_MAX; |
234 | } | 309 | } |
235 | 310 | ||
236 | pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap); | ||
237 | |||
238 | set_bit(ssap, &local->local_sdp); | ||
239 | mutex_unlock(&local->sdp_lock); | 311 | mutex_unlock(&local->sdp_lock); |
240 | 312 | ||
241 | return LLCP_WKS_NUM_SAP + ssap; | 313 | return LLCP_SDP_UNBOUND; |
242 | |||
243 | } else if (sock->ssap != 0) { | ||
244 | if (sock->ssap < LLCP_WKS_NUM_SAP) { | ||
245 | if (!test_bit(sock->ssap, &local->local_wks)) { | ||
246 | set_bit(sock->ssap, &local->local_wks); | ||
247 | mutex_unlock(&local->sdp_lock); | ||
248 | |||
249 | return sock->ssap; | ||
250 | } | ||
251 | 314 | ||
252 | } else if (sock->ssap < LLCP_SDP_NUM_SAP) { | 315 | } else if (sock->ssap != 0 && sock->ssap < LLCP_WKS_NUM_SAP) { |
253 | if (!test_bit(sock->ssap - LLCP_WKS_NUM_SAP, | 316 | if (!test_bit(sock->ssap, &local->local_wks)) { |
254 | &local->local_sdp)) { | 317 | set_bit(sock->ssap, &local->local_wks); |
255 | set_bit(sock->ssap - LLCP_WKS_NUM_SAP, | 318 | mutex_unlock(&local->sdp_lock); |
256 | &local->local_sdp); | ||
257 | mutex_unlock(&local->sdp_lock); | ||
258 | 319 | ||
259 | return sock->ssap; | 320 | return sock->ssap; |
260 | } | ||
261 | } | 321 | } |
262 | } | 322 | } |
263 | 323 | ||
@@ -294,8 +354,34 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap) | |||
294 | local_ssap = ssap; | 354 | local_ssap = ssap; |
295 | sdp = &local->local_wks; | 355 | sdp = &local->local_wks; |
296 | } else if (ssap < LLCP_LOCAL_NUM_SAP) { | 356 | } else if (ssap < LLCP_LOCAL_NUM_SAP) { |
357 | atomic_t *client_cnt; | ||
358 | |||
297 | local_ssap = ssap - LLCP_WKS_NUM_SAP; | 359 | local_ssap = ssap - LLCP_WKS_NUM_SAP; |
298 | sdp = &local->local_sdp; | 360 | sdp = &local->local_sdp; |
361 | client_cnt = &local->local_sdp_cnt[local_ssap]; | ||
362 | |||
363 | pr_debug("%d clients\n", atomic_read(client_cnt)); | ||
364 | |||
365 | mutex_lock(&local->sdp_lock); | ||
366 | |||
367 | if (atomic_dec_and_test(client_cnt)) { | ||
368 | struct nfc_llcp_sock *l_sock; | ||
369 | |||
370 | pr_debug("No more clients for SAP %d\n", ssap); | ||
371 | |||
372 | clear_bit(local_ssap, sdp); | ||
373 | |||
374 | /* Find the listening sock and set it back to UNBOUND */ | ||
375 | l_sock = nfc_llcp_sock_get(local, ssap, LLCP_SAP_SDP); | ||
376 | if (l_sock) { | ||
377 | l_sock->ssap = LLCP_SDP_UNBOUND; | ||
378 | nfc_llcp_sock_put(l_sock); | ||
379 | } | ||
380 | } | ||
381 | |||
382 | mutex_unlock(&local->sdp_lock); | ||
383 | |||
384 | return; | ||
299 | } else if (ssap < LLCP_MAX_SAP) { | 385 | } else if (ssap < LLCP_MAX_SAP) { |
300 | local_ssap = ssap - LLCP_LOCAL_NUM_SAP; | 386 | local_ssap = ssap - LLCP_LOCAL_NUM_SAP; |
301 | sdp = &local->local_sap; | 387 | sdp = &local->local_sap; |
@@ -310,19 +396,26 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap) | |||
310 | mutex_unlock(&local->sdp_lock); | 396 | mutex_unlock(&local->sdp_lock); |
311 | } | 397 | } |
312 | 398 | ||
313 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) | 399 | static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local) |
314 | { | 400 | { |
315 | struct nfc_llcp_local *local; | 401 | u8 ssap; |
316 | 402 | ||
317 | local = nfc_llcp_find_local(dev); | 403 | mutex_lock(&local->sdp_lock); |
318 | if (local == NULL) { | 404 | |
319 | *general_bytes_len = 0; | 405 | ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP); |
320 | return NULL; | 406 | if (ssap == LLCP_SDP_NUM_SAP) { |
407 | mutex_unlock(&local->sdp_lock); | ||
408 | |||
409 | return LLCP_SAP_MAX; | ||
321 | } | 410 | } |
322 | 411 | ||
323 | *general_bytes_len = local->gb_len; | 412 | pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap); |
324 | 413 | ||
325 | return local->gb; | 414 | set_bit(ssap, &local->local_sdp); |
415 | |||
416 | mutex_unlock(&local->sdp_lock); | ||
417 | |||
418 | return LLCP_WKS_NUM_SAP + ssap; | ||
326 | } | 419 | } |
327 | 420 | ||
328 | static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | 421 | static int nfc_llcp_build_gb(struct nfc_llcp_local *local) |
@@ -386,6 +479,23 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
386 | return 0; | 479 | return 0; |
387 | } | 480 | } |
388 | 481 | ||
482 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) | ||
483 | { | ||
484 | struct nfc_llcp_local *local; | ||
485 | |||
486 | local = nfc_llcp_find_local(dev); | ||
487 | if (local == NULL) { | ||
488 | *general_bytes_len = 0; | ||
489 | return NULL; | ||
490 | } | ||
491 | |||
492 | nfc_llcp_build_gb(local); | ||
493 | |||
494 | *general_bytes_len = local->gb_len; | ||
495 | |||
496 | return local->gb; | ||
497 | } | ||
498 | |||
389 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | 499 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) |
390 | { | 500 | { |
391 | struct nfc_llcp_local *local = nfc_llcp_find_local(dev); | 501 | struct nfc_llcp_local *local = nfc_llcp_find_local(dev); |
@@ -509,74 +619,12 @@ out: | |||
509 | return llcp_sock; | 619 | return llcp_sock; |
510 | } | 620 | } |
511 | 621 | ||
512 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | ||
513 | u8 ssap, u8 dsap) | ||
514 | { | ||
515 | struct sock *sk; | ||
516 | struct hlist_node *node; | ||
517 | struct nfc_llcp_sock *llcp_sock; | ||
518 | |||
519 | pr_debug("ssap dsap %d %d\n", ssap, dsap); | ||
520 | |||
521 | if (ssap == 0 && dsap == 0) | ||
522 | return NULL; | ||
523 | |||
524 | read_lock(&local->sockets.lock); | ||
525 | |||
526 | llcp_sock = NULL; | ||
527 | |||
528 | sk_for_each(sk, node, &local->sockets.head) { | ||
529 | llcp_sock = nfc_llcp_sock(sk); | ||
530 | |||
531 | if (llcp_sock->ssap == ssap && | ||
532 | llcp_sock->dsap == dsap) | ||
533 | break; | ||
534 | } | ||
535 | |||
536 | read_unlock(&local->sockets.lock); | ||
537 | |||
538 | if (llcp_sock == NULL) | ||
539 | return NULL; | ||
540 | |||
541 | sock_hold(&llcp_sock->sk); | ||
542 | |||
543 | return llcp_sock; | ||
544 | } | ||
545 | |||
546 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, | 622 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, |
547 | u8 *sn, size_t sn_len) | 623 | u8 *sn, size_t sn_len) |
548 | { | 624 | { |
549 | struct sock *sk; | ||
550 | struct hlist_node *node; | ||
551 | struct nfc_llcp_sock *llcp_sock; | 625 | struct nfc_llcp_sock *llcp_sock; |
552 | 626 | ||
553 | pr_debug("sn %zd\n", sn_len); | 627 | llcp_sock = nfc_llcp_sock_from_sn(local, sn, sn_len); |
554 | |||
555 | if (sn == NULL || sn_len == 0) | ||
556 | return NULL; | ||
557 | |||
558 | read_lock(&local->sockets.lock); | ||
559 | |||
560 | llcp_sock = NULL; | ||
561 | |||
562 | sk_for_each(sk, node, &local->sockets.head) { | ||
563 | llcp_sock = nfc_llcp_sock(sk); | ||
564 | |||
565 | if (llcp_sock->sk.sk_state != LLCP_LISTEN) | ||
566 | continue; | ||
567 | |||
568 | if (llcp_sock->service_name == NULL || | ||
569 | llcp_sock->service_name_len == 0) | ||
570 | continue; | ||
571 | |||
572 | if (llcp_sock->service_name_len != sn_len) | ||
573 | continue; | ||
574 | |||
575 | if (memcmp(sn, llcp_sock->service_name, sn_len) == 0) | ||
576 | break; | ||
577 | } | ||
578 | |||
579 | read_unlock(&local->sockets.lock); | ||
580 | 628 | ||
581 | if (llcp_sock == NULL) | 629 | if (llcp_sock == NULL) |
582 | return NULL; | 630 | return NULL; |
@@ -586,11 +634,6 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, | |||
586 | return llcp_sock; | 634 | return llcp_sock; |
587 | } | 635 | } |
588 | 636 | ||
589 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) | ||
590 | { | ||
591 | sock_put(&sock->sk); | ||
592 | } | ||
593 | |||
594 | static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) | 637 | static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) |
595 | { | 638 | { |
596 | u8 *tlv = &skb->data[2], type, length; | 639 | u8 *tlv = &skb->data[2], type, length; |
@@ -662,6 +705,21 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
662 | goto fail; | 705 | goto fail; |
663 | } | 706 | } |
664 | 707 | ||
708 | if (sock->ssap == LLCP_SDP_UNBOUND) { | ||
709 | u8 ssap = nfc_llcp_reserve_sdp_ssap(local); | ||
710 | |||
711 | pr_debug("First client, reserving %d\n", ssap); | ||
712 | |||
713 | if (ssap == LLCP_SAP_MAX) { | ||
714 | reason = LLCP_DM_REJ; | ||
715 | release_sock(&sock->sk); | ||
716 | sock_put(&sock->sk); | ||
717 | goto fail; | ||
718 | } | ||
719 | |||
720 | sock->ssap = ssap; | ||
721 | } | ||
722 | |||
665 | new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC); | 723 | new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC); |
666 | if (new_sk == NULL) { | 724 | if (new_sk == NULL) { |
667 | reason = LLCP_DM_REJ; | 725 | reason = LLCP_DM_REJ; |
@@ -675,9 +733,21 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
675 | new_sock->local = nfc_llcp_local_get(local); | 733 | new_sock->local = nfc_llcp_local_get(local); |
676 | new_sock->miu = local->remote_miu; | 734 | new_sock->miu = local->remote_miu; |
677 | new_sock->nfc_protocol = sock->nfc_protocol; | 735 | new_sock->nfc_protocol = sock->nfc_protocol; |
678 | new_sock->ssap = sock->ssap; | ||
679 | new_sock->dsap = ssap; | 736 | new_sock->dsap = ssap; |
737 | new_sock->target_idx = local->target_idx; | ||
680 | new_sock->parent = parent; | 738 | new_sock->parent = parent; |
739 | new_sock->ssap = sock->ssap; | ||
740 | if (sock->ssap < LLCP_LOCAL_NUM_SAP && sock->ssap >= LLCP_WKS_NUM_SAP) { | ||
741 | atomic_t *client_count; | ||
742 | |||
743 | pr_debug("reserved_ssap %d for %p\n", sock->ssap, new_sock); | ||
744 | |||
745 | client_count = | ||
746 | &local->local_sdp_cnt[sock->ssap - LLCP_WKS_NUM_SAP]; | ||
747 | |||
748 | atomic_inc(client_count); | ||
749 | new_sock->reserved_ssap = sock->ssap; | ||
750 | } | ||
681 | 751 | ||
682 | nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE], | 752 | nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE], |
683 | skb->len - LLCP_HEADER_SIZE); | 753 | skb->len - LLCP_HEADER_SIZE); |
@@ -886,6 +956,45 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
886 | nfc_llcp_sock_put(llcp_sock); | 956 | nfc_llcp_sock_put(llcp_sock); |
887 | } | 957 | } |
888 | 958 | ||
959 | static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) | ||
960 | { | ||
961 | struct nfc_llcp_sock *llcp_sock; | ||
962 | struct sock *sk; | ||
963 | u8 dsap, ssap, reason; | ||
964 | |||
965 | dsap = nfc_llcp_dsap(skb); | ||
966 | ssap = nfc_llcp_ssap(skb); | ||
967 | reason = skb->data[2]; | ||
968 | |||
969 | pr_debug("%d %d reason %d\n", ssap, dsap, reason); | ||
970 | |||
971 | switch (reason) { | ||
972 | case LLCP_DM_NOBOUND: | ||
973 | case LLCP_DM_REJ: | ||
974 | llcp_sock = nfc_llcp_connecting_sock_get(local, dsap); | ||
975 | break; | ||
976 | |||
977 | default: | ||
978 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | ||
979 | break; | ||
980 | } | ||
981 | |||
982 | if (llcp_sock == NULL) { | ||
983 | pr_err("Invalid DM\n"); | ||
984 | return; | ||
985 | } | ||
986 | |||
987 | sk = &llcp_sock->sk; | ||
988 | |||
989 | sk->sk_err = ENXIO; | ||
990 | sk->sk_state = LLCP_CLOSED; | ||
991 | sk->sk_state_change(sk); | ||
992 | |||
993 | nfc_llcp_sock_put(llcp_sock); | ||
994 | |||
995 | return; | ||
996 | } | ||
997 | |||
889 | static void nfc_llcp_rx_work(struct work_struct *work) | 998 | static void nfc_llcp_rx_work(struct work_struct *work) |
890 | { | 999 | { |
891 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | 1000 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, |
@@ -929,6 +1038,11 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
929 | nfc_llcp_recv_cc(local, skb); | 1038 | nfc_llcp_recv_cc(local, skb); |
930 | break; | 1039 | break; |
931 | 1040 | ||
1041 | case LLCP_PDU_DM: | ||
1042 | pr_debug("DM\n"); | ||
1043 | nfc_llcp_recv_dm(local, skb); | ||
1044 | break; | ||
1045 | |||
932 | case LLCP_PDU_I: | 1046 | case LLCP_PDU_I: |
933 | case LLCP_PDU_RR: | 1047 | case LLCP_PDU_RR: |
934 | case LLCP_PDU_RNR: | 1048 | case LLCP_PDU_RNR: |
@@ -985,10 +1099,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev) | |||
985 | if (local == NULL) | 1099 | if (local == NULL) |
986 | return; | 1100 | return; |
987 | 1101 | ||
988 | nfc_llcp_clear_sdp(local); | ||
989 | |||
990 | /* Close and purge all existing sockets */ | 1102 | /* Close and purge all existing sockets */ |
991 | nfc_llcp_socket_release(local); | 1103 | nfc_llcp_socket_release(local, true); |
992 | } | 1104 | } |
993 | 1105 | ||
994 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | 1106 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 7286c86982ff..83b8bba5a280 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -37,6 +37,7 @@ enum llcp_state { | |||
37 | #define LLCP_LOCAL_NUM_SAP 32 | 37 | #define LLCP_LOCAL_NUM_SAP 32 |
38 | #define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP) | 38 | #define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP) |
39 | #define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP) | 39 | #define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP) |
40 | #define LLCP_SDP_UNBOUND (LLCP_MAX_SAP + 1) | ||
40 | 41 | ||
41 | struct nfc_llcp_sock; | 42 | struct nfc_llcp_sock; |
42 | 43 | ||
@@ -69,6 +70,7 @@ struct nfc_llcp_local { | |||
69 | unsigned long local_wks; /* Well known services */ | 70 | unsigned long local_wks; /* Well known services */ |
70 | unsigned long local_sdp; /* Local services */ | 71 | unsigned long local_sdp; /* Local services */ |
71 | unsigned long local_sap; /* Local SAPs, not available for discovery */ | 72 | unsigned long local_sap; /* Local SAPs, not available for discovery */ |
73 | atomic_t local_sdp_cnt[LLCP_SDP_NUM_SAP]; | ||
72 | 74 | ||
73 | /* local */ | 75 | /* local */ |
74 | u8 gb[NFC_MAX_GT_LEN]; | 76 | u8 gb[NFC_MAX_GT_LEN]; |
@@ -113,6 +115,9 @@ struct nfc_llcp_sock { | |||
113 | /* Is the remote peer ready to receive */ | 115 | /* Is the remote peer ready to receive */ |
114 | u8 remote_ready; | 116 | u8 remote_ready; |
115 | 117 | ||
118 | /* Reserved source SAP */ | ||
119 | u8 reserved_ssap; | ||
120 | |||
116 | struct sk_buff_head tx_queue; | 121 | struct sk_buff_head tx_queue; |
117 | struct sk_buff_head tx_pending_queue; | 122 | struct sk_buff_head tx_pending_queue; |
118 | struct sk_buff_head tx_backlog_queue; | 123 | struct sk_buff_head tx_backlog_queue; |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 05ca5a680071..ddeb9aa398f0 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -78,11 +78,11 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
78 | struct sockaddr_nfc_llcp llcp_addr; | 78 | struct sockaddr_nfc_llcp llcp_addr; |
79 | int len, ret = 0; | 79 | int len, ret = 0; |
80 | 80 | ||
81 | pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); | ||
82 | |||
83 | if (!addr || addr->sa_family != AF_NFC) | 81 | if (!addr || addr->sa_family != AF_NFC) |
84 | return -EINVAL; | 82 | return -EINVAL; |
85 | 83 | ||
84 | pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); | ||
85 | |||
86 | memset(&llcp_addr, 0, sizeof(llcp_addr)); | 86 | memset(&llcp_addr, 0, sizeof(llcp_addr)); |
87 | len = min_t(unsigned int, sizeof(llcp_addr), alen); | 87 | len = min_t(unsigned int, sizeof(llcp_addr), alen); |
88 | memcpy(&llcp_addr, addr, len); | 88 | memcpy(&llcp_addr, addr, len); |
@@ -121,8 +121,12 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
121 | GFP_KERNEL); | 121 | GFP_KERNEL); |
122 | 122 | ||
123 | llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); | 123 | llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); |
124 | if (llcp_sock->ssap == LLCP_MAX_SAP) | 124 | if (llcp_sock->ssap == LLCP_SAP_MAX) { |
125 | ret = -EADDRINUSE; | ||
125 | goto put_dev; | 126 | goto put_dev; |
127 | } | ||
128 | |||
129 | llcp_sock->reserved_ssap = llcp_sock->ssap; | ||
126 | 130 | ||
127 | nfc_llcp_sock_link(&local->sockets, sk); | 131 | nfc_llcp_sock_link(&local->sockets, sk); |
128 | 132 | ||
@@ -283,22 +287,28 @@ error: | |||
283 | return ret; | 287 | return ret; |
284 | } | 288 | } |
285 | 289 | ||
286 | static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, | 290 | static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr, |
287 | int *len, int peer) | 291 | int *len, int peer) |
288 | { | 292 | { |
289 | struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *)addr; | ||
290 | struct sock *sk = sock->sk; | 293 | struct sock *sk = sock->sk; |
291 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | 294 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); |
295 | DECLARE_SOCKADDR(struct sockaddr_nfc_llcp *, llcp_addr, uaddr); | ||
292 | 296 | ||
293 | pr_debug("%p\n", sk); | 297 | if (llcp_sock == NULL || llcp_sock->dev == NULL) |
298 | return -EBADFD; | ||
299 | |||
300 | pr_debug("%p %d %d %d\n", sk, llcp_sock->target_idx, | ||
301 | llcp_sock->dsap, llcp_sock->ssap); | ||
294 | 302 | ||
295 | if (llcp_sock == NULL || llcp_sock->dev == NULL) | 303 | if (llcp_sock == NULL || llcp_sock->dev == NULL) |
296 | return -EBADFD; | 304 | return -EBADFD; |
297 | 305 | ||
298 | addr->sa_family = AF_NFC; | 306 | uaddr->sa_family = AF_NFC; |
307 | |||
299 | *len = sizeof(struct sockaddr_nfc_llcp); | 308 | *len = sizeof(struct sockaddr_nfc_llcp); |
300 | 309 | ||
301 | llcp_addr->dev_idx = llcp_sock->dev->idx; | 310 | llcp_addr->dev_idx = llcp_sock->dev->idx; |
311 | llcp_addr->target_idx = llcp_sock->target_idx; | ||
302 | llcp_addr->dsap = llcp_sock->dsap; | 312 | llcp_addr->dsap = llcp_sock->dsap; |
303 | llcp_addr->ssap = llcp_sock->ssap; | 313 | llcp_addr->ssap = llcp_sock->ssap; |
304 | llcp_addr->service_name_len = llcp_sock->service_name_len; | 314 | llcp_addr->service_name_len = llcp_sock->service_name_len; |
@@ -406,7 +416,8 @@ static int llcp_sock_release(struct socket *sock) | |||
406 | } | 416 | } |
407 | } | 417 | } |
408 | 418 | ||
409 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); | 419 | if (llcp_sock->reserved_ssap < LLCP_SAP_MAX) |
420 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); | ||
410 | 421 | ||
411 | release_sock(sk); | 422 | release_sock(sk); |
412 | 423 | ||
@@ -486,6 +497,9 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
486 | ret = -ENOMEM; | 497 | ret = -ENOMEM; |
487 | goto put_dev; | 498 | goto put_dev; |
488 | } | 499 | } |
500 | |||
501 | llcp_sock->reserved_ssap = llcp_sock->ssap; | ||
502 | |||
489 | if (addr->service_name_len == 0) | 503 | if (addr->service_name_len == 0) |
490 | llcp_sock->dsap = addr->dsap; | 504 | llcp_sock->dsap = addr->dsap; |
491 | else | 505 | else |
@@ -687,6 +701,7 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
687 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; | 701 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; |
688 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; | 702 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; |
689 | llcp_sock->remote_ready = 1; | 703 | llcp_sock->remote_ready = 1; |
704 | llcp_sock->reserved_ssap = LLCP_SAP_MAX; | ||
690 | skb_queue_head_init(&llcp_sock->tx_queue); | 705 | skb_queue_head_init(&llcp_sock->tx_queue); |
691 | skb_queue_head_init(&llcp_sock->tx_pending_queue); | 706 | skb_queue_head_init(&llcp_sock->tx_pending_queue); |
692 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); | 707 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 766a02b1dfa1..5bb4da680427 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -194,7 +194,7 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | |||
194 | } | 194 | } |
195 | 195 | ||
196 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | 196 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && |
197 | (protocols & NFC_PROTO_ISO14443_MASK)) { | 197 | (protocols & NFC_PROTO_ISO14443_B_MASK)) { |
198 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = | 198 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = |
199 | NCI_NFC_B_PASSIVE_POLL_MODE; | 199 | NCI_NFC_B_PASSIVE_POLL_MODE; |
200 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | 200 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; |
@@ -486,7 +486,8 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, | |||
486 | param.rf_protocol = NCI_RF_PROTOCOL_T2T; | 486 | param.rf_protocol = NCI_RF_PROTOCOL_T2T; |
487 | else if (protocol == NFC_PROTO_FELICA) | 487 | else if (protocol == NFC_PROTO_FELICA) |
488 | param.rf_protocol = NCI_RF_PROTOCOL_T3T; | 488 | param.rf_protocol = NCI_RF_PROTOCOL_T3T; |
489 | else if (protocol == NFC_PROTO_ISO14443) | 489 | else if (protocol == NFC_PROTO_ISO14443 || |
490 | protocol == NFC_PROTO_ISO14443_B) | ||
490 | param.rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; | 491 | param.rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; |
491 | else | 492 | else |
492 | param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; | 493 | param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; |
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 2ab196a9f228..af7a93b04393 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
@@ -170,7 +170,10 @@ static int nci_add_new_protocol(struct nci_dev *ndev, | |||
170 | if (rf_protocol == NCI_RF_PROTOCOL_T2T) | 170 | if (rf_protocol == NCI_RF_PROTOCOL_T2T) |
171 | protocol = NFC_PROTO_MIFARE_MASK; | 171 | protocol = NFC_PROTO_MIFARE_MASK; |
172 | else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) | 172 | else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) |
173 | protocol = NFC_PROTO_ISO14443_MASK; | 173 | if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) |
174 | protocol = NFC_PROTO_ISO14443_MASK; | ||
175 | else | ||
176 | protocol = NFC_PROTO_ISO14443_B_MASK; | ||
174 | else if (rf_protocol == NCI_RF_PROTOCOL_T3T) | 177 | else if (rf_protocol == NCI_RF_PROTOCOL_T3T) |
175 | protocol = NFC_PROTO_FELICA_MASK; | 178 | protocol = NFC_PROTO_FELICA_MASK; |
176 | else | 179 | else |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index f4f07f9b61c0..4c51714ee741 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -634,6 +634,15 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info) | |||
634 | if (!dev) | 634 | if (!dev) |
635 | return -ENODEV; | 635 | return -ENODEV; |
636 | 636 | ||
637 | device_lock(&dev->dev); | ||
638 | |||
639 | if (!dev->polling) { | ||
640 | device_unlock(&dev->dev); | ||
641 | return -EINVAL; | ||
642 | } | ||
643 | |||
644 | device_unlock(&dev->dev); | ||
645 | |||
637 | mutex_lock(&dev->genl_data.genl_data_mutex); | 646 | mutex_lock(&dev->genl_data.genl_data_mutex); |
638 | 647 | ||
639 | if (dev->genl_data.poll_req_pid != info->snd_pid) { | 648 | if (dev->genl_data.poll_req_pid != info->snd_pid) { |