Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFC: Add NFC_CMD_DEACTIVATE_TARGET support

Once an NFC target (i.e., a tag) is found, it remains active until
there is a failure reading or writing it (often caused by the target
moving out of range). While the target is active, the NFC adapter
and antenna must remain powered. This wastes power when the target
remains in range but the client application no longer cares whether
it is there or not.

To mitigate this, add a new netlink command that allows userspace
to deactivate an active target. When issued, this command will cause
the NFC subsystem to act as though the target was moved out of range.
Once the command has been executed, the client application can power
off the NFC adapter to reduce power consumption.

Signed-off-by: Mark Greer <mgreer@animalcreek.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Mark Greer and committed by
Samuel Ortiz
4d63adfe 72ad533a

+31
+2
include/uapi/linux/nfc.h
··· 89 89 * @NFC_CMD_ACTIVATE_TARGET: Request NFC controller to reactivate target. 90 90 * @NFC_CMD_VENDOR: Vendor specific command, to be implemented directly 91 91 * from the driver in order to support hardware specific operations. 92 + * @NFC_CMD_DEACTIVATE_TARGET: Request NFC controller to deactivate target. 92 93 */ 93 94 enum nfc_commands { 94 95 NFC_CMD_UNSPEC, ··· 122 121 NFC_CMD_SE_IO, 123 122 NFC_CMD_ACTIVATE_TARGET, 124 123 NFC_CMD_VENDOR, 124 + NFC_CMD_DEACTIVATE_TARGET, 125 125 /* private: internal use only */ 126 126 __NFC_CMD_AFTER_LAST 127 127 };
+29
net/nfc/netlink.c
··· 928 928 return rc; 929 929 } 930 930 931 + static int nfc_genl_deactivate_target(struct sk_buff *skb, 932 + struct genl_info *info) 933 + { 934 + struct nfc_dev *dev; 935 + u32 device_idx, target_idx; 936 + int rc; 937 + 938 + if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) 939 + return -EINVAL; 940 + 941 + device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); 942 + 943 + dev = nfc_get_device(device_idx); 944 + if (!dev) 945 + return -ENODEV; 946 + 947 + target_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]); 948 + 949 + rc = nfc_deactivate_target(dev, target_idx, NFC_TARGET_MODE_SLEEP); 950 + 951 + nfc_put_device(dev); 952 + return rc; 953 + } 954 + 931 955 static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info) 932 956 { 933 957 struct nfc_dev *dev; ··· 1773 1749 { 1774 1750 .cmd = NFC_CMD_VENDOR, 1775 1751 .doit = nfc_genl_vendor_cmd, 1752 + .policy = nfc_genl_policy, 1753 + }, 1754 + { 1755 + .cmd = NFC_CMD_DEACTIVATE_TARGET, 1756 + .doit = nfc_genl_deactivate_target, 1776 1757 .policy = nfc_genl_policy, 1777 1758 }, 1778 1759 };