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