mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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:
		
							parent
							
								
									369f4d503a
								
							
						
					
					
						commit
						ac22ac466a
					
				
					 2 changed files with 93 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -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,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue