NFC: Add a GET_SE netlink API
In order to fetch the discovered secure elements from an NFC controller, we need to send a netlink command that will dump the list of available SEs from NFC. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Родитель
369f4d503a
Коммит
ac22ac466a
|
@ -84,6 +84,7 @@
|
|||
* @NFC_EVENT_SE_TRANSACTION: This event is sent when an application running on
|
||||
* a specific SE notifies us about the end of a transaction. The parameter
|
||||
* for this event is the application ID (AID).
|
||||
* @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller.
|
||||
*/
|
||||
enum nfc_commands {
|
||||
NFC_CMD_UNSPEC,
|
||||
|
@ -112,6 +113,7 @@ enum nfc_commands {
|
|||
NFC_EVENT_SE_REMOVED,
|
||||
NFC_EVENT_SE_CONNECTIVITY,
|
||||
NFC_EVENT_SE_TRANSACTION,
|
||||
NFC_CMD_GET_SE,
|
||||
/* private: internal use only */
|
||||
__NFC_CMD_AFTER_LAST
|
||||
};
|
||||
|
|
|
@ -1191,6 +1191,91 @@ static int nfc_genl_disable_se(struct sk_buff *skb, struct genl_info *info)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int nfc_genl_send_se(struct sk_buff *msg, struct nfc_dev *dev,
|
||||
u32 portid, u32 seq,
|
||||
struct netlink_callback *cb,
|
||||
int flags)
|
||||
{
|
||||
void *hdr;
|
||||
struct nfc_se *se, *n;
|
||||
|
||||
list_for_each_entry_safe(se, n, &dev->secure_elements, list) {
|
||||
hdr = genlmsg_put(msg, portid, seq, &nfc_genl_family, flags,
|
||||
NFC_CMD_GET_SE);
|
||||
if (!hdr)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (cb)
|
||||
genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
|
||||
|
||||
if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
|
||||
nla_put_u32(msg, NFC_ATTR_SE_INDEX, se->idx) ||
|
||||
nla_put_u8(msg, NFC_ATTR_SE_TYPE, se->type))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (genlmsg_end(msg, hdr) < 0)
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nfc_genl_dump_ses(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
|
||||
struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
|
||||
bool first_call = false;
|
||||
|
||||
if (!iter) {
|
||||
first_call = true;
|
||||
iter = kmalloc(sizeof(struct class_dev_iter), GFP_KERNEL);
|
||||
if (!iter)
|
||||
return -ENOMEM;
|
||||
cb->args[0] = (long) iter;
|
||||
}
|
||||
|
||||
mutex_lock(&nfc_devlist_mutex);
|
||||
|
||||
cb->seq = nfc_devlist_generation;
|
||||
|
||||
if (first_call) {
|
||||
nfc_device_iter_init(iter);
|
||||
dev = nfc_device_iter_next(iter);
|
||||
}
|
||||
|
||||
while (dev) {
|
||||
int rc;
|
||||
|
||||
rc = nfc_genl_send_se(skb, dev, NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, cb, NLM_F_MULTI);
|
||||
if (rc < 0)
|
||||
break;
|
||||
|
||||
dev = nfc_device_iter_next(iter);
|
||||
}
|
||||
|
||||
mutex_unlock(&nfc_devlist_mutex);
|
||||
|
||||
cb->args[1] = (long) dev;
|
||||
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
static int nfc_genl_dump_ses_done(struct netlink_callback *cb)
|
||||
{
|
||||
struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
|
||||
|
||||
nfc_device_iter_exit(iter);
|
||||
kfree(iter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct genl_ops nfc_genl_ops[] = {
|
||||
{
|
||||
.cmd = NFC_CMD_GET_DEVICE,
|
||||
|
@ -1265,6 +1350,12 @@ static struct genl_ops nfc_genl_ops[] = {
|
|||
.doit = nfc_genl_disable_se,
|
||||
.policy = nfc_genl_policy,
|
||||
},
|
||||
{
|
||||
.cmd = NFC_CMD_GET_SE,
|
||||
.dumpit = nfc_genl_dump_ses,
|
||||
.done = nfc_genl_dump_ses_done,
|
||||
.policy = nfc_genl_policy,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче