diff options
author | Eric Lapuyade <eric.lapuyade@intel.com> | 2012-04-10 13:43:06 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-04-12 15:10:34 -0400 |
commit | 8b8d2e08bf0d50193931afd27482a59376b66b2b (patch) | |
tree | 7752d914ca7d89f2f2c00159bb718a53d9980139 /net | |
parent | e1da0efa2ee71df957b280bcfa41f82ce6986a1d (diff) |
NFC: HCI support
This is an implementation of ETSI TS 102 622 specification.
Many NFC chipsets use HCI as the host <-> target protocol on top of a
serial link like i2c.
Signed-off-by: Eric Lapuyade <eric.lapuyade@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/nfc/Kconfig | 1 | ||||
-rw-r--r-- | net/nfc/Makefile | 1 | ||||
-rw-r--r-- | net/nfc/hci/Kconfig | 8 | ||||
-rw-r--r-- | net/nfc/hci/Makefile | 7 | ||||
-rw-r--r-- | net/nfc/hci/command.c | 354 | ||||
-rw-r--r-- | net/nfc/hci/core.c | 830 | ||||
-rw-r--r-- | net/nfc/hci/hci.h | 139 | ||||
-rw-r--r-- | net/nfc/hci/hcp.c | 156 |
8 files changed, 1496 insertions, 0 deletions
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig index 44c865b86d6f..8d8d9bc4b6ff 100644 --- a/net/nfc/Kconfig +++ b/net/nfc/Kconfig | |||
@@ -14,6 +14,7 @@ menuconfig NFC | |||
14 | be called nfc. | 14 | be called nfc. |
15 | 15 | ||
16 | source "net/nfc/nci/Kconfig" | 16 | source "net/nfc/nci/Kconfig" |
17 | source "net/nfc/hci/Kconfig" | ||
17 | source "net/nfc/llcp/Kconfig" | 18 | source "net/nfc/llcp/Kconfig" |
18 | 19 | ||
19 | source "drivers/nfc/Kconfig" | 20 | source "drivers/nfc/Kconfig" |
diff --git a/net/nfc/Makefile b/net/nfc/Makefile index 7b4a6dcfa566..d1a117c2c401 100644 --- a/net/nfc/Makefile +++ b/net/nfc/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_NFC) += nfc.o | 5 | obj-$(CONFIG_NFC) += nfc.o |
6 | obj-$(CONFIG_NFC_NCI) += nci/ | 6 | obj-$(CONFIG_NFC_NCI) += nci/ |
7 | obj-$(CONFIG_NFC_HCI) += hci/ | ||
7 | 8 | ||
8 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o | 9 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o |
9 | nfc-$(CONFIG_NFC_LLCP) += llcp/llcp.o llcp/commands.o llcp/sock.o | 10 | nfc-$(CONFIG_NFC_LLCP) += llcp/llcp.o llcp/commands.o llcp/sock.o |
diff --git a/net/nfc/hci/Kconfig b/net/nfc/hci/Kconfig new file mode 100644 index 000000000000..c32d2d4a9635 --- /dev/null +++ b/net/nfc/hci/Kconfig | |||
@@ -0,0 +1,8 @@ | |||
1 | config NFC_HCI | ||
2 | depends on NFC | ||
3 | tristate "NFC HCI implementation" | ||
4 | default n | ||
5 | help | ||
6 | Say Y here if you want to build support for a kernel NFC HCI | ||
7 | implementation. This is mostly needed for devices that only process | ||
8 | HCI frames, like for example the NXP pn544. | ||
diff --git a/net/nfc/hci/Makefile b/net/nfc/hci/Makefile new file mode 100644 index 000000000000..af17c7be051a --- /dev/null +++ b/net/nfc/hci/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the Linux NFC HCI layer. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_NFC_HCI) += hci.o | ||
6 | |||
7 | hci-y := core.o hcp.o command.o | ||
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c new file mode 100644 index 000000000000..8729abf5f18b --- /dev/null +++ b/net/nfc/hci/command.c | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #define pr_fmt(fmt) "hci: %s: " fmt, __func__ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/module.h> | ||
26 | |||
27 | #include <net/nfc/hci.h> | ||
28 | |||
29 | #include "hci.h" | ||
30 | |||
31 | static int nfc_hci_result_to_errno(u8 result) | ||
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) | ||
45 | { | ||
46 | struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)cb_data; | ||
47 | |||
48 | pr_debug("HCI Cmd completed with HCI result=%d\n", result); | ||
49 | |||
50 | hcp_ew->exec_result = nfc_hci_result_to_errno(result); | ||
51 | if (hcp_ew->exec_result == 0) | ||
52 | hcp_ew->result_skb = skb; | ||
53 | else | ||
54 | kfree_skb(skb); | ||
55 | hcp_ew->exec_complete = true; | ||
56 | |||
57 | wake_up(hcp_ew->wq); | ||
58 | } | ||
59 | |||
60 | static int nfc_hci_execute_cmd(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | ||
61 | const u8 *param, size_t param_len, | ||
62 | struct sk_buff **skb) | ||
63 | { | ||
64 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(ew_wq); | ||
65 | struct hcp_exec_waiter hcp_ew; | ||
66 | hcp_ew.wq = &ew_wq; | ||
67 | hcp_ew.exec_complete = false; | ||
68 | hcp_ew.result_skb = NULL; | ||
69 | |||
70 | pr_debug("through pipe=%d, cmd=%d, plen=%zd\n", pipe, cmd, param_len); | ||
71 | |||
72 | /* TODO: Define hci cmd execution delay. Should it be the same | ||
73 | * for all commands? | ||
74 | */ | ||
75 | hcp_ew.exec_result = nfc_hci_hcp_message_tx(hdev, pipe, | ||
76 | NFC_HCI_HCP_COMMAND, cmd, | ||
77 | param, param_len, | ||
78 | nfc_hci_execute_cb, &hcp_ew, | ||
79 | 3000); | ||
80 | if (hcp_ew.exec_result < 0) | ||
81 | return hcp_ew.exec_result; | ||
82 | |||
83 | wait_event(ew_wq, hcp_ew.exec_complete == true); | ||
84 | |||
85 | if (hcp_ew.exec_result == 0) { | ||
86 | if (skb) | ||
87 | *skb = hcp_ew.result_skb; | ||
88 | else | ||
89 | kfree_skb(hcp_ew.result_skb); | ||
90 | } | ||
91 | |||
92 | return hcp_ew.exec_result; | ||
93 | } | ||
94 | |||
95 | int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, | ||
96 | const u8 *param, size_t param_len) | ||
97 | { | ||
98 | u8 pipe; | ||
99 | |||
100 | pr_debug("%d to gate %d\n", event, gate); | ||
101 | |||
102 | pipe = hdev->gate2pipe[gate]; | ||
103 | if (pipe == NFC_HCI_INVALID_PIPE) | ||
104 | return -EADDRNOTAVAIL; | ||
105 | |||
106 | return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_EVENT, event, | ||
107 | param, param_len, NULL, NULL, 0); | ||
108 | } | ||
109 | EXPORT_SYMBOL(nfc_hci_send_event); | ||
110 | |||
111 | int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response, | ||
112 | const u8 *param, size_t param_len) | ||
113 | { | ||
114 | u8 pipe; | ||
115 | |||
116 | pr_debug("\n"); | ||
117 | |||
118 | pipe = hdev->gate2pipe[gate]; | ||
119 | if (pipe == NFC_HCI_INVALID_PIPE) | ||
120 | return -EADDRNOTAVAIL; | ||
121 | |||
122 | return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_RESPONSE, | ||
123 | response, param, param_len, NULL, NULL, | ||
124 | 0); | ||
125 | } | ||
126 | EXPORT_SYMBOL(nfc_hci_send_response); | ||
127 | |||
128 | /* | ||
129 | * Execute an hci command sent to gate. | ||
130 | * skb will contain response data if success. skb can be NULL if you are not | ||
131 | * interested by the response. | ||
132 | */ | ||
133 | int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, | ||
134 | const u8 *param, size_t param_len, struct sk_buff **skb) | ||
135 | { | ||
136 | u8 pipe; | ||
137 | |||
138 | pr_debug("\n"); | ||
139 | |||
140 | pipe = hdev->gate2pipe[gate]; | ||
141 | if (pipe == NFC_HCI_INVALID_PIPE) | ||
142 | return -EADDRNOTAVAIL; | ||
143 | |||
144 | return nfc_hci_execute_cmd(hdev, pipe, cmd, param, param_len, skb); | ||
145 | } | ||
146 | EXPORT_SYMBOL(nfc_hci_send_cmd); | ||
147 | |||
148 | int nfc_hci_set_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, | ||
149 | const u8 *param, size_t param_len) | ||
150 | { | ||
151 | int r; | ||
152 | u8 *tmp; | ||
153 | |||
154 | /* TODO ELa: reg idx must be inserted before param, but we don't want | ||
155 | * to ask the caller to do it to keep a simpler API. | ||
156 | * For now, just create a new temporary param buffer. This is far from | ||
157 | * optimal though, and the plan is to modify APIs to pass idx down to | ||
158 | * nfc_hci_hcp_message_tx where the frame is actually built, thereby | ||
159 | * eliminating the need for the temp allocation-copy here. | ||
160 | */ | ||
161 | |||
162 | pr_debug("idx=%d to gate %d\n", idx, gate); | ||
163 | |||
164 | tmp = kmalloc(1 + param_len, GFP_KERNEL); | ||
165 | if (tmp == NULL) | ||
166 | return -ENOMEM; | ||
167 | |||
168 | *tmp = idx; | ||
169 | memcpy(tmp + 1, param, param_len); | ||
170 | |||
171 | r = nfc_hci_send_cmd(hdev, gate, NFC_HCI_ANY_SET_PARAMETER, | ||
172 | tmp, param_len + 1, NULL); | ||
173 | |||
174 | kfree(tmp); | ||
175 | |||
176 | return r; | ||
177 | } | ||
178 | EXPORT_SYMBOL(nfc_hci_set_param); | ||
179 | |||
180 | int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, | ||
181 | struct sk_buff **skb) | ||
182 | { | ||
183 | pr_debug("gate=%d regidx=%d\n", gate, idx); | ||
184 | |||
185 | return nfc_hci_send_cmd(hdev, gate, NFC_HCI_ANY_GET_PARAMETER, | ||
186 | &idx, 1, skb); | ||
187 | } | ||
188 | EXPORT_SYMBOL(nfc_hci_get_param); | ||
189 | |||
190 | static int nfc_hci_open_pipe(struct nfc_hci_dev *hdev, u8 pipe) | ||
191 | { | ||
192 | struct sk_buff *skb; | ||
193 | int r; | ||
194 | |||
195 | pr_debug("pipe=%d\n", pipe); | ||
196 | |||
197 | r = nfc_hci_execute_cmd(hdev, pipe, NFC_HCI_ANY_OPEN_PIPE, | ||
198 | NULL, 0, &skb); | ||
199 | if (r == 0) { | ||
200 | /* dest host other than host controller will send | ||
201 | * number of pipes already open on this gate before | ||
202 | * execution. The number can be found in skb->data[0] | ||
203 | */ | ||
204 | kfree_skb(skb); | ||
205 | } | ||
206 | |||
207 | return r; | ||
208 | } | ||
209 | |||
210 | static int nfc_hci_close_pipe(struct nfc_hci_dev *hdev, u8 pipe) | ||
211 | { | ||
212 | pr_debug("\n"); | ||
213 | |||
214 | return nfc_hci_execute_cmd(hdev, pipe, NFC_HCI_ANY_CLOSE_PIPE, | ||
215 | NULL, 0, NULL); | ||
216 | } | ||
217 | |||
218 | static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host, | ||
219 | u8 dest_gate, int *result) | ||
220 | { | ||
221 | struct sk_buff *skb; | ||
222 | struct hci_create_pipe_params params; | ||
223 | struct hci_create_pipe_resp *resp; | ||
224 | u8 pipe; | ||
225 | |||
226 | pr_debug("gate=%d\n", dest_gate); | ||
227 | |||
228 | params.src_gate = NFC_HCI_ADMIN_GATE; | ||
229 | params.dest_host = dest_host; | ||
230 | params.dest_gate = dest_gate; | ||
231 | |||
232 | *result = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, | ||
233 | NFC_HCI_ADM_CREATE_PIPE, | ||
234 | (u8 *) ¶ms, sizeof(params), &skb); | ||
235 | if (*result == 0) { | ||
236 | resp = (struct hci_create_pipe_resp *)skb->data; | ||
237 | pipe = resp->pipe; | ||
238 | kfree_skb(skb); | ||
239 | |||
240 | pr_debug("pipe created=%d\n", pipe); | ||
241 | |||
242 | return pipe; | ||
243 | } else | ||
244 | return NFC_HCI_INVALID_PIPE; | ||
245 | } | ||
246 | |||
247 | static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) | ||
248 | { | ||
249 | pr_debug("\n"); | ||
250 | |||
251 | return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, | ||
252 | NFC_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL); | ||
253 | } | ||
254 | |||
255 | static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) | ||
256 | { | ||
257 | int r; | ||
258 | |||
259 | u8 param[2]; | ||
260 | |||
261 | /* TODO: Find out what the identity reference data is | ||
262 | * and fill param with it. HCI spec 6.1.3.5 */ | ||
263 | |||
264 | pr_debug("\n"); | ||
265 | |||
266 | r = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, | ||
267 | NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) | ||
273 | { | ||
274 | int r; | ||
275 | u8 pipe = hdev->gate2pipe[gate]; | ||
276 | |||
277 | pr_debug("\n"); | ||
278 | |||
279 | if (pipe == NFC_HCI_INVALID_PIPE) | ||
280 | return -EADDRNOTAVAIL; | ||
281 | |||
282 | r = nfc_hci_close_pipe(hdev, pipe); | ||
283 | if (r < 0) | ||
284 | return r; | ||
285 | |||
286 | if (pipe != NFC_HCI_LINK_MGMT_PIPE && pipe != NFC_HCI_ADMIN_PIPE) { | ||
287 | r = nfc_hci_delete_pipe(hdev, pipe); | ||
288 | if (r < 0) | ||
289 | return r; | ||
290 | } | ||
291 | |||
292 | hdev->gate2pipe[gate] = NFC_HCI_INVALID_PIPE; | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | EXPORT_SYMBOL(nfc_hci_disconnect_gate); | ||
297 | |||
298 | int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev) | ||
299 | { | ||
300 | int r; | ||
301 | |||
302 | pr_debug("\n"); | ||
303 | |||
304 | r = nfc_hci_clear_all_pipes(hdev); | ||
305 | if (r < 0) | ||
306 | return r; | ||
307 | |||
308 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | EXPORT_SYMBOL(nfc_hci_disconnect_all_gates); | ||
313 | |||
314 | int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate) | ||
315 | { | ||
316 | u8 pipe = NFC_HCI_INVALID_PIPE; | ||
317 | bool pipe_created = false; | ||
318 | int r; | ||
319 | |||
320 | pr_debug("\n"); | ||
321 | |||
322 | if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) | ||
323 | return -EADDRINUSE; | ||
324 | |||
325 | switch (dest_gate) { | ||
326 | case NFC_HCI_LINK_MGMT_GATE: | ||
327 | pipe = NFC_HCI_LINK_MGMT_PIPE; | ||
328 | break; | ||
329 | case NFC_HCI_ADMIN_GATE: | ||
330 | pipe = NFC_HCI_ADMIN_PIPE; | ||
331 | break; | ||
332 | default: | ||
333 | pipe = nfc_hci_create_pipe(hdev, dest_host, dest_gate, &r); | ||
334 | if (pipe == NFC_HCI_INVALID_PIPE) | ||
335 | return r; | ||
336 | pipe_created = true; | ||
337 | break; | ||
338 | } | ||
339 | |||
340 | r = nfc_hci_open_pipe(hdev, pipe); | ||
341 | if (r < 0) { | ||
342 | if (pipe_created) | ||
343 | if (nfc_hci_delete_pipe(hdev, pipe) < 0) { | ||
344 | /* TODO: Cannot clean by deleting pipe... | ||
345 | * -> inconsistent state */ | ||
346 | } | ||
347 | return r; | ||
348 | } | ||
349 | |||
350 | hdev->gate2pipe[dest_gate] = pipe; | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | EXPORT_SYMBOL(nfc_hci_connect_gate); | ||
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c new file mode 100644 index 000000000000..86fd00d5a099 --- /dev/null +++ b/net/nfc/hci/core.c | |||
@@ -0,0 +1,830 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #define pr_fmt(fmt) "hci: %s: " fmt, __func__ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/nfc.h> | ||
26 | |||
27 | #include <net/nfc/nfc.h> | ||
28 | #include <net/nfc/hci.h> | ||
29 | |||
30 | #include "hci.h" | ||
31 | |||
32 | /* Largest headroom needed for outgoing HCI commands */ | ||
33 | #define HCI_CMDS_HEADROOM 1 | ||
34 | |||
35 | static void nfc_hci_msg_tx_work(struct work_struct *work) | ||
36 | { | ||
37 | struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev, | ||
38 | msg_tx_work); | ||
39 | struct hci_msg *msg; | ||
40 | struct sk_buff *skb; | ||
41 | int r = 0; | ||
42 | |||
43 | mutex_lock(&hdev->msg_tx_mutex); | ||
44 | |||
45 | if (hdev->cmd_pending_msg) { | ||
46 | if (timer_pending(&hdev->cmd_timer) == 0) { | ||
47 | if (hdev->cmd_pending_msg->cb) | ||
48 | hdev->cmd_pending_msg->cb(hdev, | ||
49 | NFC_HCI_ANY_E_TIMEOUT, | ||
50 | NULL, | ||
51 | hdev-> | ||
52 | cmd_pending_msg-> | ||
53 | cb_context); | ||
54 | kfree(hdev->cmd_pending_msg); | ||
55 | hdev->cmd_pending_msg = NULL; | ||
56 | } else | ||
57 | goto exit; | ||
58 | } | ||
59 | |||
60 | next_msg: | ||
61 | if (list_empty(&hdev->msg_tx_queue)) | ||
62 | goto exit; | ||
63 | |||
64 | msg = list_first_entry(&hdev->msg_tx_queue, struct hci_msg, msg_l); | ||
65 | list_del(&msg->msg_l); | ||
66 | |||
67 | pr_debug("msg_tx_queue has a cmd to send\n"); | ||
68 | while ((skb = skb_dequeue(&msg->msg_frags)) != NULL) { | ||
69 | r = hdev->ops->xmit(hdev, skb); | ||
70 | if (r < 0) { | ||
71 | kfree_skb(skb); | ||
72 | skb_queue_purge(&msg->msg_frags); | ||
73 | if (msg->cb) | ||
74 | msg->cb(hdev, NFC_HCI_ANY_E_NOK, NULL, | ||
75 | msg->cb_context); | ||
76 | kfree(msg); | ||
77 | break; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | if (r) | ||
82 | goto next_msg; | ||
83 | |||
84 | if (msg->wait_response == false) { | ||
85 | kfree(msg); | ||
86 | goto next_msg; | ||
87 | } | ||
88 | |||
89 | hdev->cmd_pending_msg = msg; | ||
90 | mod_timer(&hdev->cmd_timer, jiffies + | ||
91 | msecs_to_jiffies(hdev->cmd_pending_msg->completion_delay)); | ||
92 | |||
93 | exit: | ||
94 | mutex_unlock(&hdev->msg_tx_mutex); | ||
95 | } | ||
96 | |||
97 | static void nfc_hci_msg_rx_work(struct work_struct *work) | ||
98 | { | ||
99 | struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev, | ||
100 | msg_rx_work); | ||
101 | struct sk_buff *skb; | ||
102 | struct hcp_message *message; | ||
103 | u8 pipe; | ||
104 | u8 type; | ||
105 | u8 instruction; | ||
106 | |||
107 | while ((skb = skb_dequeue(&hdev->msg_rx_queue)) != NULL) { | ||
108 | pipe = skb->data[0]; | ||
109 | skb_pull(skb, NFC_HCI_HCP_PACKET_HEADER_LEN); | ||
110 | message = (struct hcp_message *)skb->data; | ||
111 | type = HCP_MSG_GET_TYPE(message->header); | ||
112 | instruction = HCP_MSG_GET_CMD(message->header); | ||
113 | skb_pull(skb, NFC_HCI_HCP_MESSAGE_HEADER_LEN); | ||
114 | |||
115 | nfc_hci_hcp_message_rx(hdev, pipe, type, instruction, skb); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, | ||
120 | struct sk_buff *skb) | ||
121 | { | ||
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); | ||
130 | |||
131 | if (hdev->cmd_pending_msg->cb) | ||
132 | hdev->cmd_pending_msg->cb(hdev, result, skb, | ||
133 | hdev->cmd_pending_msg->cb_context); | ||
134 | else | ||
135 | kfree_skb(skb); | ||
136 | |||
137 | kfree(hdev->cmd_pending_msg); | ||
138 | hdev->cmd_pending_msg = NULL; | ||
139 | |||
140 | queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); | ||
141 | |||
142 | exit: | ||
143 | mutex_unlock(&hdev->msg_tx_mutex); | ||
144 | } | ||
145 | |||
146 | void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | ||
147 | struct sk_buff *skb) | ||
148 | { | ||
149 | kfree_skb(skb); | ||
150 | } | ||
151 | |||
152 | static u32 nfc_hci_sak_to_protocol(u8 sak) | ||
153 | { | ||
154 | switch (NFC_HCI_TYPE_A_SEL_PROT(sak)) { | ||
155 | case NFC_HCI_TYPE_A_SEL_PROT_MIFARE: | ||
156 | return NFC_PROTO_MIFARE_MASK; | ||
157 | case NFC_HCI_TYPE_A_SEL_PROT_ISO14443: | ||
158 | return NFC_PROTO_ISO14443_MASK; | ||
159 | case NFC_HCI_TYPE_A_SEL_PROT_DEP: | ||
160 | return NFC_PROTO_NFC_DEP_MASK; | ||
161 | case NFC_HCI_TYPE_A_SEL_PROT_ISO14443_DEP: | ||
162 | return NFC_PROTO_ISO14443_MASK | NFC_PROTO_NFC_DEP_MASK; | ||
163 | default: | ||
164 | return 0xffffffff; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) | ||
169 | { | ||
170 | struct nfc_target *targets; | ||
171 | struct sk_buff *atqa_skb = NULL; | ||
172 | struct sk_buff *sak_skb = NULL; | ||
173 | int r; | ||
174 | |||
175 | pr_debug("from gate %d\n", gate); | ||
176 | |||
177 | targets = kzalloc(sizeof(struct nfc_target), GFP_KERNEL); | ||
178 | if (targets == NULL) | ||
179 | return -ENOMEM; | ||
180 | |||
181 | switch (gate) { | ||
182 | case NFC_HCI_RF_READER_A_GATE: | ||
183 | r = nfc_hci_get_param(hdev, NFC_HCI_RF_READER_A_GATE, | ||
184 | NFC_HCI_RF_READER_A_ATQA, &atqa_skb); | ||
185 | if (r < 0) | ||
186 | goto exit; | ||
187 | |||
188 | r = nfc_hci_get_param(hdev, NFC_HCI_RF_READER_A_GATE, | ||
189 | NFC_HCI_RF_READER_A_SAK, &sak_skb); | ||
190 | if (r < 0) | ||
191 | goto exit; | ||
192 | |||
193 | if (atqa_skb->len != 2 || sak_skb->len != 1) { | ||
194 | r = -EPROTO; | ||
195 | goto exit; | ||
196 | } | ||
197 | |||
198 | targets->supported_protocols = | ||
199 | nfc_hci_sak_to_protocol(sak_skb->data[0]); | ||
200 | if (targets->supported_protocols == 0xffffffff) { | ||
201 | r = -EPROTO; | ||
202 | goto exit; | ||
203 | } | ||
204 | |||
205 | targets->sens_res = be16_to_cpu(*(u16 *)atqa_skb->data); | ||
206 | targets->sel_res = sak_skb->data[0]; | ||
207 | |||
208 | if (hdev->ops->complete_target_discovered) { | ||
209 | r = hdev->ops->complete_target_discovered(hdev, gate, | ||
210 | targets); | ||
211 | if (r < 0) | ||
212 | goto exit; | ||
213 | } | ||
214 | break; | ||
215 | case NFC_HCI_RF_READER_B_GATE: | ||
216 | targets->supported_protocols = NFC_PROTO_ISO14443_MASK; | ||
217 | break; | ||
218 | default: | ||
219 | if (hdev->ops->target_from_gate) | ||
220 | r = hdev->ops->target_from_gate(hdev, gate, targets); | ||
221 | else | ||
222 | r = -EPROTO; | ||
223 | if (r < 0) | ||
224 | goto exit; | ||
225 | |||
226 | if (hdev->ops->complete_target_discovered) { | ||
227 | r = hdev->ops->complete_target_discovered(hdev, gate, | ||
228 | targets); | ||
229 | if (r < 0) | ||
230 | goto exit; | ||
231 | } | ||
232 | break; | ||
233 | } | ||
234 | |||
235 | targets->hci_reader_gate = gate; | ||
236 | |||
237 | r = nfc_targets_found(hdev->ndev, targets, 1); | ||
238 | if (r < 0) | ||
239 | goto exit; | ||
240 | |||
241 | kfree(hdev->targets); | ||
242 | hdev->targets = targets; | ||
243 | targets = NULL; | ||
244 | hdev->target_count = 1; | ||
245 | |||
246 | exit: | ||
247 | kfree(targets); | ||
248 | kfree_skb(atqa_skb); | ||
249 | kfree_skb(sak_skb); | ||
250 | |||
251 | return r; | ||
252 | } | ||
253 | |||
254 | void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | ||
255 | struct sk_buff *skb) | ||
256 | { | ||
257 | int r = 0; | ||
258 | |||
259 | switch (event) { | ||
260 | case NFC_HCI_EVT_TARGET_DISCOVERED: | ||
261 | if (hdev->poll_started == false) { | ||
262 | r = -EPROTO; | ||
263 | goto exit; | ||
264 | } | ||
265 | |||
266 | if (skb->len < 1) { /* no status data? */ | ||
267 | r = -EPROTO; | ||
268 | goto exit; | ||
269 | } | ||
270 | |||
271 | if (skb->data[0] == 3) { | ||
272 | /* TODO: Multiple targets in field, none activated | ||
273 | * poll is supposedly stopped, but there is no | ||
274 | * single target to activate, so nothing to report | ||
275 | * up. | ||
276 | * if we need to restart poll, we must save the | ||
277 | * protocols from the initial poll and reuse here. | ||
278 | */ | ||
279 | } | ||
280 | |||
281 | if (skb->data[0] != 0) { | ||
282 | r = -EPROTO; | ||
283 | goto exit; | ||
284 | } | ||
285 | |||
286 | r = nfc_hci_target_discovered(hdev, | ||
287 | nfc_hci_pipe2gate(hdev, pipe)); | ||
288 | break; | ||
289 | default: | ||
290 | /* TODO: Unknown events are hardware specific | ||
291 | * pass them to the driver (needs a new hci_ops) */ | ||
292 | break; | ||
293 | } | ||
294 | |||
295 | exit: | ||
296 | kfree_skb(skb); | ||
297 | |||
298 | if (r) { | ||
299 | /* TODO: There was an error dispatching the event, | ||
300 | * how to propagate up to nfc core? | ||
301 | */ | ||
302 | } | ||
303 | } | ||
304 | |||
305 | static void nfc_hci_cmd_timeout(unsigned long data) | ||
306 | { | ||
307 | struct nfc_hci_dev *hdev = (struct nfc_hci_dev *)data; | ||
308 | |||
309 | queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); | ||
310 | } | ||
311 | |||
312 | static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count, | ||
313 | u8 gates[]) | ||
314 | { | ||
315 | int r; | ||
316 | u8 *p = gates; | ||
317 | while (gate_count--) { | ||
318 | r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, *p); | ||
319 | if (r < 0) | ||
320 | return r; | ||
321 | p++; | ||
322 | } | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int hci_dev_session_init(struct nfc_hci_dev *hdev) | ||
328 | { | ||
329 | struct sk_buff *skb = NULL; | ||
330 | int r; | ||
331 | u8 hci_gates[] = { /* NFC_HCI_ADMIN_GATE MUST be first */ | ||
332 | NFC_HCI_ADMIN_GATE, NFC_HCI_LOOPBACK_GATE, | ||
333 | NFC_HCI_ID_MGMT_GATE, NFC_HCI_LINK_MGMT_GATE, | ||
334 | NFC_HCI_RF_READER_B_GATE, NFC_HCI_RF_READER_A_GATE | ||
335 | }; | ||
336 | |||
337 | r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, | ||
338 | NFC_HCI_ADMIN_GATE); | ||
339 | if (r < 0) | ||
340 | goto exit; | ||
341 | |||
342 | r = nfc_hci_get_param(hdev, NFC_HCI_ADMIN_GATE, | ||
343 | NFC_HCI_ADMIN_SESSION_IDENTITY, &skb); | ||
344 | if (r < 0) | ||
345 | goto disconnect_all; | ||
346 | |||
347 | if (skb->len && skb->len == strlen(hdev->init_data.session_id)) | ||
348 | if (memcmp(hdev->init_data.session_id, skb->data, | ||
349 | skb->len) == 0) { | ||
350 | /* TODO ELa: restore gate<->pipe table from | ||
351 | * some TBD location. | ||
352 | * note: it doesn't seem possible to get the chip | ||
353 | * currently open gate/pipe table. | ||
354 | * It is only possible to obtain the supported | ||
355 | * gate list. | ||
356 | */ | ||
357 | |||
358 | /* goto exit | ||
359 | * For now, always do a full initialization */ | ||
360 | } | ||
361 | |||
362 | r = nfc_hci_disconnect_all_gates(hdev); | ||
363 | if (r < 0) | ||
364 | goto exit; | ||
365 | |||
366 | r = hci_dev_connect_gates(hdev, sizeof(hci_gates), hci_gates); | ||
367 | if (r < 0) | ||
368 | goto disconnect_all; | ||
369 | |||
370 | r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, | ||
371 | hdev->init_data.gates); | ||
372 | if (r < 0) | ||
373 | goto disconnect_all; | ||
374 | |||
375 | r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, | ||
376 | NFC_HCI_ADMIN_SESSION_IDENTITY, | ||
377 | hdev->init_data.session_id, | ||
378 | strlen(hdev->init_data.session_id)); | ||
379 | if (r == 0) | ||
380 | goto exit; | ||
381 | |||
382 | disconnect_all: | ||
383 | nfc_hci_disconnect_all_gates(hdev); | ||
384 | |||
385 | exit: | ||
386 | if (skb) | ||
387 | kfree_skb(skb); | ||
388 | |||
389 | return r; | ||
390 | } | ||
391 | |||
392 | static int hci_dev_version(struct nfc_hci_dev *hdev) | ||
393 | { | ||
394 | int r; | ||
395 | struct sk_buff *skb; | ||
396 | |||
397 | r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, | ||
398 | NFC_HCI_ID_MGMT_VERSION_SW, &skb); | ||
399 | if (r < 0) | ||
400 | return r; | ||
401 | |||
402 | if (skb->len != 3) { | ||
403 | kfree_skb(skb); | ||
404 | return -EINVAL; | ||
405 | } | ||
406 | |||
407 | hdev->sw_romlib = (skb->data[0] & 0xf0) >> 4; | ||
408 | hdev->sw_patch = skb->data[0] & 0x0f; | ||
409 | hdev->sw_flashlib_major = skb->data[1]; | ||
410 | hdev->sw_flashlib_minor = skb->data[2]; | ||
411 | |||
412 | kfree_skb(skb); | ||
413 | |||
414 | r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, | ||
415 | NFC_HCI_ID_MGMT_VERSION_HW, &skb); | ||
416 | if (r < 0) | ||
417 | return r; | ||
418 | |||
419 | if (skb->len != 3) { | ||
420 | kfree_skb(skb); | ||
421 | return -EINVAL; | ||
422 | } | ||
423 | |||
424 | hdev->hw_derivative = (skb->data[0] & 0xe0) >> 5; | ||
425 | hdev->hw_version = skb->data[0] & 0x1f; | ||
426 | hdev->hw_mpw = (skb->data[1] & 0xc0) >> 6; | ||
427 | hdev->hw_software = skb->data[1] & 0x3f; | ||
428 | hdev->hw_bsid = skb->data[2]; | ||
429 | |||
430 | kfree_skb(skb); | ||
431 | |||
432 | pr_info("SOFTWARE INFO:\n"); | ||
433 | pr_info("RomLib : %d\n", hdev->sw_romlib); | ||
434 | pr_info("Patch : %d\n", hdev->sw_patch); | ||
435 | pr_info("FlashLib Major : %d\n", hdev->sw_flashlib_major); | ||
436 | pr_info("FlashLib Minor : %d\n", hdev->sw_flashlib_minor); | ||
437 | pr_info("HARDWARE INFO:\n"); | ||
438 | pr_info("Derivative : %d\n", hdev->hw_derivative); | ||
439 | pr_info("HW Version : %d\n", hdev->hw_version); | ||
440 | pr_info("#MPW : %d\n", hdev->hw_mpw); | ||
441 | pr_info("Software : %d\n", hdev->hw_software); | ||
442 | pr_info("BSID Version : %d\n", hdev->hw_bsid); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int hci_dev_up(struct nfc_dev *nfc_dev) | ||
448 | { | ||
449 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
450 | int r = 0; | ||
451 | |||
452 | if (hdev->ops->open) { | ||
453 | r = hdev->ops->open(hdev); | ||
454 | if (r < 0) | ||
455 | return r; | ||
456 | } | ||
457 | |||
458 | r = hci_dev_session_init(hdev); | ||
459 | if (r < 0) | ||
460 | goto exit; | ||
461 | |||
462 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
463 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
464 | if (r < 0) | ||
465 | goto exit; | ||
466 | |||
467 | if (hdev->ops->hci_ready) { | ||
468 | r = hdev->ops->hci_ready(hdev); | ||
469 | if (r < 0) | ||
470 | goto exit; | ||
471 | } | ||
472 | |||
473 | r = hci_dev_version(hdev); | ||
474 | if (r < 0) | ||
475 | goto exit; | ||
476 | |||
477 | exit: | ||
478 | if (r < 0) | ||
479 | if (hdev->ops->close) | ||
480 | hdev->ops->close(hdev); | ||
481 | return r; | ||
482 | } | ||
483 | |||
484 | static int hci_dev_down(struct nfc_dev *nfc_dev) | ||
485 | { | ||
486 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
487 | |||
488 | if (hdev->ops->close) | ||
489 | hdev->ops->close(hdev); | ||
490 | |||
491 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static int hci_start_poll(struct nfc_dev *nfc_dev, u32 protocols) | ||
497 | { | ||
498 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
499 | int r; | ||
500 | |||
501 | if (hdev->ops->start_poll) | ||
502 | r = hdev->ops->start_poll(hdev, protocols); | ||
503 | else | ||
504 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
505 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | ||
506 | if (r == 0) | ||
507 | hdev->poll_started = true; | ||
508 | |||
509 | return r; | ||
510 | } | ||
511 | |||
512 | static void hci_stop_poll(struct nfc_dev *nfc_dev) | ||
513 | { | ||
514 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
515 | |||
516 | if (hdev->poll_started) { | ||
517 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
518 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
519 | hdev->poll_started = false; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | static struct nfc_target *hci_find_target(struct nfc_hci_dev *hdev, | ||
524 | u32 target_idx) | ||
525 | { | ||
526 | int i; | ||
527 | if (hdev->poll_started == false || hdev->targets == NULL) | ||
528 | return NULL; | ||
529 | |||
530 | for (i = 0; i < hdev->target_count; i++) { | ||
531 | if (hdev->targets[i].idx == target_idx) | ||
532 | return &hdev->targets[i]; | ||
533 | } | ||
534 | |||
535 | return NULL; | ||
536 | } | ||
537 | |||
538 | static int hci_activate_target(struct nfc_dev *nfc_dev, u32 target_idx, | ||
539 | u32 protocol) | ||
540 | { | ||
541 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
542 | |||
543 | if (hci_find_target(hdev, target_idx) == NULL) | ||
544 | return -ENOMEDIUM; | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static void hci_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx) | ||
550 | { | ||
551 | } | ||
552 | |||
553 | static int hci_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx, | ||
554 | struct sk_buff *skb, data_exchange_cb_t cb, | ||
555 | void *cb_context) | ||
556 | { | ||
557 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
558 | int r; | ||
559 | struct nfc_target *target; | ||
560 | struct sk_buff *res_skb = NULL; | ||
561 | |||
562 | pr_debug("target_idx=%d\n", target_idx); | ||
563 | |||
564 | target = hci_find_target(hdev, target_idx); | ||
565 | if (target == NULL) | ||
566 | return -ENOMEDIUM; | ||
567 | |||
568 | switch (target->hci_reader_gate) { | ||
569 | case NFC_HCI_RF_READER_A_GATE: | ||
570 | case NFC_HCI_RF_READER_B_GATE: | ||
571 | if (hdev->ops->data_exchange) { | ||
572 | r = hdev->ops->data_exchange(hdev, target, skb, | ||
573 | &res_skb); | ||
574 | if (r <= 0) /* handled */ | ||
575 | break; | ||
576 | } | ||
577 | |||
578 | *skb_push(skb, 1) = 0; /* CTR, see spec:10.2.2.1 */ | ||
579 | r = nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
580 | NFC_HCI_WR_XCHG_DATA, | ||
581 | skb->data, skb->len, &res_skb); | ||
582 | /* | ||
583 | * TODO: Check RF Error indicator to make sure data is valid. | ||
584 | * It seems that HCI cmd can complete without error, but data | ||
585 | * can be invalid if an RF error occured? Ignore for now. | ||
586 | */ | ||
587 | if (r == 0) | ||
588 | skb_trim(res_skb, res_skb->len - 1); /* RF Err ind */ | ||
589 | break; | ||
590 | default: | ||
591 | if (hdev->ops->data_exchange) { | ||
592 | r = hdev->ops->data_exchange(hdev, target, skb, | ||
593 | &res_skb); | ||
594 | if (r == 1) | ||
595 | r = -ENOTSUPP; | ||
596 | } | ||
597 | else | ||
598 | r = -ENOTSUPP; | ||
599 | } | ||
600 | |||
601 | kfree_skb(skb); | ||
602 | |||
603 | cb(cb_context, res_skb, r); | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | struct nfc_ops hci_nfc_ops = { | ||
609 | .dev_up = hci_dev_up, | ||
610 | .dev_down = hci_dev_down, | ||
611 | .start_poll = hci_start_poll, | ||
612 | .stop_poll = hci_stop_poll, | ||
613 | .activate_target = hci_activate_target, | ||
614 | .deactivate_target = hci_deactivate_target, | ||
615 | .data_exchange = hci_data_exchange, | ||
616 | }; | ||
617 | |||
618 | struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, | ||
619 | struct nfc_hci_init_data *init_data, | ||
620 | u32 protocols, | ||
621 | int tx_headroom, | ||
622 | int tx_tailroom, | ||
623 | int max_link_payload) | ||
624 | { | ||
625 | struct nfc_hci_dev *hdev; | ||
626 | |||
627 | if (ops->xmit == NULL) | ||
628 | return NULL; | ||
629 | |||
630 | if (protocols == 0) | ||
631 | return NULL; | ||
632 | |||
633 | hdev = kzalloc(sizeof(struct nfc_hci_dev), GFP_KERNEL); | ||
634 | if (hdev == NULL) | ||
635 | return NULL; | ||
636 | |||
637 | hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, | ||
638 | tx_headroom + HCI_CMDS_HEADROOM, | ||
639 | tx_tailroom); | ||
640 | if (!hdev->ndev) { | ||
641 | kfree(hdev); | ||
642 | return NULL; | ||
643 | } | ||
644 | |||
645 | hdev->ops = ops; | ||
646 | hdev->max_data_link_payload = max_link_payload; | ||
647 | hdev->init_data = *init_data; | ||
648 | |||
649 | nfc_set_drvdata(hdev->ndev, hdev); | ||
650 | |||
651 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); | ||
652 | |||
653 | return hdev; | ||
654 | } | ||
655 | EXPORT_SYMBOL(nfc_hci_allocate_device); | ||
656 | |||
657 | void nfc_hci_free_device(struct nfc_hci_dev *hdev) | ||
658 | { | ||
659 | nfc_free_device(hdev->ndev); | ||
660 | kfree(hdev); | ||
661 | } | ||
662 | EXPORT_SYMBOL(nfc_hci_free_device); | ||
663 | |||
664 | int nfc_hci_register_device(struct nfc_hci_dev *hdev) | ||
665 | { | ||
666 | struct device *dev = &hdev->ndev->dev; | ||
667 | const char *devname = dev_name(dev); | ||
668 | char name[32]; | ||
669 | int r = 0; | ||
670 | |||
671 | mutex_init(&hdev->msg_tx_mutex); | ||
672 | |||
673 | INIT_LIST_HEAD(&hdev->msg_tx_queue); | ||
674 | |||
675 | INIT_WORK(&hdev->msg_tx_work, nfc_hci_msg_tx_work); | ||
676 | snprintf(name, sizeof(name), "%s_hci_msg_tx_wq", devname); | ||
677 | hdev->msg_tx_wq = alloc_workqueue(name, WQ_NON_REENTRANT | WQ_UNBOUND | | ||
678 | WQ_MEM_RECLAIM, 1); | ||
679 | if (hdev->msg_tx_wq == NULL) { | ||
680 | r = -ENOMEM; | ||
681 | goto exit; | ||
682 | } | ||
683 | |||
684 | init_timer(&hdev->cmd_timer); | ||
685 | hdev->cmd_timer.data = (unsigned long)hdev; | ||
686 | hdev->cmd_timer.function = nfc_hci_cmd_timeout; | ||
687 | |||
688 | skb_queue_head_init(&hdev->rx_hcp_frags); | ||
689 | |||
690 | INIT_WORK(&hdev->msg_rx_work, nfc_hci_msg_rx_work); | ||
691 | snprintf(name, sizeof(name), "%s_hci_msg_rx_wq", devname); | ||
692 | hdev->msg_rx_wq = alloc_workqueue(name, WQ_NON_REENTRANT | WQ_UNBOUND | | ||
693 | WQ_MEM_RECLAIM, 1); | ||
694 | if (hdev->msg_rx_wq == NULL) { | ||
695 | r = -ENOMEM; | ||
696 | goto exit; | ||
697 | } | ||
698 | |||
699 | skb_queue_head_init(&hdev->msg_rx_queue); | ||
700 | |||
701 | r = nfc_register_device(hdev->ndev); | ||
702 | |||
703 | exit: | ||
704 | if (r < 0) { | ||
705 | if (hdev->msg_tx_wq) | ||
706 | destroy_workqueue(hdev->msg_tx_wq); | ||
707 | if (hdev->msg_rx_wq) | ||
708 | destroy_workqueue(hdev->msg_rx_wq); | ||
709 | } | ||
710 | |||
711 | return r; | ||
712 | } | ||
713 | EXPORT_SYMBOL(nfc_hci_register_device); | ||
714 | |||
715 | void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) | ||
716 | { | ||
717 | struct hci_msg *msg; | ||
718 | |||
719 | skb_queue_purge(&hdev->rx_hcp_frags); | ||
720 | skb_queue_purge(&hdev->msg_rx_queue); | ||
721 | |||
722 | while ((msg = list_first_entry(&hdev->msg_tx_queue, struct hci_msg, | ||
723 | msg_l)) != NULL) { | ||
724 | list_del(&msg->msg_l); | ||
725 | skb_queue_purge(&msg->msg_frags); | ||
726 | kfree(msg); | ||
727 | } | ||
728 | |||
729 | del_timer_sync(&hdev->cmd_timer); | ||
730 | |||
731 | nfc_unregister_device(hdev->ndev); | ||
732 | |||
733 | destroy_workqueue(hdev->msg_tx_wq); | ||
734 | |||
735 | destroy_workqueue(hdev->msg_rx_wq); | ||
736 | } | ||
737 | EXPORT_SYMBOL(nfc_hci_unregister_device); | ||
738 | |||
739 | void nfc_hci_set_clientdata(struct nfc_hci_dev *hdev, void *clientdata) | ||
740 | { | ||
741 | hdev->clientdata = clientdata; | ||
742 | } | ||
743 | EXPORT_SYMBOL(nfc_hci_set_clientdata); | ||
744 | |||
745 | void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev) | ||
746 | { | ||
747 | return hdev->clientdata; | ||
748 | } | ||
749 | EXPORT_SYMBOL(nfc_hci_get_clientdata); | ||
750 | |||
751 | void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) | ||
752 | { | ||
753 | struct hcp_packet *packet; | ||
754 | u8 type; | ||
755 | u8 instruction; | ||
756 | struct sk_buff *hcp_skb; | ||
757 | u8 pipe; | ||
758 | struct sk_buff *frag_skb; | ||
759 | int msg_len; | ||
760 | |||
761 | if (skb == NULL) { | ||
762 | /* TODO ELa: lower layer had permanent failure, need to | ||
763 | * propagate that up | ||
764 | */ | ||
765 | |||
766 | skb_queue_purge(&hdev->rx_hcp_frags); | ||
767 | |||
768 | return; | ||
769 | } | ||
770 | |||
771 | packet = (struct hcp_packet *)skb->data; | ||
772 | if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) { | ||
773 | skb_queue_tail(&hdev->rx_hcp_frags, skb); | ||
774 | return; | ||
775 | } | ||
776 | |||
777 | /* it's the last fragment. Does it need re-aggregation? */ | ||
778 | if (skb_queue_len(&hdev->rx_hcp_frags)) { | ||
779 | pipe = packet->header & NFC_HCI_FRAGMENT; | ||
780 | skb_queue_tail(&hdev->rx_hcp_frags, skb); | ||
781 | |||
782 | msg_len = 0; | ||
783 | skb_queue_walk(&hdev->rx_hcp_frags, frag_skb) { | ||
784 | msg_len += (frag_skb->len - | ||
785 | NFC_HCI_HCP_PACKET_HEADER_LEN); | ||
786 | } | ||
787 | |||
788 | hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN + | ||
789 | msg_len, GFP_KERNEL); | ||
790 | if (hcp_skb == NULL) { | ||
791 | /* TODO ELa: cannot deliver HCP message. How to | ||
792 | * propagate error up? | ||
793 | */ | ||
794 | } | ||
795 | |||
796 | *skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe; | ||
797 | |||
798 | skb_queue_walk(&hdev->rx_hcp_frags, frag_skb) { | ||
799 | msg_len = frag_skb->len - NFC_HCI_HCP_PACKET_HEADER_LEN; | ||
800 | memcpy(skb_put(hcp_skb, msg_len), | ||
801 | frag_skb->data + NFC_HCI_HCP_PACKET_HEADER_LEN, | ||
802 | msg_len); | ||
803 | } | ||
804 | |||
805 | skb_queue_purge(&hdev->rx_hcp_frags); | ||
806 | } else { | ||
807 | packet->header &= NFC_HCI_FRAGMENT; | ||
808 | hcp_skb = skb; | ||
809 | } | ||
810 | |||
811 | /* if this is a response, dispatch immediately to | ||
812 | * unblock waiting cmd context. Otherwise, enqueue to dispatch | ||
813 | * in separate context where handler can also execute command. | ||
814 | */ | ||
815 | packet = (struct hcp_packet *)hcp_skb->data; | ||
816 | type = HCP_MSG_GET_TYPE(packet->message.header); | ||
817 | if (type == NFC_HCI_HCP_RESPONSE) { | ||
818 | pipe = packet->header; | ||
819 | instruction = HCP_MSG_GET_CMD(packet->message.header); | ||
820 | skb_pull(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN + | ||
821 | NFC_HCI_HCP_MESSAGE_HEADER_LEN); | ||
822 | nfc_hci_hcp_message_rx(hdev, pipe, type, instruction, hcp_skb); | ||
823 | } else { | ||
824 | skb_queue_tail(&hdev->msg_rx_queue, hcp_skb); | ||
825 | queue_work(hdev->msg_rx_wq, &hdev->msg_rx_work); | ||
826 | } | ||
827 | } | ||
828 | EXPORT_SYMBOL(nfc_hci_recv_frame); | ||
829 | |||
830 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/nfc/hci/hci.h b/net/nfc/hci/hci.h new file mode 100644 index 000000000000..45f2fe4fd486 --- /dev/null +++ b/net/nfc/hci/hci.h | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef __LOCAL_HCI_H | ||
21 | #define __LOCAL_HCI_H | ||
22 | |||
23 | struct gate_pipe_map { | ||
24 | u8 gate; | ||
25 | u8 pipe; | ||
26 | }; | ||
27 | |||
28 | struct hcp_message { | ||
29 | u8 header; /* type -cmd,evt,rsp- + instruction */ | ||
30 | u8 data[]; | ||
31 | } __packed; | ||
32 | |||
33 | struct hcp_packet { | ||
34 | u8 header; /* cbit+pipe */ | ||
35 | struct hcp_message message; | ||
36 | } __packed; | ||
37 | |||
38 | /* | ||
39 | * HCI command execution completion callback. | ||
40 | * result will be one of the HCI response codes. | ||
41 | * skb contains the response data and must be disposed. | ||
42 | */ | ||
43 | typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, u8 result, | ||
44 | struct sk_buff *skb, void *cb_data); | ||
45 | |||
46 | struct hcp_exec_waiter { | ||
47 | wait_queue_head_t *wq; | ||
48 | bool exec_complete; | ||
49 | int exec_result; | ||
50 | struct sk_buff *result_skb; | ||
51 | }; | ||
52 | |||
53 | struct hci_msg { | ||
54 | struct list_head msg_l; | ||
55 | struct sk_buff_head msg_frags; | ||
56 | bool wait_response; | ||
57 | hci_cmd_cb_t cb; | ||
58 | void *cb_context; | ||
59 | unsigned long completion_delay; | ||
60 | }; | ||
61 | |||
62 | struct hci_create_pipe_params { | ||
63 | u8 src_gate; | ||
64 | u8 dest_host; | ||
65 | u8 dest_gate; | ||
66 | } __packed; | ||
67 | |||
68 | struct hci_create_pipe_resp { | ||
69 | u8 src_host; | ||
70 | u8 src_gate; | ||
71 | u8 dest_host; | ||
72 | u8 dest_gate; | ||
73 | u8 pipe; | ||
74 | } __packed; | ||
75 | |||
76 | #define NFC_HCI_FRAGMENT 0x7f | ||
77 | |||
78 | #define HCP_HEADER(type, instr) ((((type) & 0x03) << 6) | ((instr) & 0x3f)) | ||
79 | #define HCP_MSG_GET_TYPE(header) ((header & 0xc0) >> 6) | ||
80 | #define HCP_MSG_GET_CMD(header) (header & 0x3f) | ||
81 | |||
82 | int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, | ||
83 | u8 type, u8 instruction, | ||
84 | const u8 *payload, size_t payload_len, | ||
85 | hci_cmd_cb_t cb, void *cb_data, | ||
86 | unsigned long completion_delay); | ||
87 | |||
88 | u8 nfc_hci_pipe2gate(struct nfc_hci_dev *hdev, u8 pipe); | ||
89 | |||
90 | void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type, | ||
91 | u8 instruction, struct sk_buff *skb); | ||
92 | |||
93 | /* HCP headers */ | ||
94 | #define NFC_HCI_HCP_PACKET_HEADER_LEN 1 | ||
95 | #define NFC_HCI_HCP_MESSAGE_HEADER_LEN 1 | ||
96 | #define NFC_HCI_HCP_HEADER_LEN 2 | ||
97 | |||
98 | /* HCP types */ | ||
99 | #define NFC_HCI_HCP_COMMAND 0x00 | ||
100 | #define NFC_HCI_HCP_EVENT 0x01 | ||
101 | #define NFC_HCI_HCP_RESPONSE 0x02 | ||
102 | |||
103 | /* Generic commands */ | ||
104 | #define NFC_HCI_ANY_SET_PARAMETER 0x01 | ||
105 | #define NFC_HCI_ANY_GET_PARAMETER 0x02 | ||
106 | #define NFC_HCI_ANY_OPEN_PIPE 0x03 | ||
107 | #define NFC_HCI_ANY_CLOSE_PIPE 0x04 | ||
108 | |||
109 | /* Reader RF commands */ | ||
110 | #define NFC_HCI_WR_XCHG_DATA 0x10 | ||
111 | |||
112 | /* Admin commands */ | ||
113 | #define NFC_HCI_ADM_CREATE_PIPE 0x10 | ||
114 | #define NFC_HCI_ADM_DELETE_PIPE 0x11 | ||
115 | #define NFC_HCI_ADM_NOTIFY_PIPE_CREATED 0x12 | ||
116 | #define NFC_HCI_ADM_NOTIFY_PIPE_DELETED 0x13 | ||
117 | #define NFC_HCI_ADM_CLEAR_ALL_PIPE 0x14 | ||
118 | #define NFC_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED 0x15 | ||
119 | |||
120 | /* Generic responses */ | ||
121 | #define NFC_HCI_ANY_OK 0x00 | ||
122 | #define NFC_HCI_ANY_E_NOT_CONNECTED 0x01 | ||
123 | #define NFC_HCI_ANY_E_CMD_PAR_UNKNOWN 0x02 | ||
124 | #define NFC_HCI_ANY_E_NOK 0x03 | ||
125 | #define NFC_HCI_ANY_E_PIPES_FULL 0x04 | ||
126 | #define NFC_HCI_ANY_E_REG_PAR_UNKNOWN 0x05 | ||
127 | #define NFC_HCI_ANY_E_PIPE_NOT_OPENED 0x06 | ||
128 | #define NFC_HCI_ANY_E_CMD_NOT_SUPPORTED 0x07 | ||
129 | #define NFC_HCI_ANY_E_INHIBITED 0x08 | ||
130 | #define NFC_HCI_ANY_E_TIMEOUT 0x09 | ||
131 | #define NFC_HCI_ANY_E_REG_ACCESS_DENIED 0x0a | ||
132 | #define NFC_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b | ||
133 | |||
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 */ | ||
diff --git a/net/nfc/hci/hcp.c b/net/nfc/hci/hcp.c new file mode 100644 index 000000000000..7212cf2c5785 --- /dev/null +++ b/net/nfc/hci/hcp.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #define pr_fmt(fmt) "hci: %s: " fmt, __func__ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | |||
26 | #include <net/nfc/hci.h> | ||
27 | |||
28 | #include "hci.h" | ||
29 | |||
30 | /* | ||
31 | * Payload is the HCP message data only. Instruction will be prepended. | ||
32 | * Guarantees that cb will be called upon completion or timeout delay | ||
33 | * counted from the moment the cmd is sent to the transport. | ||
34 | */ | ||
35 | int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, | ||
36 | u8 type, u8 instruction, | ||
37 | const u8 *payload, size_t payload_len, | ||
38 | hci_cmd_cb_t cb, void *cb_data, | ||
39 | unsigned long completion_delay) | ||
40 | { | ||
41 | struct nfc_dev *ndev = hdev->ndev; | ||
42 | struct hci_msg *cmd; | ||
43 | const u8 *ptr = payload; | ||
44 | int hci_len, err; | ||
45 | bool firstfrag = true; | ||
46 | |||
47 | cmd = kzalloc(sizeof(struct hci_msg), GFP_KERNEL); | ||
48 | if (cmd == NULL) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | INIT_LIST_HEAD(&cmd->msg_l); | ||
52 | skb_queue_head_init(&cmd->msg_frags); | ||
53 | cmd->wait_response = (type == NFC_HCI_HCP_COMMAND) ? true : false; | ||
54 | cmd->cb = cb; | ||
55 | cmd->cb_context = cb_data; | ||
56 | cmd->completion_delay = completion_delay; | ||
57 | |||
58 | hci_len = payload_len + 1; | ||
59 | while (hci_len > 0) { | ||
60 | struct sk_buff *skb; | ||
61 | int skb_len, data_link_len; | ||
62 | struct hcp_packet *packet; | ||
63 | |||
64 | if (NFC_HCI_HCP_PACKET_HEADER_LEN + hci_len <= | ||
65 | hdev->max_data_link_payload) | ||
66 | data_link_len = hci_len; | ||
67 | else | ||
68 | data_link_len = hdev->max_data_link_payload - | ||
69 | NFC_HCI_HCP_PACKET_HEADER_LEN; | ||
70 | |||
71 | skb_len = ndev->tx_headroom + NFC_HCI_HCP_PACKET_HEADER_LEN + | ||
72 | data_link_len + ndev->tx_tailroom; | ||
73 | hci_len -= data_link_len; | ||
74 | |||
75 | skb = alloc_skb(skb_len, GFP_KERNEL); | ||
76 | if (skb == NULL) { | ||
77 | err = -ENOMEM; | ||
78 | goto out_skb_err; | ||
79 | } | ||
80 | skb_reserve(skb, ndev->tx_headroom); | ||
81 | |||
82 | skb_put(skb, NFC_HCI_HCP_PACKET_HEADER_LEN + data_link_len); | ||
83 | |||
84 | /* Only the last fragment will have the cb bit set to 1 */ | ||
85 | packet = (struct hcp_packet *)skb->data; | ||
86 | packet->header = pipe; | ||
87 | if (firstfrag) { | ||
88 | firstfrag = false; | ||
89 | packet->message.header = HCP_HEADER(type, instruction); | ||
90 | if (ptr) { | ||
91 | memcpy(packet->message.data, ptr, | ||
92 | data_link_len - 1); | ||
93 | ptr += data_link_len - 1; | ||
94 | } | ||
95 | } else { | ||
96 | memcpy(&packet->message, ptr, data_link_len); | ||
97 | ptr += data_link_len; | ||
98 | } | ||
99 | |||
100 | /* This is the last fragment, set the cb bit */ | ||
101 | if (hci_len == 0) | ||
102 | packet->header |= ~NFC_HCI_FRAGMENT; | ||
103 | |||
104 | skb_queue_tail(&cmd->msg_frags, skb); | ||
105 | } | ||
106 | |||
107 | mutex_lock(&hdev->msg_tx_mutex); | ||
108 | list_add_tail(&hdev->msg_tx_queue, &cmd->msg_l); | ||
109 | mutex_unlock(&hdev->msg_tx_mutex); | ||
110 | |||
111 | queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); | ||
112 | |||
113 | return 0; | ||
114 | |||
115 | out_skb_err: | ||
116 | skb_queue_purge(&cmd->msg_frags); | ||
117 | kfree(cmd); | ||
118 | |||
119 | return err; | ||
120 | } | ||
121 | |||
122 | u8 nfc_hci_pipe2gate(struct nfc_hci_dev *hdev, u8 pipe) | ||
123 | { | ||
124 | int gate; | ||
125 | |||
126 | for (gate = 0; gate < NFC_HCI_MAX_GATES; gate++) | ||
127 | if (hdev->gate2pipe[gate] == pipe) | ||
128 | return gate; | ||
129 | |||
130 | return 0xff; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * Receive hcp message for pipe, with type and cmd. | ||
135 | * skb contains optional message data only. | ||
136 | */ | ||
137 | void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type, | ||
138 | u8 instruction, struct sk_buff *skb) | ||
139 | { | ||
140 | switch (type) { | ||
141 | case NFC_HCI_HCP_RESPONSE: | ||
142 | nfc_hci_resp_received(hdev, instruction, skb); | ||
143 | break; | ||
144 | case NFC_HCI_HCP_COMMAND: | ||
145 | nfc_hci_cmd_received(hdev, pipe, instruction, skb); | ||
146 | break; | ||
147 | case NFC_HCI_HCP_EVENT: | ||
148 | nfc_hci_event_received(hdev, pipe, instruction, skb); | ||
149 | break; | ||
150 | default: | ||
151 | pr_err("UNKNOWN MSG Type %d, instruction=%d\n", | ||
152 | type, instruction); | ||
153 | kfree_skb(skb); | ||
154 | break; | ||
155 | } | ||
156 | } | ||