2019-05-31 01:09:57 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2012-09-13 17:10:00 +02:00
/*
* Link Layer Control manager
*
* Copyright ( C ) 2012 Intel Corporation . All rights reserved .
*/
# 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
2021-07-30 16:41:58 +02:00
int __init nfc_llc_init ( void )
2012-09-13 17:10:00 +02:00
{
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
}
2024-02-03 08:51:03 +01:00
static void nfc_llc_del_engine ( struct nfc_llc_engine * llc_engine )
{
list_del ( & llc_engine - > entry ) ;
2024-02-03 08:51:04 +01:00
kfree_const ( llc_engine - > name ) ;
2024-02-03 08:51:03 +01:00
kfree ( llc_engine ) ;
}
2012-09-13 17:10:00 +02:00
void nfc_llc_exit ( void )
{
struct nfc_llc_engine * llc_engine , * n ;
2024-02-03 08:51:03 +01:00
list_for_each_entry_safe ( llc_engine , n , & llc_engines , entry )
nfc_llc_del_engine ( llc_engine ) ;
2012-09-13 17:10:00 +02:00
}
2021-07-24 23:49:27 +02:00
int nfc_llc_register ( const char * name , const struct nfc_llc_ops * ops )
2012-09-13 17:10:00 +02:00
{
struct nfc_llc_engine * llc_engine ;
llc_engine = kzalloc ( sizeof ( struct nfc_llc_engine ) , GFP_KERNEL ) ;
if ( llc_engine = = NULL )
return - ENOMEM ;
2024-02-03 08:51:04 +01:00
llc_engine - > name = kstrdup_const ( name , GFP_KERNEL ) ;
2012-09-13 17:10:00 +02:00
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 ;
2024-02-03 08:51:03 +01:00
nfc_llc_del_engine ( llc_engine ) ;
2012-09-13 17:10:00 +02:00
}
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 ;
}