blob: 3361170cb26224f75b35e06777e04d5dce3ca92f [file] [log] [blame]
Samuel Ortizd6469602011-12-14 16:43:12 +01001/*
2 * Copyright (C) 2011 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) "llcp: %s: " fmt, __func__
21
22#include <linux/init.h>
23#include <linux/kernel.h>
24#include <linux/list.h>
25#include <linux/nfc.h>
26
27#include "../nfc.h"
28#include "llcp.h"
29
30static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
31
32static struct list_head llcp_devices;
33
Samuel Ortiza69f32a2012-05-04 17:04:19 +020034void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk)
35{
36 write_lock(&l->lock);
37 sk_add_node(sk, &l->head);
38 write_unlock(&l->lock);
39}
40
41void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk)
42{
43 write_lock(&l->lock);
44 sk_del_node_init(sk);
45 write_unlock(&l->lock);
46}
47
Samuel Ortizf31652a2012-10-26 18:20:10 +020048static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
49{
50 struct nfc_llcp_local *local = sock->local;
51 struct sk_buff *s, *tmp;
52
53 pr_debug("%p\n", &sock->sk);
54
55 skb_queue_purge(&sock->tx_queue);
56 skb_queue_purge(&sock->tx_pending_queue);
Samuel Ortizf31652a2012-10-26 18:20:10 +020057
58 if (local == NULL)
59 return;
60
61 /* Search for local pending SKBs that are related to this socket */
62 skb_queue_walk_safe(&local->tx_queue, s, tmp) {
63 if (s->sk != &sock->sk)
64 continue;
65
66 skb_unlink(s, &local->tx_queue);
67 kfree_skb(s);
68 }
69}
70
Samuel Ortiz4d22ea12012-06-22 14:40:34 +020071static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
Samuel Ortizd6469602011-12-14 16:43:12 +010072{
Samuel Ortiza69f32a2012-05-04 17:04:19 +020073 struct sock *sk;
Sasha Levinb67bfe02013-02-27 17:06:00 -080074 struct hlist_node *tmp;
Samuel Ortiza69f32a2012-05-04 17:04:19 +020075 struct nfc_llcp_sock *llcp_sock;
Samuel Ortizd6469602011-12-14 16:43:12 +010076
Samuel Ortizf31652a2012-10-26 18:20:10 +020077 skb_queue_purge(&local->tx_queue);
78
Samuel Ortiza69f32a2012-05-04 17:04:19 +020079 write_lock(&local->sockets.lock);
Samuel Ortizd6469602011-12-14 16:43:12 +010080
Sasha Levinb67bfe02013-02-27 17:06:00 -080081 sk_for_each_safe(sk, tmp, &local->sockets.head) {
Samuel Ortiza69f32a2012-05-04 17:04:19 +020082 llcp_sock = nfc_llcp_sock(sk);
Samuel Ortizd6469602011-12-14 16:43:12 +010083
Szymon Janc50b78b22012-09-26 14:22:10 +020084 bh_lock_sock(sk);
Samuel Ortizd6469602011-12-14 16:43:12 +010085
Samuel Ortizf31652a2012-10-26 18:20:10 +020086 nfc_llcp_socket_purge(llcp_sock);
87
Samuel Ortiza69f32a2012-05-04 17:04:19 +020088 if (sk->sk_state == LLCP_CONNECTED)
89 nfc_put_device(llcp_sock->dev);
Samuel Ortizd6469602011-12-14 16:43:12 +010090
Samuel Ortiza69f32a2012-05-04 17:04:19 +020091 if (sk->sk_state == LLCP_LISTEN) {
Samuel Ortizd6469602011-12-14 16:43:12 +010092 struct nfc_llcp_sock *lsk, *n;
93 struct sock *accept_sk;
94
Szymon Janc0f450772012-10-17 15:23:39 +020095 list_for_each_entry_safe(lsk, n,
96 &llcp_sock->accept_queue,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +010097 accept_queue) {
Samuel Ortizd6469602011-12-14 16:43:12 +010098 accept_sk = &lsk->sk;
Szymon Janc50b78b22012-09-26 14:22:10 +020099 bh_lock_sock(accept_sk);
Samuel Ortizd6469602011-12-14 16:43:12 +0100100
101 nfc_llcp_accept_unlink(accept_sk);
102
103 accept_sk->sk_state = LLCP_CLOSED;
Samuel Ortizd6469602011-12-14 16:43:12 +0100104
Szymon Janc50b78b22012-09-26 14:22:10 +0200105 bh_unlock_sock(accept_sk);
Samuel Ortizd6469602011-12-14 16:43:12 +0100106
107 sock_orphan(accept_sk);
108 }
Samuel Ortiz4d22ea12012-06-22 14:40:34 +0200109
110 if (listen == true) {
Szymon Janc50b78b22012-09-26 14:22:10 +0200111 bh_unlock_sock(sk);
Samuel Ortiz4d22ea12012-06-22 14:40:34 +0200112 continue;
113 }
Samuel Ortizd6469602011-12-14 16:43:12 +0100114 }
115
Samuel Ortizc8512be2012-10-15 15:09:52 +0200116 /*
117 * If we have a connection less socket bound, we keep it alive
118 * if the device is still present.
119 */
120 if (sk->sk_state == LLCP_BOUND && sk->sk_type == SOCK_DGRAM &&
121 listen == true) {
122 bh_unlock_sock(sk);
123 continue;
124 }
125
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200126 sk->sk_state = LLCP_CLOSED;
Samuel Ortizd6469602011-12-14 16:43:12 +0100127
Szymon Janc50b78b22012-09-26 14:22:10 +0200128 bh_unlock_sock(sk);
Samuel Ortizd6469602011-12-14 16:43:12 +0100129
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200130 sock_orphan(sk);
Samuel Ortiz40c75f82012-03-05 01:03:51 +0100131
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200132 sk_del_node_init(sk);
Samuel Ortizd6469602011-12-14 16:43:12 +0100133 }
134
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200135 write_unlock(&local->sockets.lock);
Samuel Ortizd6469602011-12-14 16:43:12 +0100136}
137
Samuel Ortizc7aa1222012-05-04 11:24:16 +0200138struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
139{
140 kref_get(&local->ref);
141
142 return local;
143}
144
145static void local_release(struct kref *ref)
146{
147 struct nfc_llcp_local *local;
148
149 local = container_of(ref, struct nfc_llcp_local, ref);
150
151 list_del(&local->list);
Samuel Ortiz4d22ea12012-06-22 14:40:34 +0200152 nfc_llcp_socket_release(local, false);
Samuel Ortizc7aa1222012-05-04 11:24:16 +0200153 del_timer_sync(&local->link_timer);
154 skb_queue_purge(&local->tx_queue);
Tejun Heo474fee32012-08-22 16:22:16 -0700155 cancel_work_sync(&local->tx_work);
156 cancel_work_sync(&local->rx_work);
157 cancel_work_sync(&local->timeout_work);
Samuel Ortizc7aa1222012-05-04 11:24:16 +0200158 kfree_skb(local->rx_pending);
Thierry Escande40213fa2013-03-04 15:43:32 +0100159 del_timer_sync(&local->sdreq_timer);
160 cancel_work_sync(&local->sdreq_timeout_work);
Thierry Escanded9b8d8e2013-02-15 10:43:06 +0100161 nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs);
Samuel Ortizc7aa1222012-05-04 11:24:16 +0200162 kfree(local);
163}
164
165int nfc_llcp_local_put(struct nfc_llcp_local *local)
166{
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200167 if (local == NULL)
168 return 0;
169
Samuel Ortizc7aa1222012-05-04 11:24:16 +0200170 return kref_put(&local->ref, local_release);
171}
172
Samuel Ortiz8f500202012-06-25 15:46:28 +0200173static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
174 u8 ssap, u8 dsap)
175{
176 struct sock *sk;
Samuel Ortiza8df0f32012-10-16 21:15:59 +0200177 struct nfc_llcp_sock *llcp_sock, *tmp_sock;
Samuel Ortiz8f500202012-06-25 15:46:28 +0200178
179 pr_debug("ssap dsap %d %d\n", ssap, dsap);
180
181 if (ssap == 0 && dsap == 0)
182 return NULL;
183
184 read_lock(&local->sockets.lock);
185
186 llcp_sock = NULL;
187
Sasha Levinb67bfe02013-02-27 17:06:00 -0800188 sk_for_each(sk, &local->sockets.head) {
Samuel Ortiza8df0f32012-10-16 21:15:59 +0200189 tmp_sock = nfc_llcp_sock(sk);
Samuel Ortiz8f500202012-06-25 15:46:28 +0200190
Samuel Ortiza8df0f32012-10-16 21:15:59 +0200191 if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) {
192 llcp_sock = tmp_sock;
Samuel Ortiz8f500202012-06-25 15:46:28 +0200193 break;
Samuel Ortiza8df0f32012-10-16 21:15:59 +0200194 }
Samuel Ortiz8f500202012-06-25 15:46:28 +0200195 }
196
197 read_unlock(&local->sockets.lock);
198
199 if (llcp_sock == NULL)
200 return NULL;
201
202 sock_hold(&llcp_sock->sk);
203
204 return llcp_sock;
205}
206
207static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock)
208{
209 sock_put(&sock->sk);
210}
211
Samuel Ortizd6469602011-12-14 16:43:12 +0100212static void nfc_llcp_timeout_work(struct work_struct *work)
213{
214 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100215 timeout_work);
Samuel Ortizd6469602011-12-14 16:43:12 +0100216
217 nfc_dep_link_down(local->dev);
218}
219
220static void nfc_llcp_symm_timer(unsigned long data)
221{
222 struct nfc_llcp_local *local = (struct nfc_llcp_local *) data;
223
224 pr_err("SYMM timeout\n");
225
Linus Torvalds916082b2012-10-02 16:01:31 -0700226 schedule_work(&local->timeout_work);
Samuel Ortizd6469602011-12-14 16:43:12 +0100227}
228
Thierry Escande40213fa2013-03-04 15:43:32 +0100229static void nfc_llcp_sdreq_timeout_work(struct work_struct *work)
230{
231 unsigned long time;
232 HLIST_HEAD(nl_sdres_list);
233 struct hlist_node *n;
234 struct nfc_llcp_sdp_tlv *sdp;
235 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
236 sdreq_timeout_work);
237
238 mutex_lock(&local->sdreq_lock);
239
240 time = jiffies - msecs_to_jiffies(3 * local->remote_lto);
241
242 hlist_for_each_entry_safe(sdp, n, &local->pending_sdreqs, node) {
243 if (time_after(sdp->time, time))
244 continue;
245
246 sdp->sap = LLCP_SDP_UNBOUND;
247
248 hlist_del(&sdp->node);
249
250 hlist_add_head(&sdp->node, &nl_sdres_list);
251 }
252
253 if (!hlist_empty(&local->pending_sdreqs))
254 mod_timer(&local->sdreq_timer,
255 jiffies + msecs_to_jiffies(3 * local->remote_lto));
256
257 mutex_unlock(&local->sdreq_lock);
258
259 if (!hlist_empty(&nl_sdres_list))
260 nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list);
261}
262
263static void nfc_llcp_sdreq_timer(unsigned long data)
264{
265 struct nfc_llcp_local *local = (struct nfc_llcp_local *) data;
266
267 schedule_work(&local->sdreq_timeout_work);
268}
269
Samuel Ortizd6469602011-12-14 16:43:12 +0100270struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
271{
272 struct nfc_llcp_local *local, *n;
273
274 list_for_each_entry_safe(local, n, &llcp_devices, list)
275 if (local->dev == dev)
276 return local;
277
278 pr_debug("No device found\n");
279
280 return NULL;
281}
282
283static char *wks[] = {
284 NULL,
285 NULL, /* SDP */
286 "urn:nfc:sn:ip",
287 "urn:nfc:sn:obex",
288 "urn:nfc:sn:snep",
289};
290
291static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len)
292{
293 int sap, num_wks;
294
295 pr_debug("%s\n", service_name);
296
297 if (service_name == NULL)
298 return -EINVAL;
299
300 num_wks = ARRAY_SIZE(wks);
301
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100302 for (sap = 0; sap < num_wks; sap++) {
Samuel Ortizd6469602011-12-14 16:43:12 +0100303 if (wks[sap] == NULL)
304 continue;
305
306 if (strncmp(wks[sap], service_name, service_name_len) == 0)
307 return sap;
308 }
309
310 return -EINVAL;
311}
312
Samuel Ortiz8f500202012-06-25 15:46:28 +0200313static
314struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local,
315 u8 *sn, size_t sn_len)
316{
317 struct sock *sk;
Samuel Ortiz8f500202012-06-25 15:46:28 +0200318 struct nfc_llcp_sock *llcp_sock, *tmp_sock;
319
320 pr_debug("sn %zd %p\n", sn_len, sn);
321
322 if (sn == NULL || sn_len == 0)
323 return NULL;
324
325 read_lock(&local->sockets.lock);
326
327 llcp_sock = NULL;
328
Sasha Levinb67bfe02013-02-27 17:06:00 -0800329 sk_for_each(sk, &local->sockets.head) {
Samuel Ortiz8f500202012-06-25 15:46:28 +0200330 tmp_sock = nfc_llcp_sock(sk);
331
332 pr_debug("llcp sock %p\n", tmp_sock);
333
Samuel Ortiz54292d62012-10-15 15:08:29 +0200334 if (tmp_sock->sk.sk_type == SOCK_STREAM &&
335 tmp_sock->sk.sk_state != LLCP_LISTEN)
336 continue;
337
338 if (tmp_sock->sk.sk_type == SOCK_DGRAM &&
339 tmp_sock->sk.sk_state != LLCP_BOUND)
Samuel Ortiz8f500202012-06-25 15:46:28 +0200340 continue;
341
342 if (tmp_sock->service_name == NULL ||
343 tmp_sock->service_name_len == 0)
344 continue;
345
346 if (tmp_sock->service_name_len != sn_len)
347 continue;
348
349 if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) {
350 llcp_sock = tmp_sock;
351 break;
352 }
353 }
354
355 read_unlock(&local->sockets.lock);
356
357 pr_debug("Found llcp sock %p\n", llcp_sock);
358
359 return llcp_sock;
360}
361
Samuel Ortizd6469602011-12-14 16:43:12 +0100362u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100363 struct nfc_llcp_sock *sock)
Samuel Ortizd6469602011-12-14 16:43:12 +0100364{
365 mutex_lock(&local->sdp_lock);
366
367 if (sock->service_name != NULL && sock->service_name_len > 0) {
368 int ssap = nfc_llcp_wks_sap(sock->service_name,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100369 sock->service_name_len);
Samuel Ortizd6469602011-12-14 16:43:12 +0100370
371 if (ssap > 0) {
372 pr_debug("WKS %d\n", ssap);
373
374 /* This is a WKS, let's check if it's free */
375 if (local->local_wks & BIT(ssap)) {
376 mutex_unlock(&local->sdp_lock);
377
378 return LLCP_SAP_MAX;
379 }
380
Samuel Ortiz1762c172012-03-05 01:03:38 +0100381 set_bit(ssap, &local->local_wks);
Samuel Ortizd6469602011-12-14 16:43:12 +0100382 mutex_unlock(&local->sdp_lock);
383
384 return ssap;
385 }
386
387 /*
Samuel Ortiz8f500202012-06-25 15:46:28 +0200388 * Check if there already is a non WKS socket bound
389 * to this service name.
Samuel Ortizd6469602011-12-14 16:43:12 +0100390 */
Samuel Ortiz8f500202012-06-25 15:46:28 +0200391 if (nfc_llcp_sock_from_sn(local, sock->service_name,
392 sock->service_name_len) != NULL) {
Samuel Ortizd6469602011-12-14 16:43:12 +0100393 mutex_unlock(&local->sdp_lock);
394
395 return LLCP_SAP_MAX;
396 }
397
Samuel Ortizd6469602011-12-14 16:43:12 +0100398 mutex_unlock(&local->sdp_lock);
399
Samuel Ortiz8f500202012-06-25 15:46:28 +0200400 return LLCP_SDP_UNBOUND;
Samuel Ortizd6469602011-12-14 16:43:12 +0100401
Samuel Ortizebbb16d2012-06-22 17:15:20 +0200402 } else if (sock->ssap != 0 && sock->ssap < LLCP_WKS_NUM_SAP) {
403 if (!test_bit(sock->ssap, &local->local_wks)) {
404 set_bit(sock->ssap, &local->local_wks);
405 mutex_unlock(&local->sdp_lock);
Samuel Ortizd6469602011-12-14 16:43:12 +0100406
Samuel Ortizebbb16d2012-06-22 17:15:20 +0200407 return sock->ssap;
Samuel Ortizd6469602011-12-14 16:43:12 +0100408 }
409 }
410
411 mutex_unlock(&local->sdp_lock);
412
413 return LLCP_SAP_MAX;
414}
415
416u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local)
417{
418 u8 local_ssap;
419
420 mutex_lock(&local->sdp_lock);
421
422 local_ssap = find_first_zero_bit(&local->local_sap, LLCP_LOCAL_NUM_SAP);
423 if (local_ssap == LLCP_LOCAL_NUM_SAP) {
424 mutex_unlock(&local->sdp_lock);
425 return LLCP_SAP_MAX;
426 }
427
Samuel Ortiz1762c172012-03-05 01:03:38 +0100428 set_bit(local_ssap, &local->local_sap);
Samuel Ortizd6469602011-12-14 16:43:12 +0100429
430 mutex_unlock(&local->sdp_lock);
431
432 return local_ssap + LLCP_LOCAL_SAP_OFFSET;
433}
434
435void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap)
436{
437 u8 local_ssap;
438 unsigned long *sdp;
439
440 if (ssap < LLCP_WKS_NUM_SAP) {
441 local_ssap = ssap;
442 sdp = &local->local_wks;
443 } else if (ssap < LLCP_LOCAL_NUM_SAP) {
Samuel Ortiz8f500202012-06-25 15:46:28 +0200444 atomic_t *client_cnt;
445
Samuel Ortizd6469602011-12-14 16:43:12 +0100446 local_ssap = ssap - LLCP_WKS_NUM_SAP;
447 sdp = &local->local_sdp;
Samuel Ortiz8f500202012-06-25 15:46:28 +0200448 client_cnt = &local->local_sdp_cnt[local_ssap];
449
450 pr_debug("%d clients\n", atomic_read(client_cnt));
451
452 mutex_lock(&local->sdp_lock);
453
454 if (atomic_dec_and_test(client_cnt)) {
455 struct nfc_llcp_sock *l_sock;
456
457 pr_debug("No more clients for SAP %d\n", ssap);
458
459 clear_bit(local_ssap, sdp);
460
461 /* Find the listening sock and set it back to UNBOUND */
462 l_sock = nfc_llcp_sock_get(local, ssap, LLCP_SAP_SDP);
463 if (l_sock) {
464 l_sock->ssap = LLCP_SDP_UNBOUND;
465 nfc_llcp_sock_put(l_sock);
466 }
467 }
468
469 mutex_unlock(&local->sdp_lock);
470
471 return;
Samuel Ortizd6469602011-12-14 16:43:12 +0100472 } else if (ssap < LLCP_MAX_SAP) {
473 local_ssap = ssap - LLCP_LOCAL_NUM_SAP;
474 sdp = &local->local_sap;
475 } else {
476 return;
477 }
478
479 mutex_lock(&local->sdp_lock);
480
Samuel Ortiz1762c172012-03-05 01:03:38 +0100481 clear_bit(local_ssap, sdp);
Samuel Ortizd6469602011-12-14 16:43:12 +0100482
483 mutex_unlock(&local->sdp_lock);
484}
485
Samuel Ortiz8f500202012-06-25 15:46:28 +0200486static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local)
487{
488 u8 ssap;
489
490 mutex_lock(&local->sdp_lock);
491
492 ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP);
493 if (ssap == LLCP_SDP_NUM_SAP) {
494 mutex_unlock(&local->sdp_lock);
495
496 return LLCP_SAP_MAX;
497 }
498
499 pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap);
500
501 set_bit(ssap, &local->local_sdp);
502
503 mutex_unlock(&local->sdp_lock);
504
505 return LLCP_WKS_NUM_SAP + ssap;
506}
507
Samuel Ortizd6469602011-12-14 16:43:12 +0100508static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
509{
510 u8 *gb_cur, *version_tlv, version, version_length;
Thierry Escande52feb442012-10-17 14:43:39 +0200511 u8 *lto_tlv, lto_length;
Samuel Ortizd6469602011-12-14 16:43:12 +0100512 u8 *wks_tlv, wks_length;
Samuel Ortiz56d58762012-04-10 19:43:19 +0200513 u8 *miux_tlv, miux_length;
Samuel Ortizd6469602011-12-14 16:43:12 +0100514 u8 gb_len = 0;
Wei Yongjun52da2442012-09-02 21:21:46 +0800515 int ret = 0;
Samuel Ortizd6469602011-12-14 16:43:12 +0100516
517 version = LLCP_VERSION_11;
518 version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100519 1, &version_length);
Samuel Ortizd6469602011-12-14 16:43:12 +0100520 gb_len += version_length;
521
Thierry Escande52feb442012-10-17 14:43:39 +0200522 lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, &local->lto, 1, &lto_length);
Samuel Ortizd6469602011-12-14 16:43:12 +0100523 gb_len += lto_length;
524
525 pr_debug("Local wks 0x%lx\n", local->local_wks);
526 wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&local->local_wks, 2,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100527 &wks_length);
Samuel Ortizd6469602011-12-14 16:43:12 +0100528 gb_len += wks_length;
529
Thierry Escande52feb442012-10-17 14:43:39 +0200530 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
Samuel Ortiz56d58762012-04-10 19:43:19 +0200531 &miux_length);
532 gb_len += miux_length;
533
Samuel Ortizd6469602011-12-14 16:43:12 +0100534 gb_len += ARRAY_SIZE(llcp_magic);
535
536 if (gb_len > NFC_MAX_GT_LEN) {
Wei Yongjun52da2442012-09-02 21:21:46 +0800537 ret = -EINVAL;
538 goto out;
Samuel Ortizd6469602011-12-14 16:43:12 +0100539 }
540
541 gb_cur = local->gb;
542
543 memcpy(gb_cur, llcp_magic, ARRAY_SIZE(llcp_magic));
544 gb_cur += ARRAY_SIZE(llcp_magic);
545
546 memcpy(gb_cur, version_tlv, version_length);
547 gb_cur += version_length;
548
549 memcpy(gb_cur, lto_tlv, lto_length);
550 gb_cur += lto_length;
551
552 memcpy(gb_cur, wks_tlv, wks_length);
553 gb_cur += wks_length;
554
Samuel Ortiz56d58762012-04-10 19:43:19 +0200555 memcpy(gb_cur, miux_tlv, miux_length);
556 gb_cur += miux_length;
557
Samuel Ortizd6469602011-12-14 16:43:12 +0100558 local->gb_len = gb_len;
559
Wei Yongjun52da2442012-09-02 21:21:46 +0800560out:
561 kfree(version_tlv);
562 kfree(lto_tlv);
563 kfree(wks_tlv);
564 kfree(miux_tlv);
565
566 return ret;
Samuel Ortizd6469602011-12-14 16:43:12 +0100567}
568
Samuel Ortizb8e7a062012-06-22 02:04:53 +0200569u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
570{
571 struct nfc_llcp_local *local;
572
573 local = nfc_llcp_find_local(dev);
574 if (local == NULL) {
575 *general_bytes_len = 0;
576 return NULL;
577 }
578
579 nfc_llcp_build_gb(local);
580
581 *general_bytes_len = local->gb_len;
582
583 return local->gb;
584}
585
Samuel Ortizd6469602011-12-14 16:43:12 +0100586int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
587{
588 struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
589
590 if (local == NULL) {
591 pr_err("No LLCP device\n");
592 return -ENODEV;
593 }
Dan Carpentere9a4aa32013-01-31 11:16:46 +0300594 if (gb_len < 3)
595 return -EINVAL;
Samuel Ortizd6469602011-12-14 16:43:12 +0100596
597 memset(local->remote_gb, 0, NFC_MAX_GT_LEN);
598 memcpy(local->remote_gb, gb, gb_len);
599 local->remote_gb_len = gb_len;
600
Samuel Ortizd6469602011-12-14 16:43:12 +0100601 if (memcmp(local->remote_gb, llcp_magic, 3)) {
602 pr_err("MAC does not support LLCP\n");
603 return -EINVAL;
604 }
605
Samuel Ortiz7a06e582012-05-07 22:03:34 +0200606 return nfc_llcp_parse_gb_tlv(local,
607 &local->remote_gb[3],
608 local->remote_gb_len - 3);
Samuel Ortizd6469602011-12-14 16:43:12 +0100609}
610
Samuel Ortizd6469602011-12-14 16:43:12 +0100611static u8 nfc_llcp_dsap(struct sk_buff *pdu)
612{
613 return (pdu->data[0] & 0xfc) >> 2;
614}
615
616static u8 nfc_llcp_ptype(struct sk_buff *pdu)
617{
618 return ((pdu->data[0] & 0x03) << 2) | ((pdu->data[1] & 0xc0) >> 6);
619}
620
621static u8 nfc_llcp_ssap(struct sk_buff *pdu)
622{
623 return pdu->data[1] & 0x3f;
624}
625
626static u8 nfc_llcp_ns(struct sk_buff *pdu)
627{
628 return pdu->data[2] >> 4;
629}
630
631static u8 nfc_llcp_nr(struct sk_buff *pdu)
632{
633 return pdu->data[2] & 0xf;
634}
635
636static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
637{
Samuel Ortiz279cf172012-04-10 19:43:14 +0200638 pdu->data[2] = (sock->send_n << 4) | (sock->recv_n);
Samuel Ortizd6469602011-12-14 16:43:12 +0100639 sock->send_n = (sock->send_n + 1) % 16;
640 sock->recv_ack_n = (sock->recv_n - 1) % 16;
641}
642
Thierry Escande44635232012-09-26 18:16:44 +0200643void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local,
644 struct sk_buff *skb, u8 direction)
645{
Thierry Escande44635232012-09-26 18:16:44 +0200646 struct sk_buff *skb_copy = NULL, *nskb;
647 struct sock *sk;
648 u8 *data;
649
650 read_lock(&local->raw_sockets.lock);
651
Sasha Levinb67bfe02013-02-27 17:06:00 -0800652 sk_for_each(sk, &local->raw_sockets.head) {
Thierry Escande44635232012-09-26 18:16:44 +0200653 if (sk->sk_state != LLCP_BOUND)
654 continue;
655
656 if (skb_copy == NULL) {
657 skb_copy = __pskb_copy(skb, NFC_LLCP_RAW_HEADER_SIZE,
658 GFP_ATOMIC);
659
660 if (skb_copy == NULL)
661 continue;
662
663 data = skb_push(skb_copy, NFC_LLCP_RAW_HEADER_SIZE);
664
665 data[0] = local->dev ? local->dev->idx : 0xFF;
666 data[1] = direction;
667 }
668
669 nskb = skb_clone(skb_copy, GFP_ATOMIC);
670 if (!nskb)
671 continue;
672
673 if (sock_queue_rcv_skb(sk, nskb))
674 kfree_skb(nskb);
675 }
676
677 read_unlock(&local->raw_sockets.lock);
678
679 kfree_skb(skb_copy);
680}
681
Samuel Ortiz84457962012-05-30 17:48:29 +0200682static void nfc_llcp_tx_work(struct work_struct *work)
683{
684 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
685 tx_work);
686 struct sk_buff *skb;
687 struct sock *sk;
688 struct nfc_llcp_sock *llcp_sock;
689
690 skb = skb_dequeue(&local->tx_queue);
691 if (skb != NULL) {
692 sk = skb->sk;
693 llcp_sock = nfc_llcp_sock(sk);
Samuel Ortiza6a09152012-10-05 00:37:22 +0200694
695 if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) {
696 nfc_llcp_send_symm(local->dev);
697 } else {
Samuel Ortizbe02b6b2012-11-01 23:36:07 +0100698 struct sk_buff *copy_skb = NULL;
699 u8 ptype = nfc_llcp_ptype(skb);
Samuel Ortiz84457962012-05-30 17:48:29 +0200700 int ret;
701
702 pr_debug("Sending pending skb\n");
703 print_hex_dump(KERN_DEBUG, "LLCP Tx: ",
704 DUMP_PREFIX_OFFSET, 16, 1,
705 skb->data, skb->len, true);
706
Samuel Ortizbe02b6b2012-11-01 23:36:07 +0100707 if (ptype == LLCP_PDU_I)
708 copy_skb = skb_copy(skb, GFP_ATOMIC);
709
Thierry Escande2c2d45b2012-11-27 15:44:24 +0100710 __net_timestamp(skb);
711
Thierry Escande44635232012-09-26 18:16:44 +0200712 nfc_llcp_send_to_raw_sock(local, skb,
713 NFC_LLCP_DIRECTION_TX);
714
Samuel Ortiz84457962012-05-30 17:48:29 +0200715 ret = nfc_data_exchange(local->dev, local->target_idx,
716 skb, nfc_llcp_recv, local);
717
Samuel Ortizbe02b6b2012-11-01 23:36:07 +0100718 if (ret) {
719 kfree_skb(copy_skb);
720 goto out;
Samuel Ortiz84457962012-05-30 17:48:29 +0200721 }
Samuel Ortizbe02b6b2012-11-01 23:36:07 +0100722
723 if (ptype == LLCP_PDU_I && copy_skb)
724 skb_queue_tail(&llcp_sock->tx_pending_queue,
725 copy_skb);
Samuel Ortiz84457962012-05-30 17:48:29 +0200726 }
727 } else {
728 nfc_llcp_send_symm(local->dev);
729 }
730
Samuel Ortizbe02b6b2012-11-01 23:36:07 +0100731out:
Samuel Ortiz84457962012-05-30 17:48:29 +0200732 mod_timer(&local->link_timer,
733 jiffies + msecs_to_jiffies(2 * local->remote_lto));
734}
735
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200736static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local *local,
737 u8 ssap)
738{
739 struct sock *sk;
740 struct nfc_llcp_sock *llcp_sock;
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200741
742 read_lock(&local->connecting_sockets.lock);
743
Sasha Levinb67bfe02013-02-27 17:06:00 -0800744 sk_for_each(sk, &local->connecting_sockets.head) {
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200745 llcp_sock = nfc_llcp_sock(sk);
746
Samuel Ortiz5a0f6f32012-05-21 11:44:42 +0200747 if (llcp_sock->ssap == ssap) {
748 sock_hold(&llcp_sock->sk);
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200749 goto out;
Samuel Ortiz5a0f6f32012-05-21 11:44:42 +0200750 }
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200751 }
752
753 llcp_sock = NULL;
754
755out:
756 read_unlock(&local->connecting_sockets.lock);
757
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200758 return llcp_sock;
759}
760
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200761static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
762 u8 *sn, size_t sn_len)
763{
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200764 struct nfc_llcp_sock *llcp_sock;
765
Samuel Ortiz8f500202012-06-25 15:46:28 +0200766 llcp_sock = nfc_llcp_sock_from_sn(local, sn, sn_len);
Samuel Ortizd6469602011-12-14 16:43:12 +0100767
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200768 if (llcp_sock == NULL)
769 return NULL;
Samuel Ortizd6469602011-12-14 16:43:12 +0100770
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200771 sock_hold(&llcp_sock->sk);
Samuel Ortizd6469602011-12-14 16:43:12 +0100772
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200773 return llcp_sock;
Samuel Ortizd6469602011-12-14 16:43:12 +0100774}
775
Samuel Ortizd6469602011-12-14 16:43:12 +0100776static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len)
777{
778 u8 *tlv = &skb->data[2], type, length;
779 size_t tlv_array_len = skb->len - LLCP_HEADER_SIZE, offset = 0;
780
781 while (offset < tlv_array_len) {
782 type = tlv[0];
783 length = tlv[1];
784
785 pr_debug("type 0x%x length %d\n", type, length);
786
787 if (type == LLCP_TLV_SN) {
788 *sn_len = length;
789 return &tlv[2];
790 }
791
792 offset += length + 2;
793 tlv += length + 2;
794 }
795
796 return NULL;
797}
798
Samuel Ortiz968272b2012-10-15 16:14:37 +0200799static void nfc_llcp_recv_ui(struct nfc_llcp_local *local,
800 struct sk_buff *skb)
801{
802 struct nfc_llcp_sock *llcp_sock;
803 struct nfc_llcp_ui_cb *ui_cb;
804 u8 dsap, ssap;
805
806 dsap = nfc_llcp_dsap(skb);
807 ssap = nfc_llcp_ssap(skb);
808
809 ui_cb = nfc_llcp_ui_skb_cb(skb);
810 ui_cb->dsap = dsap;
811 ui_cb->ssap = ssap;
812
Samuel Ortiz968272b2012-10-15 16:14:37 +0200813 pr_debug("%d %d\n", dsap, ssap);
814
815 /* We're looking for a bound socket, not a client one */
816 llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP);
817 if (llcp_sock == NULL || llcp_sock->sk.sk_type != SOCK_DGRAM)
818 return;
819
820 /* There is no sequence with UI frames */
821 skb_pull(skb, LLCP_HEADER_SIZE);
Samuel Ortiz1727cf92012-12-07 16:37:30 +0100822 if (!sock_queue_rcv_skb(&llcp_sock->sk, skb)) {
823 /*
824 * UI frames will be freed from the socket layer, so we
825 * need to keep them alive until someone receives them.
826 */
827 skb_get(skb);
828 } else {
829 pr_err("Receive queue is full\n");
Samuel Ortiz2593c2c2012-12-07 15:55:19 +0100830 kfree_skb(skb);
Samuel Ortiz968272b2012-10-15 16:14:37 +0200831 }
832
833 nfc_llcp_sock_put(llcp_sock);
834}
835
Samuel Ortizd6469602011-12-14 16:43:12 +0100836static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100837 struct sk_buff *skb)
Samuel Ortizd6469602011-12-14 16:43:12 +0100838{
839 struct sock *new_sk, *parent;
840 struct nfc_llcp_sock *sock, *new_sock;
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200841 u8 dsap, ssap, reason;
Samuel Ortizd6469602011-12-14 16:43:12 +0100842
843 dsap = nfc_llcp_dsap(skb);
844 ssap = nfc_llcp_ssap(skb);
845
846 pr_debug("%d %d\n", dsap, ssap);
847
Samuel Ortizd6469602011-12-14 16:43:12 +0100848 if (dsap != LLCP_SAP_SDP) {
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200849 sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP);
850 if (sock == NULL || sock->sk.sk_state != LLCP_LISTEN) {
Samuel Ortizd6469602011-12-14 16:43:12 +0100851 reason = LLCP_DM_NOBOUND;
852 goto fail;
853 }
Samuel Ortizd6469602011-12-14 16:43:12 +0100854 } else {
855 u8 *sn;
856 size_t sn_len;
857
858 sn = nfc_llcp_connect_sn(skb, &sn_len);
859 if (sn == NULL) {
860 reason = LLCP_DM_NOBOUND;
861 goto fail;
862 }
863
864 pr_debug("Service name length %zu\n", sn_len);
865
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200866 sock = nfc_llcp_sock_get_sn(local, sn, sn_len);
867 if (sock == NULL) {
868 reason = LLCP_DM_NOBOUND;
869 goto fail;
Samuel Ortizd6469602011-12-14 16:43:12 +0100870 }
Samuel Ortizd6469602011-12-14 16:43:12 +0100871 }
872
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200873 lock_sock(&sock->sk);
Samuel Ortizd6469602011-12-14 16:43:12 +0100874
Samuel Ortizd6469602011-12-14 16:43:12 +0100875 parent = &sock->sk;
876
877 if (sk_acceptq_is_full(parent)) {
878 reason = LLCP_DM_REJ;
879 release_sock(&sock->sk);
880 sock_put(&sock->sk);
881 goto fail;
882 }
883
Samuel Ortiz8f500202012-06-25 15:46:28 +0200884 if (sock->ssap == LLCP_SDP_UNBOUND) {
885 u8 ssap = nfc_llcp_reserve_sdp_ssap(local);
886
887 pr_debug("First client, reserving %d\n", ssap);
888
889 if (ssap == LLCP_SAP_MAX) {
890 reason = LLCP_DM_REJ;
891 release_sock(&sock->sk);
892 sock_put(&sock->sk);
893 goto fail;
894 }
895
896 sock->ssap = ssap;
897 }
898
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100899 new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC);
Samuel Ortizd6469602011-12-14 16:43:12 +0100900 if (new_sk == NULL) {
901 reason = LLCP_DM_REJ;
902 release_sock(&sock->sk);
903 sock_put(&sock->sk);
904 goto fail;
905 }
906
907 new_sock = nfc_llcp_sock(new_sk);
908 new_sock->dev = local->dev;
Samuel Ortizc7aa1222012-05-04 11:24:16 +0200909 new_sock->local = nfc_llcp_local_get(local);
Samuel Ortiz06d44f82013-02-22 11:38:05 +0100910 new_sock->rw = sock->rw;
911 new_sock->miux = sock->miux;
Samuel Ortize4306be2013-02-22 01:12:28 +0100912 new_sock->remote_miu = local->remote_miu;
Samuel Ortizd6469602011-12-14 16:43:12 +0100913 new_sock->nfc_protocol = sock->nfc_protocol;
Samuel Ortizd6469602011-12-14 16:43:12 +0100914 new_sock->dsap = ssap;
Samuel Ortiz025f1522012-06-18 21:38:09 +0200915 new_sock->target_idx = local->target_idx;
Samuel Ortizd6469602011-12-14 16:43:12 +0100916 new_sock->parent = parent;
Samuel Ortiz8f500202012-06-25 15:46:28 +0200917 new_sock->ssap = sock->ssap;
918 if (sock->ssap < LLCP_LOCAL_NUM_SAP && sock->ssap >= LLCP_WKS_NUM_SAP) {
919 atomic_t *client_count;
920
921 pr_debug("reserved_ssap %d for %p\n", sock->ssap, new_sock);
922
923 client_count =
924 &local->local_sdp_cnt[sock->ssap - LLCP_WKS_NUM_SAP];
925
926 atomic_inc(client_count);
927 new_sock->reserved_ssap = sock->ssap;
928 }
Samuel Ortizd6469602011-12-14 16:43:12 +0100929
Samuel Ortiz7a06e582012-05-07 22:03:34 +0200930 nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE],
931 skb->len - LLCP_HEADER_SIZE);
932
Samuel Ortizd6469602011-12-14 16:43:12 +0100933 pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk);
934
Samuel Ortiza69f32a2012-05-04 17:04:19 +0200935 nfc_llcp_sock_link(&local->sockets, new_sk);
Samuel Ortizd6469602011-12-14 16:43:12 +0100936
937 nfc_llcp_accept_enqueue(&sock->sk, new_sk);
938
939 nfc_get_device(local->dev->idx);
940
941 new_sk->sk_state = LLCP_CONNECTED;
942
943 /* Wake the listening processes */
944 parent->sk_data_ready(parent, 0);
945
946 /* Send CC */
947 nfc_llcp_send_cc(new_sock);
948
949 release_sock(&sock->sk);
950 sock_put(&sock->sk);
951
952 return;
953
954fail:
955 /* Send DM */
956 nfc_llcp_send_dm(local, dsap, ssap, reason);
Samuel Ortizd6469602011-12-14 16:43:12 +0100957}
958
Samuel Ortizd094afa2012-03-05 01:03:42 +0100959int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
Samuel Ortiz4722d2b2012-03-05 01:03:35 +0100960{
Samuel Ortizd094afa2012-03-05 01:03:42 +0100961 int nr_frames = 0;
Samuel Ortiz4722d2b2012-03-05 01:03:35 +0100962 struct nfc_llcp_local *local = sock->local;
963
964 pr_debug("Remote ready %d tx queue len %d remote rw %d",
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100965 sock->remote_ready, skb_queue_len(&sock->tx_pending_queue),
Samuel Ortize4306be2013-02-22 01:12:28 +0100966 sock->remote_rw);
Samuel Ortiz4722d2b2012-03-05 01:03:35 +0100967
968 /* Try to queue some I frames for transmission */
969 while (sock->remote_ready &&
Samuel Ortize4306be2013-02-22 01:12:28 +0100970 skb_queue_len(&sock->tx_pending_queue) < sock->remote_rw) {
Samuel Ortiz84457962012-05-30 17:48:29 +0200971 struct sk_buff *pdu;
Samuel Ortiz4722d2b2012-03-05 01:03:35 +0100972
973 pdu = skb_dequeue(&sock->tx_queue);
974 if (pdu == NULL)
975 break;
976
977 /* Update N(S)/N(R) */
978 nfc_llcp_set_nrns(sock, pdu);
979
Samuel Ortiz4722d2b2012-03-05 01:03:35 +0100980 skb_queue_tail(&local->tx_queue, pdu);
Samuel Ortizd094afa2012-03-05 01:03:42 +0100981 nr_frames++;
Samuel Ortiz4722d2b2012-03-05 01:03:35 +0100982 }
Samuel Ortizd094afa2012-03-05 01:03:42 +0100983
984 return nr_frames;
Samuel Ortiz4722d2b2012-03-05 01:03:35 +0100985}
986
Samuel Ortizd6469602011-12-14 16:43:12 +0100987static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +0100988 struct sk_buff *skb)
Samuel Ortizd6469602011-12-14 16:43:12 +0100989{
990 struct nfc_llcp_sock *llcp_sock;
991 struct sock *sk;
992 u8 dsap, ssap, ptype, ns, nr;
993
994 ptype = nfc_llcp_ptype(skb);
995 dsap = nfc_llcp_dsap(skb);
996 ssap = nfc_llcp_ssap(skb);
997 ns = nfc_llcp_ns(skb);
998 nr = nfc_llcp_nr(skb);
999
1000 pr_debug("%d %d R %d S %d\n", dsap, ssap, nr, ns);
1001
1002 llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
1003 if (llcp_sock == NULL) {
1004 nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
1005 return;
1006 }
1007
1008 sk = &llcp_sock->sk;
1009 lock_sock(sk);
1010 if (sk->sk_state == LLCP_CLOSED) {
1011 release_sock(sk);
1012 nfc_llcp_sock_put(llcp_sock);
1013 }
1014
Samuel Ortizd6469602011-12-14 16:43:12 +01001015 /* Pass the payload upstream */
1016 if (ptype == LLCP_PDU_I) {
1017 pr_debug("I frame, queueing on %p\n", &llcp_sock->sk);
1018
Samuel Ortiz53aef922012-03-05 01:03:36 +01001019 if (ns == llcp_sock->recv_n)
1020 llcp_sock->recv_n = (llcp_sock->recv_n + 1) % 16;
1021 else
1022 pr_err("Received out of sequence I PDU\n");
1023
Samuel Ortizd6469602011-12-14 16:43:12 +01001024 skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE);
Samuel Ortiz1727cf92012-12-07 16:37:30 +01001025 if (!sock_queue_rcv_skb(&llcp_sock->sk, skb)) {
1026 /*
1027 * I frames will be freed from the socket layer, so we
1028 * need to keep them alive until someone receives them.
1029 */
1030 skb_get(skb);
1031 } else {
1032 pr_err("Receive queue is full\n");
Samuel Ortiz2593c2c2012-12-07 15:55:19 +01001033 kfree_skb(skb);
Samuel Ortizd6469602011-12-14 16:43:12 +01001034 }
1035 }
1036
1037 /* Remove skbs from the pending queue */
1038 if (llcp_sock->send_ack_n != nr) {
1039 struct sk_buff *s, *tmp;
Waldemar Rymarkiewicz28981492012-11-26 08:40:04 +01001040 u8 n;
Samuel Ortizd6469602011-12-14 16:43:12 +01001041
1042 llcp_sock->send_ack_n = nr;
1043
Samuel Ortiz84457962012-05-30 17:48:29 +02001044 /* Remove and free all skbs until ns == nr */
1045 skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) {
Waldemar Rymarkiewicz28981492012-11-26 08:40:04 +01001046 n = nfc_llcp_ns(s);
1047
Samuel Ortiz84457962012-05-30 17:48:29 +02001048 skb_unlink(s, &llcp_sock->tx_pending_queue);
1049 kfree_skb(s);
1050
Waldemar Rymarkiewicz28981492012-11-26 08:40:04 +01001051 if (n == nr)
Samuel Ortiz84457962012-05-30 17:48:29 +02001052 break;
1053 }
1054
1055 /* Re-queue the remaining skbs for transmission */
1056 skb_queue_reverse_walk_safe(&llcp_sock->tx_pending_queue,
1057 s, tmp) {
1058 skb_unlink(s, &llcp_sock->tx_pending_queue);
1059 skb_queue_head(&local->tx_queue, s);
1060 }
Samuel Ortizd6469602011-12-14 16:43:12 +01001061 }
1062
Samuel Ortiz53aef922012-03-05 01:03:36 +01001063 if (ptype == LLCP_PDU_RR)
1064 llcp_sock->remote_ready = true;
Samuel Ortiz427a2eb2012-03-05 01:03:52 +01001065 else if (ptype == LLCP_PDU_RNR)
Samuel Ortiz53aef922012-03-05 01:03:36 +01001066 llcp_sock->remote_ready = false;
1067
Samuel Ortiz56af2562012-05-30 18:06:11 +02001068 if (nfc_llcp_queue_i_frames(llcp_sock) == 0 && ptype == LLCP_PDU_I)
Samuel Ortizd094afa2012-03-05 01:03:42 +01001069 nfc_llcp_send_rr(llcp_sock);
Samuel Ortizd6469602011-12-14 16:43:12 +01001070
1071 release_sock(sk);
1072 nfc_llcp_sock_put(llcp_sock);
1073}
1074
1075static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +01001076 struct sk_buff *skb)
Samuel Ortizd6469602011-12-14 16:43:12 +01001077{
1078 struct nfc_llcp_sock *llcp_sock;
1079 struct sock *sk;
1080 u8 dsap, ssap;
1081
1082 dsap = nfc_llcp_dsap(skb);
1083 ssap = nfc_llcp_ssap(skb);
1084
1085 llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
1086 if (llcp_sock == NULL) {
1087 nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
1088 return;
1089 }
1090
1091 sk = &llcp_sock->sk;
1092 lock_sock(sk);
Samuel Ortizf31652a2012-10-26 18:20:10 +02001093
1094 nfc_llcp_socket_purge(llcp_sock);
1095
Samuel Ortizd6469602011-12-14 16:43:12 +01001096 if (sk->sk_state == LLCP_CLOSED) {
1097 release_sock(sk);
1098 nfc_llcp_sock_put(llcp_sock);
1099 }
1100
Samuel Ortizd6469602011-12-14 16:43:12 +01001101 if (sk->sk_state == LLCP_CONNECTED) {
1102 nfc_put_device(local->dev);
1103 sk->sk_state = LLCP_CLOSED;
1104 sk->sk_state_change(sk);
1105 }
1106
1107 nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_DISC);
1108
1109 release_sock(sk);
1110 nfc_llcp_sock_put(llcp_sock);
1111}
1112
Samuel Ortiz427a2eb2012-03-05 01:03:52 +01001113static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
Samuel Ortizd6469602011-12-14 16:43:12 +01001114{
1115 struct nfc_llcp_sock *llcp_sock;
Samuel Ortizff353d82012-05-07 12:31:19 +02001116 struct sock *sk;
Samuel Ortizd6469602011-12-14 16:43:12 +01001117 u8 dsap, ssap;
1118
Samuel Ortizd6469602011-12-14 16:43:12 +01001119 dsap = nfc_llcp_dsap(skb);
1120 ssap = nfc_llcp_ssap(skb);
1121
Samuel Ortiza69f32a2012-05-04 17:04:19 +02001122 llcp_sock = nfc_llcp_connecting_sock_get(local, dsap);
Samuel Ortizd6469602011-12-14 16:43:12 +01001123 if (llcp_sock == NULL) {
1124 pr_err("Invalid CC\n");
1125 nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
1126
1127 return;
1128 }
1129
Samuel Ortizff353d82012-05-07 12:31:19 +02001130 sk = &llcp_sock->sk;
Samuel Ortizd6469602011-12-14 16:43:12 +01001131
Samuel Ortiza69f32a2012-05-04 17:04:19 +02001132 /* Unlink from connecting and link to the client array */
1133 nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
1134 nfc_llcp_sock_link(&local->sockets, sk);
1135 llcp_sock->dsap = ssap;
1136
Samuel Ortiz7a06e582012-05-07 22:03:34 +02001137 nfc_llcp_parse_connection_tlv(llcp_sock, &skb->data[LLCP_HEADER_SIZE],
1138 skb->len - LLCP_HEADER_SIZE);
Samuel Ortizd6469602011-12-14 16:43:12 +01001139
Samuel Ortizff353d82012-05-07 12:31:19 +02001140 sk->sk_state = LLCP_CONNECTED;
1141 sk->sk_state_change(sk);
1142
Samuel Ortizd6469602011-12-14 16:43:12 +01001143 nfc_llcp_sock_put(llcp_sock);
1144}
1145
Samuel Ortiz5c0560b2012-06-26 16:13:29 +02001146static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb)
1147{
1148 struct nfc_llcp_sock *llcp_sock;
1149 struct sock *sk;
1150 u8 dsap, ssap, reason;
1151
1152 dsap = nfc_llcp_dsap(skb);
1153 ssap = nfc_llcp_ssap(skb);
1154 reason = skb->data[2];
1155
1156 pr_debug("%d %d reason %d\n", ssap, dsap, reason);
1157
1158 switch (reason) {
1159 case LLCP_DM_NOBOUND:
1160 case LLCP_DM_REJ:
1161 llcp_sock = nfc_llcp_connecting_sock_get(local, dsap);
1162 break;
1163
1164 default:
1165 llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
1166 break;
1167 }
1168
1169 if (llcp_sock == NULL) {
Samuel Ortiza8df0f32012-10-16 21:15:59 +02001170 pr_debug("Already closed\n");
Samuel Ortiz5c0560b2012-06-26 16:13:29 +02001171 return;
1172 }
1173
1174 sk = &llcp_sock->sk;
1175
1176 sk->sk_err = ENXIO;
1177 sk->sk_state = LLCP_CLOSED;
1178 sk->sk_state_change(sk);
1179
1180 nfc_llcp_sock_put(llcp_sock);
Samuel Ortiz5c0560b2012-06-26 16:13:29 +02001181}
1182
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001183static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
1184 struct sk_buff *skb)
1185{
1186 struct nfc_llcp_sock *llcp_sock;
1187 u8 dsap, ssap, *tlv, type, length, tid, sap;
1188 u16 tlv_len, offset;
1189 char *service_name;
1190 size_t service_name_len;
Thierry Escandee0ae7ba2013-02-15 10:43:05 +01001191 struct nfc_llcp_sdp_tlv *sdp;
1192 HLIST_HEAD(llc_sdres_list);
1193 size_t sdres_tlvs_len;
Thierry Escanded9b8d8e2013-02-15 10:43:06 +01001194 HLIST_HEAD(nl_sdres_list);
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001195
1196 dsap = nfc_llcp_dsap(skb);
1197 ssap = nfc_llcp_ssap(skb);
1198
1199 pr_debug("%d %d\n", dsap, ssap);
1200
1201 if (dsap != LLCP_SAP_SDP || ssap != LLCP_SAP_SDP) {
1202 pr_err("Wrong SNL SAP\n");
1203 return;
1204 }
1205
1206 tlv = &skb->data[LLCP_HEADER_SIZE];
1207 tlv_len = skb->len - LLCP_HEADER_SIZE;
1208 offset = 0;
Thierry Escandee0ae7ba2013-02-15 10:43:05 +01001209 sdres_tlvs_len = 0;
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001210
Szymon Janc0f450772012-10-17 15:23:39 +02001211 while (offset < tlv_len) {
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001212 type = tlv[0];
1213 length = tlv[1];
1214
1215 switch (type) {
1216 case LLCP_TLV_SDREQ:
1217 tid = tlv[2];
1218 service_name = (char *) &tlv[3];
1219 service_name_len = length - 1;
1220
Samuel Ortize6904082012-10-15 14:28:13 +02001221 pr_debug("Looking for %.16s\n", service_name);
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001222
1223 if (service_name_len == strlen("urn:nfc:sn:sdp") &&
1224 !strncmp(service_name, "urn:nfc:sn:sdp",
1225 service_name_len)) {
1226 sap = 1;
Thierry Escandee0ae7ba2013-02-15 10:43:05 +01001227 goto add_snl;
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001228 }
1229
Samuel Ortize6904082012-10-15 14:28:13 +02001230 llcp_sock = nfc_llcp_sock_from_sn(local, service_name,
1231 service_name_len);
1232 if (!llcp_sock) {
1233 sap = 0;
Thierry Escandee0ae7ba2013-02-15 10:43:05 +01001234 goto add_snl;
Samuel Ortize6904082012-10-15 14:28:13 +02001235 }
1236
1237 /*
1238 * We found a socket but its ssap has not been reserved
1239 * yet. We need to assign it for good and send a reply.
1240 * The ssap will be freed when the socket is closed.
1241 */
1242 if (llcp_sock->ssap == LLCP_SDP_UNBOUND) {
1243 atomic_t *client_count;
1244
1245 sap = nfc_llcp_reserve_sdp_ssap(local);
1246
1247 pr_debug("Reserving %d\n", sap);
1248
1249 if (sap == LLCP_SAP_MAX) {
1250 sap = 0;
Thierry Escandee0ae7ba2013-02-15 10:43:05 +01001251 goto add_snl;
Samuel Ortize6904082012-10-15 14:28:13 +02001252 }
1253
1254 client_count =
1255 &local->local_sdp_cnt[sap -
1256 LLCP_WKS_NUM_SAP];
1257
1258 atomic_inc(client_count);
1259
1260 llcp_sock->ssap = sap;
1261 llcp_sock->reserved_ssap = sap;
1262 } else {
1263 sap = llcp_sock->ssap;
1264 }
1265
1266 pr_debug("%p %d\n", llcp_sock, sap);
1267
Thierry Escandee0ae7ba2013-02-15 10:43:05 +01001268add_snl:
1269 sdp = nfc_llcp_build_sdres_tlv(tid, sap);
1270 if (sdp == NULL)
1271 goto exit;
1272
1273 sdres_tlvs_len += sdp->tlv_len;
1274 hlist_add_head(&sdp->node, &llc_sdres_list);
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001275 break;
1276
Thierry Escanded9b8d8e2013-02-15 10:43:06 +01001277 case LLCP_TLV_SDRES:
1278 mutex_lock(&local->sdreq_lock);
1279
1280 pr_debug("LLCP_TLV_SDRES: searching tid %d\n", tlv[2]);
1281
1282 hlist_for_each_entry(sdp, &local->pending_sdreqs, node) {
1283 if (sdp->tid != tlv[2])
1284 continue;
1285
1286 sdp->sap = tlv[3];
1287
1288 pr_debug("Found: uri=%s, sap=%d\n",
1289 sdp->uri, sdp->sap);
1290
1291 hlist_del(&sdp->node);
1292
1293 hlist_add_head(&sdp->node, &nl_sdres_list);
1294
1295 break;
1296 }
1297
1298 mutex_unlock(&local->sdreq_lock);
1299 break;
1300
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001301 default:
1302 pr_err("Invalid SNL tlv value 0x%x\n", type);
1303 break;
1304 }
1305
1306 offset += length + 2;
1307 tlv += length + 2;
1308 }
Thierry Escandee0ae7ba2013-02-15 10:43:05 +01001309
1310exit:
Thierry Escanded9b8d8e2013-02-15 10:43:06 +01001311 if (!hlist_empty(&nl_sdres_list))
1312 nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list);
1313
Thierry Escandee0ae7ba2013-02-15 10:43:05 +01001314 if (!hlist_empty(&llc_sdres_list))
1315 nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len);
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001316}
1317
Samuel Ortizd6469602011-12-14 16:43:12 +01001318static void nfc_llcp_rx_work(struct work_struct *work)
1319{
1320 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +01001321 rx_work);
Samuel Ortizd6469602011-12-14 16:43:12 +01001322 u8 dsap, ssap, ptype;
1323 struct sk_buff *skb;
1324
1325 skb = local->rx_pending;
1326 if (skb == NULL) {
1327 pr_debug("No pending SKB\n");
1328 return;
1329 }
1330
1331 ptype = nfc_llcp_ptype(skb);
1332 dsap = nfc_llcp_dsap(skb);
1333 ssap = nfc_llcp_ssap(skb);
1334
1335 pr_debug("ptype 0x%x dsap 0x%x ssap 0x%x\n", ptype, dsap, ssap);
1336
Samuel Ortiz4be646e2012-04-10 19:43:13 +02001337 if (ptype != LLCP_PDU_SYMM)
1338 print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET,
1339 16, 1, skb->data, skb->len, true);
1340
Thierry Escande2c2d45b2012-11-27 15:44:24 +01001341 __net_timestamp(skb);
1342
Thierry Escande44635232012-09-26 18:16:44 +02001343 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
1344
Samuel Ortizd6469602011-12-14 16:43:12 +01001345 switch (ptype) {
1346 case LLCP_PDU_SYMM:
1347 pr_debug("SYMM\n");
1348 break;
1349
Samuel Ortiz968272b2012-10-15 16:14:37 +02001350 case LLCP_PDU_UI:
1351 pr_debug("UI\n");
1352 nfc_llcp_recv_ui(local, skb);
1353 break;
1354
Samuel Ortizd6469602011-12-14 16:43:12 +01001355 case LLCP_PDU_CONNECT:
1356 pr_debug("CONNECT\n");
1357 nfc_llcp_recv_connect(local, skb);
1358 break;
1359
1360 case LLCP_PDU_DISC:
1361 pr_debug("DISC\n");
1362 nfc_llcp_recv_disc(local, skb);
1363 break;
1364
1365 case LLCP_PDU_CC:
1366 pr_debug("CC\n");
1367 nfc_llcp_recv_cc(local, skb);
1368 break;
1369
Samuel Ortiz5c0560b2012-06-26 16:13:29 +02001370 case LLCP_PDU_DM:
1371 pr_debug("DM\n");
1372 nfc_llcp_recv_dm(local, skb);
1373 break;
1374
Samuel Ortiz19cfe582012-10-05 01:21:47 +02001375 case LLCP_PDU_SNL:
1376 pr_debug("SNL\n");
1377 nfc_llcp_recv_snl(local, skb);
1378 break;
1379
Samuel Ortizd6469602011-12-14 16:43:12 +01001380 case LLCP_PDU_I:
1381 case LLCP_PDU_RR:
Samuel Ortiz53aef922012-03-05 01:03:36 +01001382 case LLCP_PDU_RNR:
Samuel Ortizd6469602011-12-14 16:43:12 +01001383 pr_debug("I frame\n");
1384 nfc_llcp_recv_hdlc(local, skb);
1385 break;
1386
1387 }
1388
Linus Torvalds916082b2012-10-02 16:01:31 -07001389 schedule_work(&local->tx_work);
Samuel Ortizd6469602011-12-14 16:43:12 +01001390 kfree_skb(local->rx_pending);
1391 local->rx_pending = NULL;
Samuel Ortizd6469602011-12-14 16:43:12 +01001392}
1393
Samuel Ortiz1727cf92012-12-07 16:37:30 +01001394static void __nfc_llcp_recv(struct nfc_llcp_local *local, struct sk_buff *skb)
1395{
1396 local->rx_pending = skb;
1397 del_timer(&local->link_timer);
1398 schedule_work(&local->rx_work);
1399}
1400
Samuel Ortizd6469602011-12-14 16:43:12 +01001401void nfc_llcp_recv(void *data, struct sk_buff *skb, int err)
1402{
1403 struct nfc_llcp_local *local = (struct nfc_llcp_local *) data;
1404
1405 pr_debug("Received an LLCP PDU\n");
1406 if (err < 0) {
Samuel Ortiz427a2eb2012-03-05 01:03:52 +01001407 pr_err("err %d\n", err);
Samuel Ortizd6469602011-12-14 16:43:12 +01001408 return;
1409 }
1410
Samuel Ortiz1727cf92012-12-07 16:37:30 +01001411 __nfc_llcp_recv(local, skb);
Samuel Ortizd6469602011-12-14 16:43:12 +01001412}
1413
Samuel Ortiz73167ce2012-05-31 00:05:50 +02001414int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)
1415{
1416 struct nfc_llcp_local *local;
1417
1418 local = nfc_llcp_find_local(dev);
1419 if (local == NULL)
1420 return -ENODEV;
1421
Samuel Ortiz1727cf92012-12-07 16:37:30 +01001422 __nfc_llcp_recv(local, skb);
Samuel Ortiz73167ce2012-05-31 00:05:50 +02001423
1424 return 0;
1425}
1426
Samuel Ortizd6469602011-12-14 16:43:12 +01001427void nfc_llcp_mac_is_down(struct nfc_dev *dev)
1428{
1429 struct nfc_llcp_local *local;
1430
1431 local = nfc_llcp_find_local(dev);
1432 if (local == NULL)
1433 return;
1434
1435 /* Close and purge all existing sockets */
Samuel Ortiz4d22ea12012-06-22 14:40:34 +02001436 nfc_llcp_socket_release(local, true);
Samuel Ortizd6469602011-12-14 16:43:12 +01001437}
1438
1439void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
1440 u8 comm_mode, u8 rf_mode)
1441{
1442 struct nfc_llcp_local *local;
1443
1444 pr_debug("rf mode %d\n", rf_mode);
1445
1446 local = nfc_llcp_find_local(dev);
1447 if (local == NULL)
1448 return;
1449
1450 local->target_idx = target_idx;
1451 local->comm_mode = comm_mode;
1452 local->rf_mode = rf_mode;
1453
1454 if (rf_mode == NFC_RF_INITIATOR) {
1455 pr_debug("Queueing Tx work\n");
1456
Linus Torvalds916082b2012-10-02 16:01:31 -07001457 schedule_work(&local->tx_work);
Samuel Ortizd6469602011-12-14 16:43:12 +01001458 } else {
1459 mod_timer(&local->link_timer,
Samuel Ortiz427a2eb2012-03-05 01:03:52 +01001460 jiffies + msecs_to_jiffies(local->remote_lto));
Samuel Ortizd6469602011-12-14 16:43:12 +01001461 }
1462}
1463
1464int nfc_llcp_register_device(struct nfc_dev *ndev)
1465{
Samuel Ortizd6469602011-12-14 16:43:12 +01001466 struct nfc_llcp_local *local;
Samuel Ortizd6469602011-12-14 16:43:12 +01001467
1468 local = kzalloc(sizeof(struct nfc_llcp_local), GFP_KERNEL);
1469 if (local == NULL)
1470 return -ENOMEM;
1471
1472 local->dev = ndev;
1473 INIT_LIST_HEAD(&local->list);
Samuel Ortizc7aa1222012-05-04 11:24:16 +02001474 kref_init(&local->ref);
Samuel Ortizd6469602011-12-14 16:43:12 +01001475 mutex_init(&local->sdp_lock);
Samuel Ortizd6469602011-12-14 16:43:12 +01001476 init_timer(&local->link_timer);
1477 local->link_timer.data = (unsigned long) local;
1478 local->link_timer.function = nfc_llcp_symm_timer;
1479
1480 skb_queue_head_init(&local->tx_queue);
1481 INIT_WORK(&local->tx_work, nfc_llcp_tx_work);
Samuel Ortizd6469602011-12-14 16:43:12 +01001482
1483 local->rx_pending = NULL;
1484 INIT_WORK(&local->rx_work, nfc_llcp_rx_work);
Samuel Ortizd6469602011-12-14 16:43:12 +01001485
1486 INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work);
Samuel Ortizd6469602011-12-14 16:43:12 +01001487
Szymon Jancfe235b52012-09-25 12:42:50 +02001488 rwlock_init(&local->sockets.lock);
1489 rwlock_init(&local->connecting_sockets.lock);
Thierry Escande44635232012-09-26 18:16:44 +02001490 rwlock_init(&local->raw_sockets.lock);
Samuel Ortiza69f32a2012-05-04 17:04:19 +02001491
Thierry Escande52feb442012-10-17 14:43:39 +02001492 local->lto = 150; /* 1500 ms */
1493 local->rw = LLCP_MAX_RW;
1494 local->miux = cpu_to_be16(LLCP_MAX_MIUX);
1495
Samuel Ortizd6469602011-12-14 16:43:12 +01001496 nfc_llcp_build_gb(local);
1497
1498 local->remote_miu = LLCP_DEFAULT_MIU;
1499 local->remote_lto = LLCP_DEFAULT_LTO;
Samuel Ortizd6469602011-12-14 16:43:12 +01001500
Thierry Escanded9b8d8e2013-02-15 10:43:06 +01001501 mutex_init(&local->sdreq_lock);
1502 INIT_HLIST_HEAD(&local->pending_sdreqs);
Thierry Escande40213fa2013-03-04 15:43:32 +01001503 init_timer(&local->sdreq_timer);
1504 local->sdreq_timer.data = (unsigned long) local;
1505 local->sdreq_timer.function = nfc_llcp_sdreq_timer;
1506 INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work);
Thierry Escanded9b8d8e2013-02-15 10:43:06 +01001507
Thierry Escande16a78e92012-10-12 15:25:43 +02001508 list_add(&local->list, &llcp_devices);
Samuel Ortizd6469602011-12-14 16:43:12 +01001509
1510 return 0;
Samuel Ortizd6469602011-12-14 16:43:12 +01001511}
1512
1513void nfc_llcp_unregister_device(struct nfc_dev *dev)
1514{
1515 struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
1516
1517 if (local == NULL) {
1518 pr_debug("No such device\n");
1519 return;
1520 }
1521
Samuel Ortizc7aa1222012-05-04 11:24:16 +02001522 nfc_llcp_local_put(local);
Samuel Ortizd6469602011-12-14 16:43:12 +01001523}
1524
1525int __init nfc_llcp_init(void)
1526{
1527 INIT_LIST_HEAD(&llcp_devices);
1528
1529 return nfc_llcp_sock_init();
1530}
1531
1532void nfc_llcp_exit(void)
1533{
1534 nfc_llcp_sock_exit();
1535}