2012-09-13 17:10:00 +02:00
/*
* Link Layer Control manager
*
* Copyright ( C ) 2012 Intel Corporation . All rights reserved .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2013-12-06 08:56:16 -08:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2012-09-13 17:10:00 +02:00
*/
# include <net/nfc/llc.h>
2012-09-18 19:17:33 +02:00
2012-09-13 17:10:00 +02:00
# include "llc.h"
2014-02-22 22:14:18 +08:00
static LIST_HEAD ( llc_engines ) ;
2012-09-13 17:10:00 +02:00
int nfc_llc_init ( void )
{
2012-09-13 17:11:37 +02:00
int r ;
r = nfc_llc_nop_register ( ) ;
if ( r )
goto exit ;
r = nfc_llc_shdlc_register ( ) ;
if ( r )
goto exit ;
return 0 ;
exit :
nfc_llc_exit ( ) ;
return r ;
2012-09-13 17:10:00 +02:00
}
void nfc_llc_exit ( void )
{
struct nfc_llc_engine * llc_engine , * n ;
list_for_each_entry_safe ( llc_engine , n , & llc_engines , entry ) {
list_del ( & llc_engine - > entry ) ;
kfree ( llc_engine - > name ) ;
kfree ( llc_engine ) ;
}
}
int nfc_llc_register ( const char * name , struct nfc_llc_ops * ops )
{
struct nfc_llc_engine * llc_engine ;
llc_engine = kzalloc ( sizeof ( struct nfc_llc_engine ) , GFP_KERNEL ) ;
if ( llc_engine = = NULL )
return - ENOMEM ;
llc_engine - > name = kstrdup ( name , GFP_KERNEL ) ;
if ( llc_engine - > name = = NULL ) {
kfree ( llc_engine ) ;
return - ENOMEM ;
}
llc_engine - > ops = ops ;
INIT_LIST_HEAD ( & llc_engine - > entry ) ;
2012-10-17 15:23:39 +02:00
list_add_tail ( & llc_engine - > entry , & llc_engines ) ;
2012-09-13 17:10:00 +02:00
return 0 ;
}
static struct nfc_llc_engine * nfc_llc_name_to_engine ( const char * name )
{
struct nfc_llc_engine * llc_engine ;
list_for_each_entry ( llc_engine , & llc_engines , entry ) {
if ( strcmp ( llc_engine - > name , name ) = = 0 )
return llc_engine ;
}
return NULL ;
}
void nfc_llc_unregister ( const char * name )
{
struct nfc_llc_engine * llc_engine ;
llc_engine = nfc_llc_name_to_engine ( name ) ;
if ( llc_engine = = NULL )
return ;
list_del ( & llc_engine - > entry ) ;
kfree ( llc_engine - > name ) ;
kfree ( llc_engine ) ;
}
struct nfc_llc * nfc_llc_allocate ( const char * name , struct nfc_hci_dev * hdev ,
xmit_to_drv_t xmit_to_drv ,
rcv_to_hci_t rcv_to_hci , int tx_headroom ,
int tx_tailroom , llc_failure_t llc_failure )
{
struct nfc_llc_engine * llc_engine ;
struct nfc_llc * llc ;
llc_engine = nfc_llc_name_to_engine ( name ) ;
if ( llc_engine = = NULL )
return NULL ;
llc = kzalloc ( sizeof ( struct nfc_llc ) , GFP_KERNEL ) ;
if ( llc = = NULL )
return NULL ;
llc - > data = llc_engine - > ops - > init ( hdev , xmit_to_drv , rcv_to_hci ,
tx_headroom , tx_tailroom ,
& llc - > rx_headroom , & llc - > rx_tailroom ,
llc_failure ) ;
if ( llc - > data = = NULL ) {
kfree ( llc ) ;
return NULL ;
}
llc - > ops = llc_engine - > ops ;
return llc ;
}
void nfc_llc_free ( struct nfc_llc * llc )
{
llc - > ops - > deinit ( llc ) ;
kfree ( llc ) ;
}
2016-04-15 18:14:25 +02:00
int nfc_llc_start ( struct nfc_llc * llc )
2012-09-13 17:10:00 +02:00
{
return llc - > ops - > start ( llc ) ;
}
2015-10-26 07:50:11 +01:00
EXPORT_SYMBOL ( nfc_llc_start ) ;
2012-09-13 17:10:00 +02:00
2016-04-15 18:14:25 +02:00
int nfc_llc_stop ( struct nfc_llc * llc )
2012-09-13 17:10:00 +02:00
{
return llc - > ops - > stop ( llc ) ;
}
2015-10-26 07:50:11 +01:00
EXPORT_SYMBOL ( nfc_llc_stop ) ;
2012-09-13 17:10:00 +02:00
2016-04-15 18:14:25 +02:00
void nfc_llc_rcv_from_drv ( struct nfc_llc * llc , struct sk_buff * skb )
2012-09-13 17:10:00 +02:00
{
llc - > ops - > rcv_from_drv ( llc , skb ) ;
}
2016-04-15 18:14:25 +02:00
int nfc_llc_xmit_from_hci ( struct nfc_llc * llc , struct sk_buff * skb )
2012-09-13 17:10:00 +02:00
{
return llc - > ops - > xmit_from_hci ( llc , skb ) ;
}
2016-04-15 18:14:25 +02:00
void * nfc_llc_get_data ( struct nfc_llc * llc )
2012-09-13 17:10:00 +02:00
{
return llc - > data ;
}