diff options
Diffstat (limited to 'net/nfc/af_nfc.c')
-rw-r--r-- | net/nfc/af_nfc.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/net/nfc/af_nfc.c b/net/nfc/af_nfc.c new file mode 100644 index 000000000000..e982cef8f49d --- /dev/null +++ b/net/nfc/af_nfc.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Instituto Nokia de Tecnologia | ||
3 | * | ||
4 | * Authors: | ||
5 | * Aloisio Almeida Jr <aloisio.almeida@openbossa.org> | ||
6 | * Lauro Ramos Venancio <lauro.venancio@openbossa.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the | ||
20 | * Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/nfc.h> | ||
25 | |||
26 | #include "nfc.h" | ||
27 | |||
28 | static DEFINE_RWLOCK(proto_tab_lock); | ||
29 | static const struct nfc_protocol *proto_tab[NFC_SOCKPROTO_MAX]; | ||
30 | |||
31 | static int nfc_sock_create(struct net *net, struct socket *sock, int proto, | ||
32 | int kern) | ||
33 | { | ||
34 | int rc = -EPROTONOSUPPORT; | ||
35 | |||
36 | if (net != &init_net) | ||
37 | return -EAFNOSUPPORT; | ||
38 | |||
39 | if (proto < 0 || proto >= NFC_SOCKPROTO_MAX) | ||
40 | return -EINVAL; | ||
41 | |||
42 | read_lock(&proto_tab_lock); | ||
43 | if (proto_tab[proto] && try_module_get(proto_tab[proto]->owner)) { | ||
44 | rc = proto_tab[proto]->create(net, sock, proto_tab[proto]); | ||
45 | module_put(proto_tab[proto]->owner); | ||
46 | } | ||
47 | read_unlock(&proto_tab_lock); | ||
48 | |||
49 | return rc; | ||
50 | } | ||
51 | |||
52 | static struct net_proto_family nfc_sock_family_ops = { | ||
53 | .owner = THIS_MODULE, | ||
54 | .family = PF_NFC, | ||
55 | .create = nfc_sock_create, | ||
56 | }; | ||
57 | |||
58 | int nfc_proto_register(const struct nfc_protocol *nfc_proto) | ||
59 | { | ||
60 | int rc; | ||
61 | |||
62 | if (nfc_proto->id < 0 || nfc_proto->id >= NFC_SOCKPROTO_MAX) | ||
63 | return -EINVAL; | ||
64 | |||
65 | rc = proto_register(nfc_proto->proto, 0); | ||
66 | if (rc) | ||
67 | return rc; | ||
68 | |||
69 | write_lock(&proto_tab_lock); | ||
70 | if (proto_tab[nfc_proto->id]) | ||
71 | rc = -EBUSY; | ||
72 | else | ||
73 | proto_tab[nfc_proto->id] = nfc_proto; | ||
74 | write_unlock(&proto_tab_lock); | ||
75 | |||
76 | return rc; | ||
77 | } | ||
78 | EXPORT_SYMBOL(nfc_proto_register); | ||
79 | |||
80 | void nfc_proto_unregister(const struct nfc_protocol *nfc_proto) | ||
81 | { | ||
82 | write_lock(&proto_tab_lock); | ||
83 | proto_tab[nfc_proto->id] = NULL; | ||
84 | write_unlock(&proto_tab_lock); | ||
85 | |||
86 | proto_unregister(nfc_proto->proto); | ||
87 | } | ||
88 | EXPORT_SYMBOL(nfc_proto_unregister); | ||
89 | |||
90 | int __init af_nfc_init(void) | ||
91 | { | ||
92 | return sock_register(&nfc_sock_family_ops); | ||
93 | } | ||
94 | |||
95 | void af_nfc_exit(void) | ||
96 | { | ||
97 | sock_unregister(PF_NFC); | ||
98 | } | ||