Commit 9907cda9 authored by Juraj Šarinay's avatar Juraj Šarinay Committed by Paolo Abeni
Browse files

net: nfc: Propagate ISO14443 type A target ATS to userspace via netlink



Add a 20-byte field ats to struct nfc_target and expose it as
NFC_ATTR_TARGET_ATS via the netlink interface. The payload contains
'historical bytes' that help to distinguish cards from one another.
The information is commonly used to assemble an emulated ATR similar
to that reported by smart cards with contacts.

Add a 20-byte field target_ats to struct nci_dev to hold the payload
obtained in nci_rf_intf_activated_ntf_packet() and copy it to over to
nfc_target.ats in nci_activate_target(). The approach is similar
to the handling of 'general bytes' within ATR_RES.

Replace the hard-coded size of rats_res within struct
activation_params_nfca_poll_iso_dep by the equal constant NFC_ATS_MAXSIZE
now defined in nfc.h

Within NCI, the information corresponds to the 'RATS Response' activation
parameter that omits the initial length byte TL. This loses no
information and is consistent with our handling of SENSB_RES that
also drops the first (constant) byte.

Tested with nxp_nci_i2c on a few type A targets including an
ICAO 9303 compliant passport.

I refrain from the corresponding change to digital_in_recv_ats()
to have the few drivers based on digital.h fill nfc_target.ats,
as I have no way to test it. That class of drivers appear not to set
NFC_ATTR_TARGET_SENSB_RES either. Consider a separate patch to propagate
(all) the parameters.

Signed-off-by: default avatarJuraj Šarinay <juraj@sarinay.com>
Link: https://patch.msgid.link/20241103124525.8392-1-juraj@sarinay.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent dc7c381b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -475,7 +475,7 @@ struct nci_rf_discover_ntf {
#define NCI_OP_RF_INTF_ACTIVATED_NTF	nci_opcode_pack(NCI_GID_RF_MGMT, 0x05)
struct activation_params_nfca_poll_iso_dep {
	__u8	rats_res_len;
	__u8	rats_res[20];
	__u8	rats_res[NFC_ATS_MAXSIZE];
};

struct activation_params_nfcb_poll_iso_dep {
+4 −0
Original line number Diff line number Diff line
@@ -265,6 +265,10 @@ struct nci_dev {
	/* stored during intf_activated_ntf */
	__u8 remote_gb[NFC_MAX_GT_LEN];
	__u8 remote_gb_len;

	/* stored during intf_activated_ntf */
	__u8 target_ats[NFC_ATS_MAXSIZE];
	__u8 target_ats_len;
};

/* ----- NCI Devices ----- */
+4 −0
Original line number Diff line number Diff line
@@ -86,6 +86,8 @@ struct nfc_ops {
 *	is a type A one. The %sens_res most significant byte must be byte 2
 *	as described by the NFC Forum digital specification (i.e. the platform
 *	configuration one) while %sens_res least significant byte is byte 1.
 * @ats_len: length of Answer To Select in bytes
 * @ats: Answer To Select returned by an ISO 14443 Type A target upon activation
 */
struct nfc_target {
	u32 idx;
@@ -105,6 +107,8 @@ struct nfc_target {
	u8 is_iso15693;
	u8 iso15693_dsfid;
	u8 iso15693_uid[NFC_ISO15693_UID_MAXSIZE];
	u8 ats_len;
	u8 ats[NFC_ATS_MAXSIZE];
};

/**
+3 −0
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ enum nfc_commands {
 * @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
 * @NFC_ATTR_TARGET_ATS: ISO 14443 type A target Answer To Select
 */
enum nfc_attrs {
	NFC_ATTR_UNSPEC,
@@ -198,6 +199,7 @@ enum nfc_attrs {
	NFC_ATTR_VENDOR_ID,
	NFC_ATTR_VENDOR_SUBCMD,
	NFC_ATTR_VENDOR_DATA,
	NFC_ATTR_TARGET_ATS,
/* private: internal use only */
	__NFC_ATTR_AFTER_LAST
};
@@ -225,6 +227,7 @@ enum nfc_sdp_attr {
#define NFC_GB_MAXSIZE			48
#define NFC_FIRMWARE_NAME_MAXSIZE	32
#define NFC_ISO15693_UID_MAXSIZE	8
#define NFC_ATS_MAXSIZE			20

/* NFC protocols */
#define NFC_PROTO_JEWEL		1
+12 −1
Original line number Diff line number Diff line
@@ -757,6 +757,14 @@ int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id)
}
EXPORT_SYMBOL(nci_core_conn_close);

static void nci_set_target_ats(struct nfc_target *target, struct nci_dev *ndev)
{
	if (ndev->target_ats_len > 0) {
		target->ats_len = ndev->target_ats_len;
		memcpy(target->ats, ndev->target_ats, target->ats_len);
	}
}

static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
{
	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
@@ -939,8 +947,11 @@ static int nci_activate_target(struct nfc_dev *nfc_dev,
				 msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT));
	}

	if (!rc)
	if (!rc) {
		ndev->target_active_prot = protocol;
		if (protocol == NFC_PROTO_ISO14443)
			nci_set_target_ats(target, ndev);
	}

	return rc;
}
Loading