Commit 9e58095f authored by Samuel Ortiz's avatar Samuel Ortiz

NFC: netlink: Implement vendor command support

Vendor commands are passed from userspace through the
NFC_CMD_VENDOR netlink command, allowing driver and hardware
specific operations implementations like for example RF tuning
or production line calibration.

Drivers will associate a set of vendor commands to a vendor
id, which could typically be an OUI. The netlink kernel
implementation will try to match the received vendor id
and sub command attributes with the registered ones. When
such match is found, the driver defined sub command routine
is called.
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 8115dd59
...@@ -86,6 +86,8 @@ ...@@ -86,6 +86,8 @@
* 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. * @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller.
* @NFC_CMD_SE_IO: Send/Receive APDUs to/from the selected secure element. * @NFC_CMD_SE_IO: Send/Receive APDUs to/from the selected secure element.
* @NFC_CMD_VENDOR: Vendor specific command, to be implemented directly
* from the driver in order to support hardware specific operations.
*/ */
enum nfc_commands { enum nfc_commands {
NFC_CMD_UNSPEC, NFC_CMD_UNSPEC,
...@@ -117,6 +119,7 @@ enum nfc_commands { ...@@ -117,6 +119,7 @@ enum nfc_commands {
NFC_CMD_GET_SE, NFC_CMD_GET_SE,
NFC_CMD_SE_IO, NFC_CMD_SE_IO,
NFC_CMD_ACTIVATE_TARGET, NFC_CMD_ACTIVATE_TARGET,
NFC_CMD_VENDOR,
/* private: internal use only */ /* private: internal use only */
__NFC_CMD_AFTER_LAST __NFC_CMD_AFTER_LAST
}; };
...@@ -153,6 +156,10 @@ enum nfc_commands { ...@@ -153,6 +156,10 @@ enum nfc_commands {
* @NFC_ATTR_APDU: Secure element APDU * @NFC_ATTR_APDU: Secure element APDU
* @NFC_ATTR_TARGET_ISO15693_DSFID: ISO 15693 Data Storage Format Identifier * @NFC_ATTR_TARGET_ISO15693_DSFID: ISO 15693 Data Storage Format Identifier
* @NFC_ATTR_TARGET_ISO15693_UID: ISO 15693 Unique Identifier * @NFC_ATTR_TARGET_ISO15693_UID: ISO 15693 Unique Identifier
* @NFC_ATTR_VENDOR_ID: NFC manufacturer unique ID, typically an OUI
* @NFC_ATTR_VENDOR_SUBCMD: Vendor specific sub command
* @NFC_ATTR_VENDOR_DATA: Vendor specific data, to be optionally passed
* to a vendor specific command implementation
*/ */
enum nfc_attrs { enum nfc_attrs {
NFC_ATTR_UNSPEC, NFC_ATTR_UNSPEC,
...@@ -184,6 +191,9 @@ enum nfc_attrs { ...@@ -184,6 +191,9 @@ enum nfc_attrs {
NFC_ATTR_TARGET_ISO15693_DSFID, NFC_ATTR_TARGET_ISO15693_DSFID,
NFC_ATTR_TARGET_ISO15693_UID, NFC_ATTR_TARGET_ISO15693_UID,
NFC_ATTR_SE_PARAMS, NFC_ATTR_SE_PARAMS,
NFC_ATTR_VENDOR_ID,
NFC_ATTR_VENDOR_SUBCMD,
NFC_ATTR_VENDOR_DATA,
/* private: internal use only */ /* private: internal use only */
__NFC_ATTR_AFTER_LAST __NFC_ATTR_AFTER_LAST
}; };
......
...@@ -5,6 +5,12 @@ ...@@ -5,6 +5,12 @@
* Lauro Ramos Venancio <lauro.venancio@openbossa.org> * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
* Aloisio Almeida Jr <aloisio.almeida@openbossa.org> * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
* *
* Vendor commands implementation based on net/wireless/nl80211.c
* which is:
*
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
...@@ -1489,6 +1495,50 @@ static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info) ...@@ -1489,6 +1495,50 @@ static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info)
return nfc_se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx); return nfc_se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx);
} }
static int nfc_genl_vendor_cmd(struct sk_buff *skb,
struct genl_info *info)
{
struct nfc_dev *dev;
struct nfc_vendor_cmd *cmd;
u32 dev_idx, vid, subcmd;
u8 *data;
size_t data_len;
int i;
if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
!info->attrs[NFC_ATTR_VENDOR_ID] ||
!info->attrs[NFC_ATTR_VENDOR_SUBCMD])
return -EINVAL;
dev_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
vid = nla_get_u32(info->attrs[NFC_ATTR_VENDOR_ID]);
subcmd = nla_get_u32(info->attrs[NFC_ATTR_VENDOR_SUBCMD]);
dev = nfc_get_device(dev_idx);
if (!dev || !dev->vendor_cmds || !dev->n_vendor_cmds)
return -ENODEV;
data = nla_data(info->attrs[NFC_ATTR_VENDOR_DATA]);
if (data) {
data_len = nla_len(info->attrs[NFC_ATTR_VENDOR_DATA]);
if (data_len == 0)
return -EINVAL;
} else {
data_len = 0;
}
for (i = 0; i < dev->n_vendor_cmds; i++) {
cmd = &dev->vendor_cmds[i];
if (cmd->vendor_id != vid || cmd->subcmd != subcmd)
continue;
return cmd->doit(dev, data, data_len);
}
return -EOPNOTSUPP;
}
static const struct genl_ops nfc_genl_ops[] = { static const struct genl_ops nfc_genl_ops[] = {
{ {
.cmd = NFC_CMD_GET_DEVICE, .cmd = NFC_CMD_GET_DEVICE,
...@@ -1579,6 +1629,11 @@ static const struct genl_ops nfc_genl_ops[] = { ...@@ -1579,6 +1629,11 @@ static const struct genl_ops nfc_genl_ops[] = {
.doit = nfc_genl_activate_target, .doit = nfc_genl_activate_target,
.policy = nfc_genl_policy, .policy = nfc_genl_policy,
}, },
{
.cmd = NFC_CMD_VENDOR,
.doit = nfc_genl_vendor_cmd,
.policy = nfc_genl_policy,
},
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment