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
|
* @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
|
* a specific SE notifies us about the end of a transaction. The parameter
|
||||||
* for this event is the application ID (AID).
|
* for this event is the application ID (AID).
|
||||||
|
* @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller.
|
||||||
*/
|
*/
|
||||||
enum nfc_commands {
|
enum nfc_commands {
|
||||||
NFC_CMD_UNSPEC,
|
NFC_CMD_UNSPEC,
|
||||||
|
@ -112,6 +113,7 @@ enum nfc_commands {
|
||||||
NFC_EVENT_SE_REMOVED,
|
NFC_EVENT_SE_REMOVED,
|
||||||
NFC_EVENT_SE_CONNECTIVITY,
|
NFC_EVENT_SE_CONNECTIVITY,
|
||||||
NFC_EVENT_SE_TRANSACTION,
|
NFC_EVENT_SE_TRANSACTION,
|
||||||
|
NFC_CMD_GET_SE,
|
||||||
/* private: internal use only */
|
/* private: internal use only */
|
||||||
__NFC_CMD_AFTER_LAST
|
__NFC_CMD_AFTER_LAST
|
||||||
};
|
};
|
||||||
|
|
|
@ -1191,6 +1191,91 @@ static int nfc_genl_disable_se(struct sk_buff *skb, struct genl_info *info)
|
||||||
return rc;
|
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[] = {
|
static struct genl_ops nfc_genl_ops[] = {
|
||||||
{
|
{
|
||||||
.cmd = NFC_CMD_GET_DEVICE,
|
.cmd = NFC_CMD_GET_DEVICE,
|
||||||
|
@ -1265,6 +1350,12 @@ static struct genl_ops nfc_genl_ops[] = {
|
||||||
.doit = nfc_genl_disable_se,
|
.doit = nfc_genl_disable_se,
|
||||||
.policy = nfc_genl_policy,
|
.policy = nfc_genl_policy,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.cmd = NFC_CMD_GET_SE,
|
||||||
|
.dumpit = nfc_genl_dump_ses,
|
||||||
|
.done = nfc_genl_dump_ses_done,
|
||||||
|
.policy = nfc_genl_policy,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче