Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ac22ac46 authored by Samuel Ortiz's avatar Samuel Ortiz
Browse files

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: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 369f4d50
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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
};
};
+91 −0
Original line number Original line Diff line number Diff line
@@ -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,
	},
};
};