xref: /openbmc/linux/net/nfc/hci/command.c (revision 95e9fd10)
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 void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, int err,
32 			       struct sk_buff *skb, void *cb_data)
33 {
34 	struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)cb_data;
35 
36 	pr_debug("HCI Cmd completed with result=%d\n", err);
37 
38 	hcp_ew->exec_result = err;
39 	if (hcp_ew->exec_result == 0)
40 		hcp_ew->result_skb = skb;
41 	else
42 		kfree_skb(skb);
43 	hcp_ew->exec_complete = true;
44 
45 	wake_up(hcp_ew->wq);
46 }
47 
48 static int nfc_hci_execute_cmd(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
49 			       const u8 *param, size_t param_len,
50 			       struct sk_buff **skb)
51 {
52 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(ew_wq);
53 	struct hcp_exec_waiter hcp_ew;
54 	hcp_ew.wq = &ew_wq;
55 	hcp_ew.exec_complete = false;
56 	hcp_ew.result_skb = NULL;
57 
58 	pr_debug("through pipe=%d, cmd=%d, plen=%zd\n", pipe, cmd, param_len);
59 
60 	/* TODO: Define hci cmd execution delay. Should it be the same
61 	 * for all commands?
62 	 */
63 	hcp_ew.exec_result = nfc_hci_hcp_message_tx(hdev, pipe,
64 						    NFC_HCI_HCP_COMMAND, cmd,
65 						    param, param_len,
66 						    nfc_hci_execute_cb, &hcp_ew,
67 						    3000);
68 	if (hcp_ew.exec_result < 0)
69 		return hcp_ew.exec_result;
70 
71 	wait_event(ew_wq, hcp_ew.exec_complete == true);
72 
73 	if (hcp_ew.exec_result == 0) {
74 		if (skb)
75 			*skb = hcp_ew.result_skb;
76 		else
77 			kfree_skb(hcp_ew.result_skb);
78 	}
79 
80 	return hcp_ew.exec_result;
81 }
82 
83 int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event,
84 		       const u8 *param, size_t param_len)
85 {
86 	u8 pipe;
87 
88 	pr_debug("%d to gate %d\n", event, gate);
89 
90 	pipe = hdev->gate2pipe[gate];
91 	if (pipe == NFC_HCI_INVALID_PIPE)
92 		return -EADDRNOTAVAIL;
93 
94 	return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_EVENT, event,
95 				      param, param_len, NULL, NULL, 0);
96 }
97 EXPORT_SYMBOL(nfc_hci_send_event);
98 
99 int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response,
100 			  const u8 *param, size_t param_len)
101 {
102 	u8 pipe;
103 
104 	pr_debug("\n");
105 
106 	pipe = hdev->gate2pipe[gate];
107 	if (pipe == NFC_HCI_INVALID_PIPE)
108 		return -EADDRNOTAVAIL;
109 
110 	return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_RESPONSE,
111 				      response, param, param_len, NULL, NULL,
112 				      0);
113 }
114 EXPORT_SYMBOL(nfc_hci_send_response);
115 
116 /*
117  * Execute an hci command sent to gate.
118  * skb will contain response data if success. skb can be NULL if you are not
119  * interested by the response.
120  */
121 int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
122 		     const u8 *param, size_t param_len, struct sk_buff **skb)
123 {
124 	u8 pipe;
125 
126 	pr_debug("\n");
127 
128 	pipe = hdev->gate2pipe[gate];
129 	if (pipe == NFC_HCI_INVALID_PIPE)
130 		return -EADDRNOTAVAIL;
131 
132 	return nfc_hci_execute_cmd(hdev, pipe, cmd, param, param_len, skb);
133 }
134 EXPORT_SYMBOL(nfc_hci_send_cmd);
135 
136 int nfc_hci_set_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
137 		      const u8 *param, size_t param_len)
138 {
139 	int r;
140 	u8 *tmp;
141 
142 	/* TODO ELa: reg idx must be inserted before param, but we don't want
143 	 * to ask the caller to do it to keep a simpler API.
144 	 * For now, just create a new temporary param buffer. This is far from
145 	 * optimal though, and the plan is to modify APIs to pass idx down to
146 	 * nfc_hci_hcp_message_tx where the frame is actually built, thereby
147 	 * eliminating the need for the temp allocation-copy here.
148 	 */
149 
150 	pr_debug("idx=%d to gate %d\n", idx, gate);
151 
152 	tmp = kmalloc(1 + param_len, GFP_KERNEL);
153 	if (tmp == NULL)
154 		return -ENOMEM;
155 
156 	*tmp = idx;
157 	memcpy(tmp + 1, param, param_len);
158 
159 	r = nfc_hci_send_cmd(hdev, gate, NFC_HCI_ANY_SET_PARAMETER,
160 			     tmp, param_len + 1, NULL);
161 
162 	kfree(tmp);
163 
164 	return r;
165 }
166 EXPORT_SYMBOL(nfc_hci_set_param);
167 
168 int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
169 		      struct sk_buff **skb)
170 {
171 	pr_debug("gate=%d regidx=%d\n", gate, idx);
172 
173 	return nfc_hci_send_cmd(hdev, gate, NFC_HCI_ANY_GET_PARAMETER,
174 				&idx, 1, skb);
175 }
176 EXPORT_SYMBOL(nfc_hci_get_param);
177 
178 static int nfc_hci_open_pipe(struct nfc_hci_dev *hdev, u8 pipe)
179 {
180 	struct sk_buff *skb;
181 	int r;
182 
183 	pr_debug("pipe=%d\n", pipe);
184 
185 	r = nfc_hci_execute_cmd(hdev, pipe, NFC_HCI_ANY_OPEN_PIPE,
186 				NULL, 0, &skb);
187 	if (r == 0) {
188 		/* dest host other than host controller will send
189 		 * number of pipes already open on this gate before
190 		 * execution. The number can be found in skb->data[0]
191 		 */
192 		kfree_skb(skb);
193 	}
194 
195 	return r;
196 }
197 
198 static int nfc_hci_close_pipe(struct nfc_hci_dev *hdev, u8 pipe)
199 {
200 	pr_debug("\n");
201 
202 	return nfc_hci_execute_cmd(hdev, pipe, NFC_HCI_ANY_CLOSE_PIPE,
203 				   NULL, 0, NULL);
204 }
205 
206 static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host,
207 			      u8 dest_gate, int *result)
208 {
209 	struct sk_buff *skb;
210 	struct hci_create_pipe_params params;
211 	struct hci_create_pipe_resp *resp;
212 	u8 pipe;
213 
214 	pr_debug("gate=%d\n", dest_gate);
215 
216 	params.src_gate = NFC_HCI_ADMIN_GATE;
217 	params.dest_host = dest_host;
218 	params.dest_gate = dest_gate;
219 
220 	*result = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE,
221 				      NFC_HCI_ADM_CREATE_PIPE,
222 				      (u8 *) &params, sizeof(params), &skb);
223 	if (*result == 0) {
224 		resp = (struct hci_create_pipe_resp *)skb->data;
225 		pipe = resp->pipe;
226 		kfree_skb(skb);
227 
228 		pr_debug("pipe created=%d\n", pipe);
229 
230 		return pipe;
231 	} else
232 		return NFC_HCI_INVALID_PIPE;
233 }
234 
235 static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe)
236 {
237 	pr_debug("\n");
238 
239 	return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE,
240 				   NFC_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL);
241 }
242 
243 static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev)
244 {
245 	int r;
246 
247 	u8 param[2];
248 
249 	/* TODO: Find out what the identity reference data is
250 	 * and fill param with it. HCI spec 6.1.3.5 */
251 
252 	pr_debug("\n");
253 
254 	r = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE,
255 				NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL);
256 
257 	return 0;
258 }
259 
260 int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate)
261 {
262 	int r;
263 	u8 pipe = hdev->gate2pipe[gate];
264 
265 	pr_debug("\n");
266 
267 	if (pipe == NFC_HCI_INVALID_PIPE)
268 		return -EADDRNOTAVAIL;
269 
270 	r = nfc_hci_close_pipe(hdev, pipe);
271 	if (r < 0)
272 		return r;
273 
274 	if (pipe != NFC_HCI_LINK_MGMT_PIPE && pipe != NFC_HCI_ADMIN_PIPE) {
275 		r = nfc_hci_delete_pipe(hdev, pipe);
276 		if (r < 0)
277 			return r;
278 	}
279 
280 	hdev->gate2pipe[gate] = NFC_HCI_INVALID_PIPE;
281 
282 	return 0;
283 }
284 EXPORT_SYMBOL(nfc_hci_disconnect_gate);
285 
286 int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev)
287 {
288 	int r;
289 
290 	pr_debug("\n");
291 
292 	r = nfc_hci_clear_all_pipes(hdev);
293 	if (r < 0)
294 		return r;
295 
296 	memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
297 
298 	return 0;
299 }
300 EXPORT_SYMBOL(nfc_hci_disconnect_all_gates);
301 
302 int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
303 			 u8 pipe)
304 {
305 	bool pipe_created = false;
306 	int r;
307 
308 	pr_debug("\n");
309 
310 	if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE)
311 		return -EADDRINUSE;
312 
313 	if (pipe != NFC_HCI_INVALID_PIPE)
314 		goto pipe_is_open;
315 
316 	switch (dest_gate) {
317 	case NFC_HCI_LINK_MGMT_GATE:
318 		pipe = NFC_HCI_LINK_MGMT_PIPE;
319 		break;
320 	case NFC_HCI_ADMIN_GATE:
321 		pipe = NFC_HCI_ADMIN_PIPE;
322 		break;
323 	default:
324 		pipe = nfc_hci_create_pipe(hdev, dest_host, dest_gate, &r);
325 		if (pipe == NFC_HCI_INVALID_PIPE)
326 			return r;
327 		pipe_created = true;
328 		break;
329 	}
330 
331 	r = nfc_hci_open_pipe(hdev, pipe);
332 	if (r < 0) {
333 		if (pipe_created)
334 			if (nfc_hci_delete_pipe(hdev, pipe) < 0) {
335 				/* TODO: Cannot clean by deleting pipe...
336 				 * -> inconsistent state */
337 			}
338 		return r;
339 	}
340 
341 pipe_is_open:
342 	hdev->gate2pipe[dest_gate] = pipe;
343 
344 	return 0;
345 }
346 EXPORT_SYMBOL(nfc_hci_connect_gate);
347