@ -29,6 +29,8 @@
# include "nfc.h"
# include "llcp/llcp.h"
static struct genl_multicast_group nfc_genl_event_mcgrp = {
. name = NFC_GENL_MCAST_EVENT_NAME ,
} ;
@ -716,6 +718,146 @@ static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info)
return rc ;
}
static int nfc_genl_send_params ( struct sk_buff * msg ,
struct nfc_llcp_local * local ,
u32 portid , u32 seq )
{
void * hdr ;
hdr = genlmsg_put ( msg , portid , seq , & nfc_genl_family , 0 ,
NFC_CMD_LLC_GET_PARAMS ) ;
if ( ! hdr )
return - EMSGSIZE ;
if ( nla_put_u32 ( msg , NFC_ATTR_DEVICE_INDEX , local - > dev - > idx ) | |
nla_put_u8 ( msg , NFC_ATTR_LLC_PARAM_LTO , local - > lto ) | |
nla_put_u8 ( msg , NFC_ATTR_LLC_PARAM_RW , local - > rw ) | |
nla_put_u16 ( msg , NFC_ATTR_LLC_PARAM_MIUX , be16_to_cpu ( local - > miux ) ) )
goto nla_put_failure ;
return genlmsg_end ( msg , hdr ) ;
nla_put_failure :
genlmsg_cancel ( msg , hdr ) ;
return - EMSGSIZE ;
}
static int nfc_genl_llc_get_params ( struct sk_buff * skb , struct genl_info * info )
{
struct nfc_dev * dev ;
struct nfc_llcp_local * local ;
int rc = 0 ;
struct sk_buff * msg = NULL ;
u32 idx ;
if ( ! info - > attrs [ NFC_ATTR_DEVICE_INDEX ] )
return - EINVAL ;
idx = nla_get_u32 ( info - > attrs [ NFC_ATTR_DEVICE_INDEX ] ) ;
dev = nfc_get_device ( idx ) ;
if ( ! dev )
return - ENODEV ;
device_lock ( & dev - > dev ) ;
local = nfc_llcp_find_local ( dev ) ;
if ( ! local ) {
rc = - ENODEV ;
goto exit ;
}
msg = nlmsg_new ( NLMSG_DEFAULT_SIZE , GFP_KERNEL ) ;
if ( ! msg ) {
rc = - ENOMEM ;
goto exit ;
}
rc = nfc_genl_send_params ( msg , local , info - > snd_portid , info - > snd_seq ) ;
exit :
device_unlock ( & dev - > dev ) ;
nfc_put_device ( dev ) ;
if ( rc < 0 ) {
if ( msg )
nlmsg_free ( msg ) ;
return rc ;
}
return genlmsg_reply ( msg , info ) ;
}
static int nfc_genl_llc_set_params ( struct sk_buff * skb , struct genl_info * info )
{
struct nfc_dev * dev ;
struct nfc_llcp_local * local ;
u8 rw = 0 ;
u16 miux = 0 ;
u32 idx ;
int rc = 0 ;
if ( ! info - > attrs [ NFC_ATTR_DEVICE_INDEX ] | |
( ! info - > attrs [ NFC_ATTR_LLC_PARAM_LTO ] & &
! info - > attrs [ NFC_ATTR_LLC_PARAM_RW ] & &
! info - > attrs [ NFC_ATTR_LLC_PARAM_MIUX ] ) )
return - EINVAL ;
if ( info - > attrs [ NFC_ATTR_LLC_PARAM_RW ] ) {
rw = nla_get_u8 ( info - > attrs [ NFC_ATTR_LLC_PARAM_RW ] ) ;
if ( rw > LLCP_MAX_RW )
return - EINVAL ;
}
if ( info - > attrs [ NFC_ATTR_LLC_PARAM_MIUX ] ) {
miux = nla_get_u16 ( info - > attrs [ NFC_ATTR_LLC_PARAM_MIUX ] ) ;
if ( miux > LLCP_MAX_MIUX )
return - EINVAL ;
}
idx = nla_get_u32 ( info - > attrs [ NFC_ATTR_DEVICE_INDEX ] ) ;
dev = nfc_get_device ( idx ) ;
if ( ! dev )
return - ENODEV ;
device_lock ( & dev - > dev ) ;
local = nfc_llcp_find_local ( dev ) ;
if ( ! local ) {
nfc_put_device ( dev ) ;
rc = - ENODEV ;
goto exit ;
}
if ( info - > attrs [ NFC_ATTR_LLC_PARAM_LTO ] ) {
if ( dev - > dep_link_up ) {
rc = - EINPROGRESS ;
goto exit ;
}
local - > lto = nla_get_u8 ( info - > attrs [ NFC_ATTR_LLC_PARAM_LTO ] ) ;
}
if ( info - > attrs [ NFC_ATTR_LLC_PARAM_RW ] )
local - > rw = rw ;
if ( info - > attrs [ NFC_ATTR_LLC_PARAM_MIUX ] )
local - > miux = cpu_to_be16 ( miux ) ;
exit :
device_unlock ( & dev - > dev ) ;
nfc_put_device ( dev ) ;
return rc ;
}
static struct genl_ops nfc_genl_ops [ ] = {
{
. cmd = NFC_CMD_GET_DEVICE ,
@ -760,6 +902,16 @@ static struct genl_ops nfc_genl_ops[] = {
. done = nfc_genl_dump_targets_done ,
. policy = nfc_genl_policy ,
} ,
{
. cmd = NFC_CMD_LLC_GET_PARAMS ,
. doit = nfc_genl_llc_get_params ,
. policy = nfc_genl_policy ,
} ,
{
. cmd = NFC_CMD_LLC_SET_PARAMS ,
. doit = nfc_genl_llc_set_params ,
. policy = nfc_genl_policy ,
} ,
} ;