summaryrefslogtreecommitdiffstats
path: root/include/net/nfc
diff options
context:
space:
mode:
authorZeng Chi <zengchi@kylinos.cn>2026-09-21 18:24:42 +0800
committerSean Christopherson <seanjc@google.com>2026-09-22 08:36:16 -0700
commit119e9db233ad0f4cbd4cfb9f9385a7bca378b37d (patch)
tree660d50d4139cb750fbde1ae3432452c20726c99d /include/net/nfc
downloadlinux-stable-119e9db233ad0f4cbd4cfb9f9385a7bca378b37d.tar.gz
linux-stable-119e9db233ad0f4cbd4cfb9f9385a7bca378b37d.zip
KVM: Don't pre-reserve xarray entries when storing empty/NULL attributesgrafted
Skip the xarray reservation loop when clearing all memory attributes, as storing NULL only erases the entry and never needs to allocate, so no reservation (and no cleanup of a failed one) is required in that case. Suggested-by: Sean Christopherson <seanjc@google.com> Cc: David Ballesteros <davimaba.v@proton.me> Signed-off-by: Zeng Chi <zengchi@kylinos.cn> Link: https://patch.msgid.link/20260921102442.1232375-1-zeng_chi911@163.com [sean: split to separate patch] Signed-off-by: Sean Christopherson <seanjc@google.com>
Diffstat (limited to 'include/net/nfc')
-rw-r--r--include/net/nfc/digital.h265
-rw-r--r--include/net/nfc/hci.h275
-rw-r--r--include/net/nfc/llc.h37
-rw-r--r--include/net/nfc/nci.h561
-rw-r--r--include/net/nfc/nci_core.h469
-rw-r--r--include/net/nfc/nfc.h358
6 files changed, 1965 insertions, 0 deletions
diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h
new file mode 100644
index 000000000..bb3e8fdc0
--- /dev/null
+++ b/include/net/nfc/digital.h
@@ -0,0 +1,265 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * NFC Digital Protocol stack
+ * Copyright (c) 2013, Intel Corporation.
+ */
+
+#ifndef __NFC_DIGITAL_H
+#define __NFC_DIGITAL_H
+
+#include <linux/skbuff.h>
+#include <net/nfc/nfc.h>
+
+/**
+ * Configuration types for in_configure_hw and tg_configure_hw.
+ */
+enum {
+ NFC_DIGITAL_CONFIG_RF_TECH = 0,
+ NFC_DIGITAL_CONFIG_FRAMING,
+};
+
+/**
+ * RF technology values passed as param argument to in_configure_hw and
+ * tg_configure_hw for NFC_DIGITAL_CONFIG_RF_TECH configuration type.
+ */
+enum {
+ NFC_DIGITAL_RF_TECH_106A = 0,
+ NFC_DIGITAL_RF_TECH_212F,
+ NFC_DIGITAL_RF_TECH_424F,
+ NFC_DIGITAL_RF_TECH_ISO15693,
+ NFC_DIGITAL_RF_TECH_106B,
+
+ NFC_DIGITAL_RF_TECH_LAST,
+};
+
+/**
+ * Framing configuration passed as param argument to in_configure_hw and
+ * tg_configure_hw for NFC_DIGITAL_CONFIG_FRAMING configuration type.
+ */
+enum {
+ NFC_DIGITAL_FRAMING_NFCA_SHORT = 0,
+ NFC_DIGITAL_FRAMING_NFCA_STANDARD,
+ NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A,
+ NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE,
+
+ NFC_DIGITAL_FRAMING_NFCA_T1T,
+ NFC_DIGITAL_FRAMING_NFCA_T2T,
+ NFC_DIGITAL_FRAMING_NFCA_T4T,
+ NFC_DIGITAL_FRAMING_NFCA_NFC_DEP,
+
+ NFC_DIGITAL_FRAMING_NFCF,
+ NFC_DIGITAL_FRAMING_NFCF_T3T,
+ NFC_DIGITAL_FRAMING_NFCF_NFC_DEP,
+ NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED,
+
+ NFC_DIGITAL_FRAMING_ISO15693_INVENTORY,
+ NFC_DIGITAL_FRAMING_ISO15693_T5T,
+
+ NFC_DIGITAL_FRAMING_NFCB,
+ NFC_DIGITAL_FRAMING_NFCB_T4T,
+
+ NFC_DIGITAL_FRAMING_LAST,
+};
+
+#define DIGITAL_MDAA_NFCID1_SIZE 3
+
+struct digital_tg_mdaa_params {
+ u16 sens_res;
+ u8 nfcid1[DIGITAL_MDAA_NFCID1_SIZE];
+ u8 sel_res;
+
+ u8 nfcid2[NFC_NFCID2_MAXSIZE];
+ u16 sc;
+};
+
+struct nfc_digital_dev;
+
+/**
+ * nfc_digital_cmd_complete_t - Definition of command result callback
+ *
+ * @ddev: nfc_digital_device ref
+ * @arg: user data
+ * @resp: response data
+ *
+ * resp pointer can be an error code and will be checked with IS_ERR() macro.
+ * The callback is responsible for freeing resp sk_buff.
+ */
+typedef void (*nfc_digital_cmd_complete_t)(struct nfc_digital_dev *ddev,
+ void *arg, struct sk_buff *resp);
+
+/**
+ * Device side NFC Digital operations
+ *
+ * Initiator mode:
+ * @in_configure_hw: Hardware configuration for RF technology and communication
+ * framing in initiator mode. This is a synchronous function.
+ * @in_send_cmd: Initiator mode data exchange using RF technology and framing
+ * previously set with in_configure_hw. The peer response is returned
+ * through callback cb. If an io error occurs or the peer didn't reply
+ * within the specified timeout (ms), the error code is passed back through
+ * the resp pointer. This is an asynchronous function.
+ *
+ * Target mode: Only NFC-DEP protocol is supported in target mode.
+ * @tg_configure_hw: Hardware configuration for RF technology and communication
+ * framing in target mode. This is a synchronous function.
+ * @tg_send_cmd: Target mode data exchange using RF technology and framing
+ * previously set with tg_configure_hw. The peer next command is returned
+ * through callback cb. If an io error occurs or the peer didn't reply
+ * within the specified timeout (ms), the error code is passed back through
+ * the resp pointer. This is an asynchronous function.
+ * @tg_listen: Put the device in listen mode waiting for data from the peer
+ * device. This is an asynchronous function.
+ * @tg_listen_mdaa: If supported, put the device in automatic listen mode with
+ * mode detection and automatic anti-collision. In this mode, the device
+ * automatically detects the RF technology and executes the anti-collision
+ * detection using the command responses specified in mdaa_params. The
+ * mdaa_params structure contains SENS_RES, NFCID1, and SEL_RES for 106A RF
+ * tech. NFCID2 and system code (sc) for 212F and 424F. The driver returns
+ * the NFC-DEP ATR_REQ command through cb. The digital stack deducts the RF
+ * tech by analyzing the SoD of the frame containing the ATR_REQ command.
+ * This is an asynchronous function.
+ * @tg_listen_md: If supported, put the device in automatic listen mode with
+ * mode detection but without automatic anti-collision. In this mode, the
+ * device automatically detects the RF technology. What the actual
+ * RF technology is can be retrieved by calling @tg_get_rf_tech.
+ * The digital stack will then perform the appropriate anti-collision
+ * sequence. This is an asynchronous function.
+ * @tg_get_rf_tech: Required when @tg_listen_md is supported, unused otherwise.
+ * Return the RF Technology that was detected by the @tg_listen_md call.
+ * This is a synchronous function.
+ *
+ * @switch_rf: Turns device radio on or off. The stack does not call explicitly
+ * switch_rf to turn the radio on. A call to in|tg_configure_hw must turn
+ * the device radio on.
+ * @abort_cmd: Discard the last sent command.
+ *
+ * Notes: Asynchronous functions have a timeout parameter. It is the driver
+ * responsibility to call the digital stack back through the
+ * nfc_digital_cmd_complete_t callback when no RF respsonse has been
+ * received within the specified time (in milliseconds). In that case the
+ * driver must set the resp sk_buff to ERR_PTR(-ETIMEDOUT).
+ * Since the digital stack serializes commands to be sent, it's mandatory
+ * for the driver to handle the timeout correctly. Otherwise the stack
+ * would not be able to send new commands, waiting for the reply of the
+ * current one.
+ */
+struct nfc_digital_ops {
+ int (*in_configure_hw)(struct nfc_digital_dev *ddev, int type,
+ int param);
+ int (*in_send_cmd)(struct nfc_digital_dev *ddev, struct sk_buff *skb,
+ u16 timeout, nfc_digital_cmd_complete_t cb,
+ void *arg);
+
+ int (*tg_configure_hw)(struct nfc_digital_dev *ddev, int type,
+ int param);
+ int (*tg_send_cmd)(struct nfc_digital_dev *ddev, struct sk_buff *skb,
+ u16 timeout, nfc_digital_cmd_complete_t cb,
+ void *arg);
+ int (*tg_listen)(struct nfc_digital_dev *ddev, u16 timeout,
+ nfc_digital_cmd_complete_t cb, void *arg);
+ int (*tg_listen_mdaa)(struct nfc_digital_dev *ddev,
+ struct digital_tg_mdaa_params *mdaa_params,
+ u16 timeout, nfc_digital_cmd_complete_t cb,
+ void *arg);
+ int (*tg_listen_md)(struct nfc_digital_dev *ddev, u16 timeout,
+ nfc_digital_cmd_complete_t cb, void *arg);
+ int (*tg_get_rf_tech)(struct nfc_digital_dev *ddev, u8 *rf_tech);
+
+ int (*switch_rf)(struct nfc_digital_dev *ddev, bool on);
+ void (*abort_cmd)(struct nfc_digital_dev *ddev);
+};
+
+#define NFC_DIGITAL_POLL_MODE_COUNT_MAX 6 /* 106A, 212F, and 424F in & tg */
+
+typedef int (*digital_poll_t)(struct nfc_digital_dev *ddev, u8 rf_tech);
+
+struct digital_poll_tech {
+ u8 rf_tech;
+ digital_poll_t poll_func;
+};
+
+/**
+ * Driver capabilities - bit mask made of the following values
+ *
+ * @NFC_DIGITAL_DRV_CAPS_IN_CRC: The driver handles CRC calculation in initiator
+ * mode.
+ * @NFC_DIGITAL_DRV_CAPS_TG_CRC: The driver handles CRC calculation in target
+ * mode.
+ */
+#define NFC_DIGITAL_DRV_CAPS_IN_CRC 0x0001
+#define NFC_DIGITAL_DRV_CAPS_TG_CRC 0x0002
+
+struct nfc_digital_dev {
+ struct nfc_dev *nfc_dev;
+ const struct nfc_digital_ops *ops;
+
+ u32 protocols;
+
+ int tx_headroom;
+ int tx_tailroom;
+
+ u32 driver_capabilities;
+ void *driver_data;
+
+ struct digital_poll_tech poll_techs[NFC_DIGITAL_POLL_MODE_COUNT_MAX];
+ u8 poll_tech_count;
+ u8 poll_tech_index;
+ struct mutex poll_lock;
+
+ struct work_struct cmd_work;
+ struct work_struct cmd_complete_work;
+ struct list_head cmd_queue;
+ struct mutex cmd_lock;
+
+ struct delayed_work poll_work;
+
+ u8 curr_protocol;
+ u8 curr_rf_tech;
+ u8 curr_nfc_dep_pni;
+ u8 did;
+ u16 dep_rwt;
+
+ u8 local_payload_max;
+ u8 remote_payload_max;
+
+ struct sk_buff *chaining_skb;
+ struct digital_data_exch *data_exch;
+
+ int atn_count;
+ int nack_count;
+
+ struct sk_buff *saved_skb;
+
+ u16 target_fsc;
+
+ int (*skb_check_crc)(struct sk_buff *skb);
+ void (*skb_add_crc)(struct sk_buff *skb);
+};
+
+struct nfc_digital_dev *nfc_digital_allocate_device(const struct nfc_digital_ops *ops,
+ __u32 supported_protocols,
+ __u32 driver_capabilities,
+ int tx_headroom,
+ int tx_tailroom);
+void nfc_digital_free_device(struct nfc_digital_dev *ndev);
+int nfc_digital_register_device(struct nfc_digital_dev *ndev);
+void nfc_digital_unregister_device(struct nfc_digital_dev *ndev);
+
+static inline void nfc_digital_set_parent_dev(struct nfc_digital_dev *ndev,
+ struct device *dev)
+{
+ nfc_set_parent_dev(ndev->nfc_dev, dev);
+}
+
+static inline void nfc_digital_set_drvdata(struct nfc_digital_dev *dev,
+ void *data)
+{
+ dev->driver_data = data;
+}
+
+static inline void *nfc_digital_get_drvdata(struct nfc_digital_dev *dev)
+{
+ return dev->driver_data;
+}
+
+#endif /* __NFC_DIGITAL_H */
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
new file mode 100644
index 000000000..756c11084
--- /dev/null
+++ b/include/net/nfc/hci.h
@@ -0,0 +1,275 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ */
+
+#ifndef __NET_HCI_H
+#define __NET_HCI_H
+
+#include <linux/skbuff.h>
+
+#include <net/nfc/nfc.h>
+
+struct nfc_hci_dev;
+
+struct nfc_hci_ops {
+ int (*open) (struct nfc_hci_dev *hdev);
+ void (*close) (struct nfc_hci_dev *hdev);
+ int (*load_session) (struct nfc_hci_dev *hdev);
+ int (*hci_ready) (struct nfc_hci_dev *hdev);
+ /*
+ * xmit must always send the complete buffer before
+ * returning. Returned result must be 0 for success
+ * or negative for failure.
+ */
+ int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb);
+ int (*start_poll) (struct nfc_hci_dev *hdev,
+ u32 im_protocols, u32 tm_protocols);
+ void (*stop_poll) (struct nfc_hci_dev *hdev);
+ int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target,
+ u8 comm_mode, u8 *gb, size_t gb_len);
+ int (*dep_link_down)(struct nfc_hci_dev *hdev);
+ int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate,
+ struct nfc_target *target);
+ int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate,
+ struct nfc_target *target);
+ int (*im_transceive) (struct nfc_hci_dev *hdev,
+ struct nfc_target *target, struct sk_buff *skb,
+ data_exchange_cb_t cb, void *cb_context);
+ int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+ int (*check_presence)(struct nfc_hci_dev *hdev,
+ struct nfc_target *target);
+ int (*event_received)(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
+ struct sk_buff *skb);
+ void (*cmd_received)(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
+ struct sk_buff *skb);
+ int (*fw_download)(struct nfc_hci_dev *hdev, const char *firmware_name);
+ int (*discover_se)(struct nfc_hci_dev *dev);
+ int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx);
+ int (*disable_se)(struct nfc_hci_dev *dev, u32 se_idx);
+ int (*se_io)(struct nfc_hci_dev *dev, u32 se_idx,
+ u8 *apdu, size_t apdu_length,
+ se_io_cb_t cb, void *cb_context);
+};
+
+/* Pipes */
+#define NFC_HCI_DO_NOT_CREATE_PIPE 0x81
+#define NFC_HCI_INVALID_PIPE 0x80
+#define NFC_HCI_INVALID_GATE 0xFF
+#define NFC_HCI_INVALID_HOST 0x80
+#define NFC_HCI_LINK_MGMT_PIPE 0x00
+#define NFC_HCI_ADMIN_PIPE 0x01
+
+struct nfc_hci_gate {
+ u8 gate;
+ u8 pipe;
+};
+
+struct nfc_hci_pipe {
+ u8 gate;
+ u8 dest_host;
+};
+
+#define NFC_HCI_MAX_CUSTOM_GATES 50
+/*
+ * According to specification 102 622 chapter 4.4 Pipes,
+ * the pipe identifier is 7 bits long.
+ */
+#define NFC_HCI_MAX_PIPES 128
+struct nfc_hci_init_data {
+ u8 gate_count;
+ struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES];
+ char session_id[9];
+};
+
+typedef int (*xmit) (struct sk_buff *skb, void *cb_data);
+
+#define NFC_HCI_MAX_GATES 256
+
+/*
+ * These values can be specified by a driver to indicate it requires some
+ * adaptation of the HCI standard.
+ *
+ * NFC_HCI_QUIRK_SHORT_CLEAR - send HCI_ADM_CLEAR_ALL_PIPE cmd with no params
+ */
+enum {
+ NFC_HCI_QUIRK_SHORT_CLEAR = 0,
+};
+
+struct nfc_hci_dev {
+ struct nfc_dev *ndev;
+
+ u32 max_data_link_payload;
+
+ bool shutting_down;
+
+ struct mutex msg_tx_mutex;
+
+ struct list_head msg_tx_queue;
+
+ struct work_struct msg_tx_work;
+
+ struct timer_list cmd_timer;
+ struct hci_msg *cmd_pending_msg;
+
+ struct sk_buff_head rx_hcp_frags;
+
+ struct work_struct msg_rx_work;
+
+ struct sk_buff_head msg_rx_queue;
+
+ const struct nfc_hci_ops *ops;
+
+ struct nfc_llc *llc;
+
+ struct nfc_hci_init_data init_data;
+
+ void *clientdata;
+
+ u8 gate2pipe[NFC_HCI_MAX_GATES];
+ struct nfc_hci_pipe pipes[NFC_HCI_MAX_PIPES];
+
+ u8 sw_romlib;
+ u8 sw_patch;
+ u8 sw_flashlib_major;
+ u8 sw_flashlib_minor;
+
+ u8 hw_derivative;
+ u8 hw_version;
+ u8 hw_mpw;
+ u8 hw_software;
+ u8 hw_bsid;
+
+ int async_cb_type;
+ data_exchange_cb_t async_cb;
+ void *async_cb_context;
+
+ u8 *gb;
+ size_t gb_len;
+
+ unsigned long quirks;
+};
+
+/* hci device allocation */
+struct nfc_hci_dev *nfc_hci_allocate_device(const struct nfc_hci_ops *ops,
+ struct nfc_hci_init_data *init_data,
+ unsigned long quirks,
+ u32 protocols,
+ const char *llc_name,
+ int tx_headroom,
+ int tx_tailroom,
+ int max_link_payload);
+void nfc_hci_free_device(struct nfc_hci_dev *hdev);
+
+int nfc_hci_register_device(struct nfc_hci_dev *hdev);
+void nfc_hci_unregister_device(struct nfc_hci_dev *hdev);
+
+void nfc_hci_set_clientdata(struct nfc_hci_dev *hdev, void *clientdata);
+void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev);
+
+static inline int nfc_hci_set_vendor_cmds(struct nfc_hci_dev *hdev,
+ const struct nfc_vendor_cmd *cmds,
+ int n_cmds)
+{
+ return nfc_set_vendor_cmds(hdev->ndev, cmds, n_cmds);
+}
+
+void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err);
+
+int nfc_hci_result_to_errno(u8 result);
+void nfc_hci_reset_pipes(struct nfc_hci_dev *dev);
+void nfc_hci_reset_pipes_per_host(struct nfc_hci_dev *hdev, u8 host);
+
+/* Host IDs */
+#define NFC_HCI_HOST_CONTROLLER_ID 0x00
+#define NFC_HCI_TERMINAL_HOST_ID 0x01
+#define NFC_HCI_UICC_HOST_ID 0x02
+
+/* Host Controller Gates and registry indexes */
+#define NFC_HCI_ADMIN_GATE 0x00
+#define NFC_HCI_ADMIN_SESSION_IDENTITY 0x01
+#define NFC_HCI_ADMIN_MAX_PIPE 0x02
+#define NFC_HCI_ADMIN_WHITELIST 0x03
+#define NFC_HCI_ADMIN_HOST_LIST 0x04
+
+#define NFC_HCI_LOOPBACK_GATE 0x04
+
+#define NFC_HCI_ID_MGMT_GATE 0x05
+#define NFC_HCI_ID_MGMT_VERSION_SW 0x01
+#define NFC_HCI_ID_MGMT_VERSION_HW 0x03
+#define NFC_HCI_ID_MGMT_VENDOR_NAME 0x04
+#define NFC_HCI_ID_MGMT_MODEL_ID 0x05
+#define NFC_HCI_ID_MGMT_HCI_VERSION 0x02
+#define NFC_HCI_ID_MGMT_GATES_LIST 0x06
+
+#define NFC_HCI_LINK_MGMT_GATE 0x06
+#define NFC_HCI_LINK_MGMT_REC_ERROR 0x01
+
+#define NFC_HCI_RF_READER_B_GATE 0x11
+#define NFC_HCI_RF_READER_B_PUPI 0x03
+#define NFC_HCI_RF_READER_B_APPLICATION_DATA 0x04
+#define NFC_HCI_RF_READER_B_AFI 0x02
+#define NFC_HCI_RF_READER_B_HIGHER_LAYER_RESPONSE 0x01
+#define NFC_HCI_RF_READER_B_HIGHER_LAYER_DATA 0x05
+
+#define NFC_HCI_RF_READER_A_GATE 0x13
+#define NFC_HCI_RF_READER_A_UID 0x02
+#define NFC_HCI_RF_READER_A_ATQA 0x04
+#define NFC_HCI_RF_READER_A_APPLICATION_DATA 0x05
+#define NFC_HCI_RF_READER_A_SAK 0x03
+#define NFC_HCI_RF_READER_A_FWI_SFGT 0x06
+#define NFC_HCI_RF_READER_A_DATARATE_MAX 0x01
+
+#define NFC_HCI_TYPE_A_SEL_PROT(x) (((x) & 0x60) >> 5)
+#define NFC_HCI_TYPE_A_SEL_PROT_MIFARE 0
+#define NFC_HCI_TYPE_A_SEL_PROT_ISO14443 1
+#define NFC_HCI_TYPE_A_SEL_PROT_DEP 2
+#define NFC_HCI_TYPE_A_SEL_PROT_ISO14443_DEP 3
+
+/* Generic events */
+#define NFC_HCI_EVT_HCI_END_OF_OPERATION 0x01
+#define NFC_HCI_EVT_POST_DATA 0x02
+#define NFC_HCI_EVT_HOT_PLUG 0x03
+
+/* Generic commands */
+#define NFC_HCI_ANY_SET_PARAMETER 0x01
+#define NFC_HCI_ANY_GET_PARAMETER 0x02
+#define NFC_HCI_ANY_OPEN_PIPE 0x03
+#define NFC_HCI_ANY_CLOSE_PIPE 0x04
+
+/* Reader RF gates events */
+#define NFC_HCI_EVT_READER_REQUESTED 0x10
+#define NFC_HCI_EVT_END_OPERATION 0x11
+
+/* Reader Application gate events */
+#define NFC_HCI_EVT_TARGET_DISCOVERED 0x10
+
+/* receiving messages from lower layer */
+void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
+ struct sk_buff *skb);
+void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
+ struct sk_buff *skb);
+void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
+ struct sk_buff *skb);
+void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+
+/* connecting to gates and sending hci instructions */
+int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
+ u8 pipe);
+int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate);
+int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev);
+int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
+ struct sk_buff **skb);
+int nfc_hci_set_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
+ const u8 *param, size_t param_len);
+int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
+ const u8 *param, size_t param_len, struct sk_buff **skb);
+int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
+ const u8 *param, size_t param_len,
+ data_exchange_cb_t cb, void *cb_context);
+int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event,
+ const u8 *param, size_t param_len);
+int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate);
+u32 nfc_hci_sak_to_protocol(u8 sak);
+
+#endif /* __NET_HCI_H */
diff --git a/include/net/nfc/llc.h b/include/net/nfc/llc.h
new file mode 100644
index 000000000..1f699cb17
--- /dev/null
+++ b/include/net/nfc/llc.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Link Layer Control manager public interface
+ *
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ */
+
+#ifndef __NFC_LLC_H_
+#define __NFC_LLC_H_
+
+#include <net/nfc/hci.h>
+#include <linux/skbuff.h>
+
+#define LLC_NOP_NAME "nop"
+#define LLC_SHDLC_NAME "shdlc"
+
+typedef void (*rcv_to_hci_t) (struct nfc_hci_dev *hdev, struct sk_buff *skb);
+typedef int (*xmit_to_drv_t) (struct nfc_hci_dev *hdev, struct sk_buff *skb);
+typedef void (*llc_failure_t) (struct nfc_hci_dev *hdev, int err);
+
+struct nfc_llc;
+
+struct nfc_llc *nfc_llc_allocate(const char *name, struct nfc_hci_dev *hdev,
+ xmit_to_drv_t xmit_to_drv,
+ rcv_to_hci_t rcv_to_hci, int tx_headroom,
+ int tx_tailroom, llc_failure_t llc_failure);
+void nfc_llc_free(struct nfc_llc *llc);
+
+int nfc_llc_start(struct nfc_llc *llc);
+int nfc_llc_stop(struct nfc_llc *llc);
+void nfc_llc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb);
+int nfc_llc_xmit_from_hci(struct nfc_llc *llc, struct sk_buff *skb);
+
+int nfc_llc_init(void);
+void nfc_llc_exit(void);
+
+#endif /* __NFC_LLC_H_ */
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
new file mode 100644
index 000000000..09efcaed7
--- /dev/null
+++ b/include/net/nfc/nci.h
@@ -0,0 +1,561 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * The NFC Controller Interface is the communication protocol between an
+ * NFC Controller (NFCC) and a Device Host (DH).
+ *
+ * Copyright (C) 2014 Marvell International Ltd.
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * Written by Ilan Elias <ilane@ti.com>
+ *
+ * Acknowledgements:
+ * This file is based on hci.h, which was written
+ * by Maxim Krasnyansky.
+ */
+
+#ifndef __NCI_H
+#define __NCI_H
+
+#include <net/nfc/nfc.h>
+
+/* NCI constants */
+#define NCI_MAX_NUM_MAPPING_CONFIGS 10
+#define NCI_MAX_NUM_RF_CONFIGS 10
+#define NCI_MAX_NUM_CONN 10
+#define NCI_MAX_PARAM_LEN 251
+#define NCI_MAX_PAYLOAD_SIZE 255
+#define NCI_MAX_PACKET_SIZE 258
+#define NCI_MAX_LARGE_PARAMS_NCI_v2 15
+#define NCI_VER_2_MASK 0x20
+
+/* NCI Status Codes */
+#define NCI_STATUS_OK 0x00
+#define NCI_STATUS_REJECTED 0x01
+#define NCI_STATUS_RF_FRAME_CORRUPTED 0x02
+#define NCI_STATUS_FAILED 0x03
+#define NCI_STATUS_NOT_INITIALIZED 0x04
+#define NCI_STATUS_SYNTAX_ERROR 0x05
+#define NCI_STATUS_SEMANTIC_ERROR 0x06
+#define NCI_STATUS_UNKNOWN_GID 0x07
+#define NCI_STATUS_UNKNOWN_OID 0x08
+#define NCI_STATUS_INVALID_PARAM 0x09
+#define NCI_STATUS_MESSAGE_SIZE_EXCEEDED 0x0a
+/* Discovery Specific Status Codes */
+#define NCI_STATUS_DISCOVERY_ALREADY_STARTED 0xa0
+#define NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED 0xa1
+#define NCI_STATUS_DISCOVERY_TEAR_DOWN 0xa2
+/* RF Interface Specific Status Codes */
+#define NCI_STATUS_RF_TRANSMISSION_ERROR 0xb0
+#define NCI_STATUS_RF_PROTOCOL_ERROR 0xb1
+#define NCI_STATUS_RF_TIMEOUT_ERROR 0xb2
+/* NFCEE Interface Specific Status Codes */
+#define NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED 0xc0
+#define NCI_STATUS_NFCEE_TRANSMISSION_ERROR 0xc1
+#define NCI_STATUS_NFCEE_PROTOCOL_ERROR 0xc2
+#define NCI_STATUS_NFCEE_TIMEOUT_ERROR 0xc3
+
+/* NFCEE Interface/Protocols */
+#define NCI_NFCEE_INTERFACE_APDU 0x00
+#define NCI_NFCEE_INTERFACE_HCI_ACCESS 0x01
+#define NCI_NFCEE_INTERFACE_TYPE3_CMD_SET 0x02
+#define NCI_NFCEE_INTERFACE_TRANSPARENT 0x03
+
+/* Destination type */
+#define NCI_DESTINATION_NFCC_LOOPBACK 0x01
+#define NCI_DESTINATION_REMOTE_NFC_ENDPOINT 0x02
+#define NCI_DESTINATION_NFCEE 0x03
+
+/* Destination-specific parameters type */
+#define NCI_DESTINATION_SPECIFIC_PARAM_RF_TYPE 0x00
+#define NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE 0x01
+
+/* NFCEE Discovery Action */
+#define NCI_NFCEE_DISCOVERY_ACTION_DISABLE 0x00
+#define NCI_NFCEE_DISCOVERY_ACTION_ENABLE 0x01
+
+/* NCI RF Technology and Mode */
+#define NCI_NFC_A_PASSIVE_POLL_MODE 0x00
+#define NCI_NFC_B_PASSIVE_POLL_MODE 0x01
+#define NCI_NFC_F_PASSIVE_POLL_MODE 0x02
+#define NCI_NFC_A_ACTIVE_POLL_MODE 0x03
+#define NCI_NFC_F_ACTIVE_POLL_MODE 0x05
+#define NCI_NFC_V_PASSIVE_POLL_MODE 0x06
+#define NCI_NFC_A_PASSIVE_LISTEN_MODE 0x80
+#define NCI_NFC_B_PASSIVE_LISTEN_MODE 0x81
+#define NCI_NFC_F_PASSIVE_LISTEN_MODE 0x82
+#define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83
+#define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85
+
+#define NCI_RF_TECH_MODE_LISTEN_MASK 0x80
+
+/* NCI RF Technologies */
+#define NCI_NFC_RF_TECHNOLOGY_A 0x00
+#define NCI_NFC_RF_TECHNOLOGY_B 0x01
+#define NCI_NFC_RF_TECHNOLOGY_F 0x02
+#define NCI_NFC_RF_TECHNOLOGY_V 0x03
+
+/* NCI Bit Rates */
+#define NCI_NFC_BIT_RATE_106 0x00
+#define NCI_NFC_BIT_RATE_212 0x01
+#define NCI_NFC_BIT_RATE_424 0x02
+#define NCI_NFC_BIT_RATE_848 0x03
+#define NCI_NFC_BIT_RATE_1695 0x04
+#define NCI_NFC_BIT_RATE_3390 0x05
+#define NCI_NFC_BIT_RATE_6780 0x06
+#define NCI_NFC_BIT_RATE_26 0x20
+
+/* NCI RF Protocols */
+#define NCI_RF_PROTOCOL_UNKNOWN 0x00
+#define NCI_RF_PROTOCOL_T1T 0x01
+#define NCI_RF_PROTOCOL_T2T 0x02
+#define NCI_RF_PROTOCOL_T3T 0x03
+#define NCI_RF_PROTOCOL_ISO_DEP 0x04
+#define NCI_RF_PROTOCOL_NFC_DEP 0x05
+#define NCI_RF_PROTOCOL_T5T 0x06
+
+/* NCI RF Interfaces */
+#define NCI_RF_INTERFACE_NFCEE_DIRECT 0x00
+#define NCI_RF_INTERFACE_FRAME 0x01
+#define NCI_RF_INTERFACE_ISO_DEP 0x02
+#define NCI_RF_INTERFACE_NFC_DEP 0x03
+
+/* NCI Configuration Parameter Tags */
+#define NCI_PN_ATR_REQ_GEN_BYTES 0x29
+#define NCI_LN_ATR_RES_GEN_BYTES 0x61
+#define NCI_LA_SEL_INFO 0x32
+#define NCI_LF_PROTOCOL_TYPE 0x50
+#define NCI_LF_CON_BITR_F 0x54
+
+/* NCI Configuration Parameters masks */
+#define NCI_LA_SEL_INFO_ISO_DEP_MASK 0x20
+#define NCI_LA_SEL_INFO_NFC_DEP_MASK 0x40
+#define NCI_LF_PROTOCOL_TYPE_NFC_DEP_MASK 0x02
+#define NCI_LF_CON_BITR_F_212 0x02
+#define NCI_LF_CON_BITR_F_424 0x04
+
+/* NCI 2.x Feature Enable Bit */
+#define NCI_FEATURE_DISABLE 0x00
+
+/* NCI Reset types */
+#define NCI_RESET_TYPE_KEEP_CONFIG 0x00
+#define NCI_RESET_TYPE_RESET_CONFIG 0x01
+
+/* NCI Static RF connection ID */
+#define NCI_STATIC_RF_CONN_ID 0x00
+
+/* NCI Data Flow Control */
+#define NCI_DATA_FLOW_CONTROL_NOT_USED 0xff
+
+/* NCI RF_DISCOVER_MAP_CMD modes */
+#define NCI_DISC_MAP_MODE_POLL 0x01
+#define NCI_DISC_MAP_MODE_LISTEN 0x02
+
+/* NCI Discover Notification Type */
+#define NCI_DISCOVER_NTF_TYPE_LAST 0x00
+#define NCI_DISCOVER_NTF_TYPE_LAST_NFCC 0x01
+#define NCI_DISCOVER_NTF_TYPE_MORE 0x02
+
+/* NCI Deactivation Type */
+#define NCI_DEACTIVATE_TYPE_IDLE_MODE 0x00
+#define NCI_DEACTIVATE_TYPE_SLEEP_MODE 0x01
+#define NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE 0x02
+#define NCI_DEACTIVATE_TYPE_DISCOVERY 0x03
+
+/* Message Type (MT) */
+#define NCI_MT_DATA_PKT 0x00
+#define NCI_MT_CMD_PKT 0x01
+#define NCI_MT_RSP_PKT 0x02
+#define NCI_MT_NTF_PKT 0x03
+
+#define nci_mt(hdr) (((hdr)[0]>>5)&0x07)
+#define nci_mt_set(hdr, mt) ((hdr)[0] |= (__u8)(((mt)&0x07)<<5))
+
+/* Packet Boundary Flag (PBF) */
+#define NCI_PBF_LAST 0x00
+#define NCI_PBF_CONT 0x01
+
+#define nci_pbf(hdr) (__u8)(((hdr)[0]>>4)&0x01)
+#define nci_pbf_set(hdr, pbf) ((hdr)[0] |= (__u8)(((pbf)&0x01)<<4))
+
+/* Control Opcode manipulation */
+#define nci_opcode_pack(gid, oid) (__u16)((((__u16)((gid)&0x0f))<<8)|\
+ ((__u16)((oid)&0x3f)))
+#define nci_opcode(hdr) nci_opcode_pack(hdr[0], hdr[1])
+#define nci_opcode_gid(op) (__u8)(((op)&0x0f00)>>8)
+#define nci_opcode_oid(op) (__u8)((op)&0x003f)
+
+/* Payload Length */
+#define nci_plen(hdr) (__u8)((hdr)[2])
+
+/* Connection ID */
+#define nci_conn_id(hdr) (__u8)(((hdr)[0])&0x0f)
+
+/* GID values */
+#define NCI_GID_CORE 0x0
+#define NCI_GID_RF_MGMT 0x1
+#define NCI_GID_NFCEE_MGMT 0x2
+#define NCI_GID_PROPRIETARY 0xf
+
+/* ----- NCI over SPI head/crc(tail) room needed for outgoing frames ----- */
+#define NCI_SPI_HDR_LEN 4
+#define NCI_SPI_CRC_LEN 2
+
+/* ---- NCI Packet structures ---- */
+#define NCI_CTRL_HDR_SIZE 3
+#define NCI_DATA_HDR_SIZE 3
+
+struct nci_ctrl_hdr {
+ __u8 gid; /* MT & PBF & GID */
+ __u8 oid;
+ __u8 plen;
+} __packed;
+
+struct nci_data_hdr {
+ __u8 conn_id; /* MT & PBF & ConnID */
+ __u8 rfu;
+ __u8 plen;
+} __packed;
+
+/* ------------------------ */
+/* ----- NCI Commands ---- */
+/* ------------------------ */
+#define NCI_OP_CORE_RESET_CMD nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_cmd {
+ __u8 reset_type;
+} __packed;
+
+#define NCI_OP_CORE_INIT_CMD nci_opcode_pack(NCI_GID_CORE, 0x01)
+/* To support NCI 2.x */
+struct nci_core_init_v2_cmd {
+ u8 feature1;
+ u8 feature2;
+};
+
+#define NCI_OP_CORE_SET_CONFIG_CMD nci_opcode_pack(NCI_GID_CORE, 0x02)
+struct set_config_param {
+ __u8 id;
+ __u8 len;
+ __u8 val[NCI_MAX_PARAM_LEN];
+} __packed;
+
+struct nci_core_set_config_cmd {
+ __u8 num_params;
+ struct set_config_param param; /* support 1 param per cmd is enough */
+} __packed;
+
+#define NCI_OP_CORE_CONN_CREATE_CMD nci_opcode_pack(NCI_GID_CORE, 0x04)
+#define DEST_SPEC_PARAMS_ID_INDEX 0
+#define DEST_SPEC_PARAMS_PROTOCOL_INDEX 1
+struct dest_spec_params {
+ __u8 id;
+ __u8 protocol;
+} __packed;
+
+struct core_conn_create_dest_spec_params {
+ __u8 type;
+ __u8 length;
+ __u8 value[];
+} __packed;
+
+struct nci_core_conn_create_cmd {
+ __u8 destination_type;
+ __u8 number_destination_params;
+ struct core_conn_create_dest_spec_params params[];
+} __packed;
+
+#define NCI_OP_CORE_CONN_CLOSE_CMD nci_opcode_pack(NCI_GID_CORE, 0x05)
+
+#define NCI_OP_RF_DISCOVER_MAP_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
+struct disc_map_config {
+ __u8 rf_protocol;
+ __u8 mode;
+ __u8 rf_interface;
+} __packed;
+
+struct nci_rf_disc_map_cmd {
+ __u8 num_mapping_configs;
+ struct disc_map_config mapping_configs
+ [NCI_MAX_NUM_MAPPING_CONFIGS];
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+struct disc_config {
+ __u8 rf_tech_and_mode;
+ __u8 frequency;
+} __packed;
+
+struct nci_rf_disc_cmd {
+ __u8 num_disc_configs;
+ struct disc_config disc_configs[NCI_MAX_NUM_RF_CONFIGS];
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_SELECT_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x04)
+struct nci_rf_discover_select_cmd {
+ __u8 rf_discovery_id;
+ __u8 rf_protocol;
+ __u8 rf_interface;
+} __packed;
+
+#define NCI_OP_RF_DEACTIVATE_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+struct nci_rf_deactivate_cmd {
+ __u8 type;
+} __packed;
+
+#define NCI_OP_NFCEE_DISCOVER_CMD nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x00)
+struct nci_nfcee_discover_cmd {
+ __u8 discovery_action;
+} __packed;
+
+#define NCI_OP_NFCEE_MODE_SET_CMD nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x01)
+#define NCI_NFCEE_DISABLE 0x00
+#define NCI_NFCEE_ENABLE 0x01
+struct nci_nfcee_mode_set_cmd {
+ __u8 nfcee_id;
+ __u8 nfcee_mode;
+} __packed;
+
+#define NCI_OP_CORE_GET_CONFIG_CMD nci_opcode_pack(NCI_GID_CORE, 0x03)
+
+/* ----------------------- */
+/* ---- NCI Responses ---- */
+/* ----------------------- */
+#define NCI_OP_CORE_RESET_RSP nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_rsp {
+ __u8 status;
+ __u8 nci_ver;
+ __u8 config_status;
+} __packed;
+
+#define NCI_OP_CORE_INIT_RSP nci_opcode_pack(NCI_GID_CORE, 0x01)
+struct nci_core_init_rsp_1 {
+ __u8 status;
+ __le32 nfcc_features;
+ __u8 num_supported_rf_interfaces;
+ __u8 supported_rf_interfaces[]; /* variable size array */
+ /* continued in nci_core_init_rsp_2 */
+} __packed;
+
+struct nci_core_init_rsp_2 {
+ __u8 max_logical_connections;
+ __le16 max_routing_table_size;
+ __u8 max_ctrl_pkt_payload_len;
+ __le16 max_size_for_large_params;
+ __u8 manufact_id;
+ __le32 manufact_specific_info;
+} __packed;
+
+/* To support NCI ver 2.x */
+struct nci_core_init_rsp_nci_ver2 {
+ u8 status;
+ __le32 nfcc_features;
+ u8 max_logical_connections;
+ __le16 max_routing_table_size;
+ u8 max_ctrl_pkt_payload_len;
+ u8 max_data_pkt_hci_payload_len;
+ u8 number_of_hci_credit;
+ __le16 max_nfc_v_frame_size;
+ u8 num_supported_rf_interfaces;
+ u8 supported_rf_interfaces[];
+} __packed;
+
+#define NCI_OP_CORE_SET_CONFIG_RSP nci_opcode_pack(NCI_GID_CORE, 0x02)
+struct nci_core_set_config_rsp {
+ __u8 status;
+ __u8 num_params;
+ __u8 params_id[]; /* variable size array */
+} __packed;
+
+#define NCI_OP_CORE_CONN_CREATE_RSP nci_opcode_pack(NCI_GID_CORE, 0x04)
+struct nci_core_conn_create_rsp {
+ __u8 status;
+ __u8 max_ctrl_pkt_payload_len;
+ __u8 credits_cnt;
+ __u8 conn_id;
+} __packed;
+
+#define NCI_OP_CORE_CONN_CLOSE_RSP nci_opcode_pack(NCI_GID_CORE, 0x05)
+
+#define NCI_OP_RF_DISCOVER_MAP_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
+
+#define NCI_OP_RF_DISCOVER_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+
+#define NCI_OP_RF_DISCOVER_SELECT_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x04)
+
+#define NCI_OP_RF_DEACTIVATE_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+
+#define NCI_OP_NFCEE_DISCOVER_RSP nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x00)
+struct nci_nfcee_discover_rsp {
+ __u8 status;
+ __u8 num_nfcee;
+} __packed;
+
+#define NCI_OP_NFCEE_MODE_SET_RSP nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x01)
+
+#define NCI_OP_CORE_GET_CONFIG_RSP nci_opcode_pack(NCI_GID_CORE, 0x03)
+
+/* --------------------------- */
+/* ---- NCI Notifications ---- */
+/* --------------------------- */
+#define NCI_OP_CORE_RESET_NTF nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_ntf {
+ u8 reset_trigger;
+ u8 config_status;
+ u8 nci_ver;
+ u8 manufact_id;
+ u8 manufacturer_specific_len;
+ __le32 manufact_specific_info;
+} __packed;
+
+#define NCI_OP_CORE_CONN_CREDITS_NTF nci_opcode_pack(NCI_GID_CORE, 0x06)
+struct conn_credit_entry {
+ __u8 conn_id;
+ __u8 credits;
+} __packed;
+
+struct nci_core_conn_credit_ntf {
+ __u8 num_entries;
+ struct conn_credit_entry conn_entries[NCI_MAX_NUM_CONN];
+} __packed;
+
+#define NCI_OP_CORE_GENERIC_ERROR_NTF nci_opcode_pack(NCI_GID_CORE, 0x07)
+
+#define NCI_OP_CORE_INTF_ERROR_NTF nci_opcode_pack(NCI_GID_CORE, 0x08)
+struct nci_core_intf_error_ntf {
+ __u8 status;
+ __u8 conn_id;
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+struct rf_tech_specific_params_nfca_poll {
+ __u16 sens_res;
+ __u8 nfcid1_len; /* 0, 4, 7, or 10 Bytes */
+ __u8 nfcid1[NFC_NFCID1_MAXSIZE];
+ __u8 sel_res_len; /* 0 or 1 Bytes */
+ __u8 sel_res;
+} __packed;
+
+struct rf_tech_specific_params_nfcb_poll {
+ __u8 sensb_res_len;
+ __u8 sensb_res[NFC_SENSB_RES_MAXSIZE]; /* 11 or 12 Bytes */
+} __packed;
+
+struct rf_tech_specific_params_nfcf_poll {
+ __u8 bit_rate;
+ __u8 sensf_res_len;
+ __u8 sensf_res[NFC_SENSF_RES_MAXSIZE]; /* 16 or 18 Bytes */
+} __packed;
+
+struct rf_tech_specific_params_nfcv_poll {
+ __u8 res_flags;
+ __u8 dsfid;
+ __u8 uid[NFC_ISO15693_UID_MAXSIZE]; /* 8 Bytes */
+} __packed;
+
+struct rf_tech_specific_params_nfcf_listen {
+ __u8 local_nfcid2_len;
+ __u8 local_nfcid2[NFC_NFCID2_MAXSIZE]; /* 0 or 8 Bytes */
+} __packed;
+
+struct nci_rf_discover_ntf {
+ __u8 rf_discovery_id;
+ __u8 rf_protocol;
+ __u8 rf_tech_and_mode;
+ __u8 rf_tech_specific_params_len;
+
+ union {
+ struct rf_tech_specific_params_nfca_poll nfca_poll;
+ struct rf_tech_specific_params_nfcb_poll nfcb_poll;
+ struct rf_tech_specific_params_nfcf_poll nfcf_poll;
+ struct rf_tech_specific_params_nfcv_poll nfcv_poll;
+ } rf_tech_specific_params;
+
+ __u8 ntf_type;
+} __packed;
+
+#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[NFC_ATS_MAXSIZE];
+};
+
+struct activation_params_nfcb_poll_iso_dep {
+ __u8 attrib_res_len;
+ __u8 attrib_res[50];
+};
+
+struct activation_params_poll_nfc_dep {
+ __u8 atr_res_len;
+ __u8 atr_res[NFC_ATR_RES_MAXSIZE - 2]; /* ATR_RES from byte 3 */
+};
+
+struct activation_params_listen_nfc_dep {
+ __u8 atr_req_len;
+ __u8 atr_req[NFC_ATR_REQ_MAXSIZE - 2]; /* ATR_REQ from byte 3 */
+};
+
+struct nci_rf_intf_activated_ntf {
+ __u8 rf_discovery_id;
+ __u8 rf_interface;
+ __u8 rf_protocol;
+ __u8 activation_rf_tech_and_mode;
+ __u8 max_data_pkt_payload_size;
+ __u8 initial_num_credits;
+ __u8 rf_tech_specific_params_len;
+
+ union {
+ struct rf_tech_specific_params_nfca_poll nfca_poll;
+ struct rf_tech_specific_params_nfcb_poll nfcb_poll;
+ struct rf_tech_specific_params_nfcf_poll nfcf_poll;
+ struct rf_tech_specific_params_nfcv_poll nfcv_poll;
+ struct rf_tech_specific_params_nfcf_listen nfcf_listen;
+ } rf_tech_specific_params;
+
+ __u8 data_exch_rf_tech_and_mode;
+ __u8 data_exch_tx_bit_rate;
+ __u8 data_exch_rx_bit_rate;
+ __u8 activation_params_len;
+
+ union {
+ struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep;
+ struct activation_params_nfcb_poll_iso_dep nfcb_poll_iso_dep;
+ struct activation_params_poll_nfc_dep poll_nfc_dep;
+ struct activation_params_listen_nfc_dep listen_nfc_dep;
+ } activation_params;
+
+} __packed;
+
+#define NCI_OP_RF_DEACTIVATE_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+struct nci_rf_deactivate_ntf {
+ __u8 type;
+ __u8 reason;
+} __packed;
+
+#define NCI_OP_RF_NFCEE_ACTION_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x09)
+struct nci_rf_nfcee_action_ntf {
+ __u8 nfcee_id;
+ __u8 trigger;
+ __u8 supported_data_length;
+ __u8 supported_data[];
+} __packed;
+
+#define NCI_OP_NFCEE_DISCOVER_NTF nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x00)
+struct nci_nfcee_supported_protocol {
+ __u8 num_protocol;
+ __u8 supported_protocol[];
+} __packed;
+
+struct nci_nfcee_information_tlv {
+ __u8 num_tlv;
+ __u8 information_tlv[];
+} __packed;
+
+struct nci_nfcee_discover_ntf {
+ __u8 nfcee_id;
+ __u8 nfcee_status;
+ struct nci_nfcee_supported_protocol supported_protocols;
+ struct nci_nfcee_information_tlv information_tlv;
+} __packed;
+
+#define NCI_OP_CORE_RESET_NTF nci_opcode_pack(NCI_GID_CORE, 0x00)
+
+#endif /* __NCI_H */
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
new file mode 100644
index 000000000..664d5058e
--- /dev/null
+++ b/include/net/nfc/nci_core.h
@@ -0,0 +1,469 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * The NFC Controller Interface is the communication protocol between an
+ * NFC Controller (NFCC) and a Device Host (DH).
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ * Copyright (C) 2014 Marvell International Ltd.
+ *
+ * Written by Ilan Elias <ilane@ti.com>
+ *
+ * Acknowledgements:
+ * This file is based on hci_core.h, which was written
+ * by Maxim Krasnyansky.
+ */
+
+#ifndef __NCI_CORE_H
+#define __NCI_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/tty.h>
+
+#include <net/nfc/nfc.h>
+#include <net/nfc/nci.h>
+
+/* NCI device flags */
+enum nci_flag {
+ NCI_INIT,
+ NCI_UP,
+ NCI_DATA_EXCHANGE,
+ NCI_DATA_EXCHANGE_TO,
+ NCI_UNREG,
+};
+
+/* NCI device states */
+enum nci_state {
+ NCI_IDLE,
+ NCI_DISCOVERY,
+ NCI_W4_ALL_DISCOVERIES,
+ NCI_W4_HOST_SELECT,
+ NCI_POLL_ACTIVE,
+ NCI_LISTEN_ACTIVE,
+ NCI_LISTEN_SLEEP,
+};
+
+/* NCI timeouts */
+#define NCI_RESET_TIMEOUT 5000
+#define NCI_INIT_TIMEOUT 5000
+#define NCI_SET_CONFIG_TIMEOUT 5000
+#define NCI_RF_DISC_TIMEOUT 5000
+#define NCI_RF_DISC_SELECT_TIMEOUT 5000
+#define NCI_RF_DEACTIVATE_TIMEOUT 30000
+#define NCI_CMD_TIMEOUT 5000
+#define NCI_DATA_TIMEOUT 3000
+
+struct nci_dev;
+
+struct nci_driver_ops {
+ __u16 opcode;
+ int (*rsp)(struct nci_dev *dev, struct sk_buff *skb);
+ int (*ntf)(struct nci_dev *dev, struct sk_buff *skb);
+};
+
+struct nci_ops {
+ int (*init)(struct nci_dev *ndev);
+ int (*open)(struct nci_dev *ndev);
+ int (*close)(struct nci_dev *ndev);
+ int (*send)(struct nci_dev *ndev, struct sk_buff *skb);
+ int (*setup)(struct nci_dev *ndev);
+ int (*post_setup)(struct nci_dev *ndev);
+ int (*fw_download)(struct nci_dev *ndev, const char *firmware_name);
+ __u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol);
+ int (*discover_se)(struct nci_dev *ndev);
+ int (*disable_se)(struct nci_dev *ndev, u32 se_idx);
+ int (*enable_se)(struct nci_dev *ndev, u32 se_idx);
+ int (*se_io)(struct nci_dev *ndev, u32 se_idx,
+ u8 *apdu, size_t apdu_length,
+ se_io_cb_t cb, void *cb_context);
+ int (*hci_load_session)(struct nci_dev *ndev);
+ void (*hci_event_received)(struct nci_dev *ndev, u8 pipe, u8 event,
+ struct sk_buff *skb);
+ void (*hci_cmd_received)(struct nci_dev *ndev, u8 pipe, u8 cmd,
+ struct sk_buff *skb);
+
+ const struct nci_driver_ops *prop_ops;
+ size_t n_prop_ops;
+
+ const struct nci_driver_ops *core_ops;
+ size_t n_core_ops;
+};
+
+#define NCI_MAX_SUPPORTED_RF_INTERFACES 4
+#define NCI_MAX_DISCOVERED_TARGETS 10
+#define NCI_MAX_NUM_NFCEE 255
+#define NCI_MAX_CONN_ID 7
+#define NCI_MAX_PROPRIETARY_CMD 64
+
+struct nci_conn_info {
+ struct list_head list;
+ /* NCI specification 4.4.2 Connection Creation
+ * The combination of destination type and destination specific
+ * parameters shall uniquely identify a single destination for the
+ * Logical Connection
+ */
+ struct dest_spec_params *dest_params;
+ __u8 dest_type;
+ __u8 conn_id;
+ __u8 max_pkt_payload_len;
+
+ atomic_t credits_cnt;
+ __u8 initial_num_credits;
+
+ data_exchange_cb_t data_exchange_cb;
+ void *data_exchange_cb_context;
+
+ struct sk_buff *rx_skb;
+};
+
+#define NCI_INVALID_CONN_ID 0x80
+
+#define NCI_HCI_ANY_OPEN_PIPE 0x03
+
+/* Gates */
+#define NCI_HCI_ADMIN_GATE 0x00
+#define NCI_HCI_LOOPBACK_GATE 0x04
+#define NCI_HCI_IDENTITY_MGMT_GATE 0x05
+#define NCI_HCI_LINK_MGMT_GATE 0x06
+
+/* Pipes */
+#define NCI_HCI_LINK_MGMT_PIPE 0x00
+#define NCI_HCI_ADMIN_PIPE 0x01
+
+/* Generic responses */
+#define NCI_HCI_ANY_OK 0x00
+#define NCI_HCI_ANY_E_NOT_CONNECTED 0x01
+#define NCI_HCI_ANY_E_CMD_PAR_UNKNOWN 0x02
+#define NCI_HCI_ANY_E_NOK 0x03
+#define NCI_HCI_ANY_E_PIPES_FULL 0x04
+#define NCI_HCI_ANY_E_REG_PAR_UNKNOWN 0x05
+#define NCI_HCI_ANY_E_PIPE_NOT_OPENED 0x06
+#define NCI_HCI_ANY_E_CMD_NOT_SUPPORTED 0x07
+#define NCI_HCI_ANY_E_INHIBITED 0x08
+#define NCI_HCI_ANY_E_TIMEOUT 0x09
+#define NCI_HCI_ANY_E_REG_ACCESS_DENIED 0x0a
+#define NCI_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b
+
+#define NCI_HCI_DO_NOT_OPEN_PIPE 0x81
+#define NCI_HCI_INVALID_PIPE 0x80
+#define NCI_HCI_INVALID_GATE 0xFF
+#define NCI_HCI_INVALID_HOST 0x80
+
+#define NCI_HCI_MAX_CUSTOM_GATES 50
+/*
+ * According to specification 102 622 chapter 4.4 Pipes,
+ * the pipe identifier is 7 bits long.
+ */
+#define NCI_HCI_MAX_PIPES 128
+
+struct nci_hci_gate {
+ u8 gate;
+ u8 pipe;
+ u8 dest_host;
+} __packed;
+
+struct nci_hci_pipe {
+ u8 gate;
+ u8 host;
+} __packed;
+
+struct nci_hci_init_data {
+ u8 gate_count;
+ struct nci_hci_gate gates[NCI_HCI_MAX_CUSTOM_GATES];
+ char session_id[9];
+};
+
+#define NCI_HCI_MAX_GATES 256
+
+struct nci_hci_dev {
+ u8 nfcee_id;
+ struct nci_dev *ndev;
+ struct nci_conn_info *conn_info;
+
+ struct nci_hci_init_data init_data;
+ struct nci_hci_pipe pipes[NCI_HCI_MAX_PIPES];
+ u8 gate2pipe[NCI_HCI_MAX_GATES];
+ int expected_pipes;
+ int count_pipes;
+
+ struct sk_buff_head rx_hcp_frags;
+ struct work_struct msg_rx_work;
+ struct sk_buff_head msg_rx_queue;
+};
+
+/* NCI Core structures */
+struct nci_dev {
+ struct nfc_dev *nfc_dev;
+ const struct nci_ops *ops;
+ struct nci_hci_dev *hci_dev;
+
+ int tx_headroom;
+ int tx_tailroom;
+
+ atomic_t state;
+ unsigned long flags;
+
+ atomic_t cmd_cnt;
+ __u8 cur_conn_id;
+
+ struct list_head conn_info_list;
+ struct nci_conn_info *rf_conn_info;
+
+ struct timer_list cmd_timer;
+ struct timer_list data_timer;
+
+ struct workqueue_struct *cmd_wq;
+ struct work_struct cmd_work;
+
+ struct workqueue_struct *rx_wq;
+ struct work_struct rx_work;
+
+ struct workqueue_struct *tx_wq;
+ struct work_struct tx_work;
+
+ struct sk_buff_head cmd_q;
+ struct sk_buff_head rx_q;
+ struct sk_buff_head tx_q;
+
+ struct mutex req_lock;
+ struct completion req_completion;
+ __u32 req_status;
+ __u32 req_result;
+
+ void *driver_data;
+
+ __u32 poll_prots;
+ __u32 target_active_prot;
+
+ struct nfc_target targets[NCI_MAX_DISCOVERED_TARGETS];
+ int n_targets;
+
+ /* received during NCI_OP_CORE_RESET_RSP */
+ __u8 nci_ver;
+
+ /* received during NCI_OP_CORE_INIT_RSP */
+ __u32 nfcc_features;
+ __u8 num_supported_rf_interfaces;
+ __u8 supported_rf_interfaces
+ [NCI_MAX_SUPPORTED_RF_INTERFACES];
+ __u8 max_logical_connections;
+ __u16 max_routing_table_size;
+ __u8 max_ctrl_pkt_payload_len;
+ __u16 max_size_for_large_params;
+ __u8 manufact_id;
+ __u32 manufact_specific_info;
+
+ /* Save RF Discovery ID or NFCEE ID under conn_create */
+ struct dest_spec_params cur_params;
+ /* Save destination type under conn_create */
+ __u8 cur_dest_type;
+
+ /* stored during nci_data_exchange */
+ struct sk_buff *rx_data_reassembly;
+
+ /* 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 ----- */
+struct nci_dev *nci_allocate_device(const struct nci_ops *ops,
+ __u32 supported_protocols,
+ int tx_headroom,
+ int tx_tailroom);
+void nci_free_device(struct nci_dev *ndev);
+int nci_register_device(struct nci_dev *ndev);
+void nci_unregister_device(struct nci_dev *ndev);
+int nci_request(struct nci_dev *ndev,
+ void (*req)(struct nci_dev *ndev,
+ const void *opt),
+ const void *opt, __u32 timeout);
+int nci_prop_cmd(struct nci_dev *ndev, __u8 oid, size_t len,
+ const __u8 *payload);
+int nci_core_cmd(struct nci_dev *ndev, __u16 opcode, size_t len,
+ const __u8 *payload);
+int nci_core_reset(struct nci_dev *ndev);
+int nci_core_init(struct nci_dev *ndev);
+
+int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb);
+int nci_send_frame(struct nci_dev *ndev, struct sk_buff *skb);
+int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, const __u8 *val);
+
+int nci_nfcee_discover(struct nci_dev *ndev, u8 action);
+int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode);
+int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type,
+ u8 number_destination_params,
+ size_t params_len,
+ const struct core_conn_create_dest_spec_params *params);
+int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id);
+int nci_nfcc_loopback(struct nci_dev *ndev, const void *data, size_t data_len,
+ struct sk_buff **resp);
+
+struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev);
+void nci_hci_deallocate(struct nci_dev *ndev);
+int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
+ const u8 *param, size_t param_len);
+int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate,
+ u8 cmd, const u8 *param, size_t param_len,
+ struct sk_buff **skb);
+int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe);
+int nci_hci_connect_gate(struct nci_dev *ndev, u8 dest_host,
+ u8 dest_gate, u8 pipe);
+int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
+ const u8 *param, size_t param_len);
+int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
+ struct sk_buff **skb);
+int nci_hci_clear_all_pipes(struct nci_dev *ndev);
+int nci_hci_dev_session_init(struct nci_dev *ndev);
+
+static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
+ unsigned int len,
+ gfp_t how)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(len + ndev->tx_headroom + ndev->tx_tailroom, how);
+ if (skb)
+ skb_reserve(skb, ndev->tx_headroom);
+
+ return skb;
+}
+
+static inline void nci_set_parent_dev(struct nci_dev *ndev, struct device *dev)
+{
+ nfc_set_parent_dev(ndev->nfc_dev, dev);
+}
+
+static inline void nci_set_drvdata(struct nci_dev *ndev, void *data)
+{
+ ndev->driver_data = data;
+}
+
+static inline void *nci_get_drvdata(struct nci_dev *ndev)
+{
+ return ndev->driver_data;
+}
+
+static inline int nci_set_vendor_cmds(struct nci_dev *ndev,
+ const struct nfc_vendor_cmd *cmds,
+ int n_cmds)
+{
+ return nfc_set_vendor_cmds(ndev->nfc_dev, cmds, n_cmds);
+}
+
+void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb);
+void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb);
+int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode,
+ struct sk_buff *skb);
+int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode,
+ struct sk_buff *skb);
+int nci_core_rsp_packet(struct nci_dev *ndev, __u16 opcode,
+ struct sk_buff *skb);
+int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode,
+ struct sk_buff *skb);
+void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb);
+int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, const void *payload);
+int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb);
+int nci_conn_max_data_pkt_payload_size(struct nci_dev *ndev, __u8 conn_id);
+void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
+ __u8 conn_id, int err);
+void nci_hci_data_received_cb(void *context, struct sk_buff *skb, int err);
+
+void nci_clear_target_list(struct nci_dev *ndev);
+
+/* ----- NCI requests ----- */
+#define NCI_REQ_DONE 0
+#define NCI_REQ_PEND 1
+#define NCI_REQ_CANCELED 2
+
+void nci_req_complete(struct nci_dev *ndev, int result);
+struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
+ int conn_id);
+int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type,
+ const struct dest_spec_params *params);
+
+/* ----- NCI status code ----- */
+int nci_to_errno(__u8 code);
+
+/* ----- NCI over SPI acknowledge modes ----- */
+#define NCI_SPI_CRC_DISABLED 0x00
+#define NCI_SPI_CRC_ENABLED 0x01
+
+/* ----- NCI SPI structures ----- */
+struct nci_spi {
+ struct nci_dev *ndev;
+ struct spi_device *spi;
+
+ unsigned int xfer_udelay; /* microseconds delay between
+ transactions */
+
+ unsigned int xfer_speed_hz; /*
+ * SPI clock frequency
+ * 0 => default clock
+ */
+
+ u8 acknowledge_mode;
+
+ struct completion req_completion;
+ u8 req_result;
+};
+
+/* ----- NCI SPI ----- */
+struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi,
+ u8 acknowledge_mode, unsigned int delay,
+ struct nci_dev *ndev);
+int nci_spi_send(struct nci_spi *nspi,
+ struct completion *write_handshake_completion,
+ struct sk_buff *skb);
+struct sk_buff *nci_spi_read(struct nci_spi *nspi);
+
+/* ----- NCI UART ---- */
+
+/* Ioctl */
+#define NCIUARTSETDRIVER _IOW('U', 0, char *)
+
+enum nci_uart_driver {
+ NCI_UART_DRIVER_MARVELL = 0,
+ NCI_UART_DRIVER_MAX
+};
+
+struct nci_uart;
+
+struct nci_uart_ops {
+ int (*open)(struct nci_uart *nci_uart);
+ void (*close)(struct nci_uart *nci_uart);
+ int (*recv)(struct nci_uart *nci_uart, struct sk_buff *skb);
+ int (*send)(struct nci_uart *nci_uart, struct sk_buff *skb);
+ void (*tx_start)(struct nci_uart *nci_uart);
+ void (*tx_done)(struct nci_uart *nci_uart);
+};
+
+struct nci_uart {
+ struct module *owner;
+ struct nci_uart_ops ops;
+ const char *name;
+ enum nci_uart_driver driver;
+
+ /* Dynamic data */
+ struct nci_dev *ndev;
+ spinlock_t rx_lock;
+ struct work_struct write_work;
+ struct tty_struct *tty;
+ unsigned long tx_state;
+ struct sk_buff_head tx_q;
+ struct sk_buff *tx_skb;
+ struct sk_buff *rx_skb;
+ int rx_packet_len;
+ void *drv_data;
+};
+
+int nci_uart_register(struct nci_uart *nu);
+void nci_uart_unregister(struct nci_uart *nu);
+void nci_uart_set_config(struct nci_uart *nu, int baudrate, int flow_ctrl);
+
+#endif /* __NCI_CORE_H */
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
new file mode 100644
index 000000000..c54df042d
--- /dev/null
+++ b/include/net/nfc/nfc.h
@@ -0,0 +1,358 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ * Copyright (C) 2014 Marvell International Ltd.
+ *
+ * Authors:
+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ */
+
+#ifndef __NET_NFC_H
+#define __NET_NFC_H
+
+#include <linux/nfc.h>
+#include <linux/device.h>
+#include <linux/skbuff.h>
+
+#define nfc_dbg(dev, fmt, ...) dev_dbg((dev), "NFC: " fmt, ##__VA_ARGS__)
+#define nfc_info(dev, fmt, ...) dev_info((dev), "NFC: " fmt, ##__VA_ARGS__)
+#define nfc_err(dev, fmt, ...) dev_err((dev), "NFC: " fmt, ##__VA_ARGS__)
+
+struct nfc_phy_ops {
+ int (*write)(void *dev_id, struct sk_buff *skb);
+ int (*enable)(void *dev_id);
+ void (*disable)(void *dev_id);
+};
+
+struct nfc_dev;
+
+/**
+ * data_exchange_cb_t - Definition of nfc_data_exchange callback
+ *
+ * @context: nfc_data_exchange cb_context parameter
+ * @skb: response data
+ * @err: If an error has occurred during data exchange, it is the
+ * error number. Zero means no error.
+ *
+ * When a rx or tx package is lost or corrupted or the target gets out
+ * of the operating field, err is -EIO.
+ */
+typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb,
+ int err);
+
+typedef void (*se_io_cb_t)(void *context, u8 *apdu, size_t apdu_len, int err);
+
+struct nfc_target;
+
+struct nfc_ops {
+ int (*dev_up)(struct nfc_dev *dev);
+ int (*dev_down)(struct nfc_dev *dev);
+ int (*start_poll)(struct nfc_dev *dev,
+ u32 im_protocols, u32 tm_protocols);
+ void (*stop_poll)(struct nfc_dev *dev);
+ int (*dep_link_up)(struct nfc_dev *dev, struct nfc_target *target,
+ u8 comm_mode, u8 *gb, size_t gb_len);
+ int (*dep_link_down)(struct nfc_dev *dev);
+ int (*activate_target)(struct nfc_dev *dev, struct nfc_target *target,
+ u32 protocol);
+ void (*deactivate_target)(struct nfc_dev *dev,
+ struct nfc_target *target, u8 mode);
+ int (*im_transceive)(struct nfc_dev *dev, struct nfc_target *target,
+ struct sk_buff *skb, data_exchange_cb_t cb,
+ void *cb_context);
+ int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb);
+ int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target);
+ int (*fw_download)(struct nfc_dev *dev, const char *firmware_name);
+
+ /* Secure Element API */
+ int (*discover_se)(struct nfc_dev *dev);
+ int (*enable_se)(struct nfc_dev *dev, u32 se_idx);
+ int (*disable_se)(struct nfc_dev *dev, u32 se_idx);
+ int (*se_io) (struct nfc_dev *dev, u32 se_idx,
+ u8 *apdu, size_t apdu_length,
+ se_io_cb_t cb, void *cb_context);
+};
+
+#define NFC_TARGET_IDX_ANY -1
+#define NFC_MAX_GT_LEN 48
+#define NFC_ATR_RES_GT_OFFSET 15
+#define NFC_ATR_REQ_GT_OFFSET 14
+
+/**
+ * struct nfc_target - NFC target description
+ *
+ * @sens_res: 2 bytes describing the target SENS_RES response, if the target
+ * 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;
+ u32 supported_protocols;
+ u16 sens_res;
+ u8 sel_res;
+ u8 nfcid1_len;
+ u8 nfcid1[NFC_NFCID1_MAXSIZE];
+ u8 nfcid2_len;
+ u8 nfcid2[NFC_NFCID2_MAXSIZE];
+ u8 sensb_res_len;
+ u8 sensb_res[NFC_SENSB_RES_MAXSIZE];
+ u8 sensf_res_len;
+ u8 sensf_res[NFC_SENSF_RES_MAXSIZE];
+ u8 hci_reader_gate;
+ u8 logical_idx;
+ u8 is_iso15693;
+ u8 iso15693_dsfid;
+ u8 iso15693_uid[NFC_ISO15693_UID_MAXSIZE];
+ u8 ats_len;
+ u8 ats[NFC_ATS_MAXSIZE];
+};
+
+/**
+ * nfc_se - A structure for NFC accessible secure elements.
+ *
+ * @idx: The secure element index. User space will enable or
+ * disable a secure element by its index.
+ * @type: The secure element type. It can be SE_UICC or
+ * SE_EMBEDDED.
+ * @state: The secure element state, either enabled or disabled.
+ *
+ */
+struct nfc_se {
+ struct list_head list;
+ u32 idx;
+ u16 type;
+ u16 state;
+};
+
+/**
+ * nfc_evt_transaction - A struct for NFC secure element event transaction.
+ *
+ * @aid: The application identifier triggering the event
+ *
+ * @aid_len: The application identifier length [5:16]
+ *
+ * @params: The application parameters transmitted during the transaction
+ *
+ * @params_len: The applications parameters length [0:255]
+ *
+ */
+#define NFC_MIN_AID_LENGTH 5
+#define NFC_MAX_AID_LENGTH 16
+#define NFC_MAX_PARAMS_LENGTH 255
+
+#define NFC_EVT_TRANSACTION_AID_TAG 0x81
+#define NFC_EVT_TRANSACTION_PARAMS_TAG 0x82
+struct nfc_evt_transaction {
+ u32 aid_len;
+ u8 aid[NFC_MAX_AID_LENGTH];
+ u8 params_len;
+ u8 params[];
+} __packed;
+
+struct nfc_genl_data {
+ u32 poll_req_portid;
+ struct mutex genl_data_mutex;
+};
+
+struct nfc_vendor_cmd {
+ __u32 vendor_id;
+ __u32 subcmd;
+ int (*doit)(struct nfc_dev *dev, void *data, size_t data_len);
+};
+
+struct nfc_dev {
+ int idx;
+ u32 target_next_idx;
+ struct nfc_target *targets;
+ int n_targets;
+ int targets_generation;
+ struct device dev;
+ bool dev_up;
+ bool fw_download_in_progress;
+ u8 rf_mode;
+ bool polling;
+ struct nfc_target *active_target;
+ bool dep_link_up;
+ struct nfc_genl_data genl_data;
+ u32 supported_protocols;
+
+ struct list_head secure_elements;
+
+ int tx_headroom;
+ int tx_tailroom;
+
+ struct timer_list check_pres_timer;
+ struct work_struct check_pres_work;
+
+ bool shutting_down;
+
+ struct rfkill *rfkill;
+
+ const struct nfc_vendor_cmd *vendor_cmds;
+ int n_vendor_cmds;
+
+ const struct nfc_ops *ops;
+ struct genl_info *cur_cmd_info;
+};
+#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)
+
+extern const struct class nfc_class;
+
+struct nfc_dev *nfc_allocate_device(const struct nfc_ops *ops,
+ u32 supported_protocols,
+ int tx_headroom,
+ int tx_tailroom);
+
+/**
+ * nfc_free_device - free nfc device
+ *
+ * @dev: The nfc device to free
+ */
+static inline void nfc_free_device(struct nfc_dev *dev)
+{
+ put_device(&dev->dev);
+}
+
+int nfc_register_device(struct nfc_dev *dev);
+
+void nfc_unregister_rfkill(struct nfc_dev *dev);
+void nfc_remove_device(struct nfc_dev *dev);
+void nfc_unregister_device(struct nfc_dev *dev);
+
+/**
+ * nfc_set_parent_dev - set the parent device
+ *
+ * @nfc_dev: The nfc device whose parent is being set
+ * @dev: The parent device
+ */
+static inline void nfc_set_parent_dev(struct nfc_dev *nfc_dev,
+ struct device *dev)
+{
+ nfc_dev->dev.parent = dev;
+}
+
+/**
+ * nfc_set_drvdata - set driver specific data
+ *
+ * @dev: The nfc device
+ * @data: Pointer to driver specific data
+ */
+static inline void nfc_set_drvdata(struct nfc_dev *dev, void *data)
+{
+ dev_set_drvdata(&dev->dev, data);
+}
+
+/**
+ * nfc_get_drvdata - get driver specific data
+ *
+ * @dev: The nfc device
+ */
+static inline void *nfc_get_drvdata(const struct nfc_dev *dev)
+{
+ return dev_get_drvdata(&dev->dev);
+}
+
+/**
+ * nfc_device_name - get the nfc device name
+ *
+ * @dev: The nfc device whose name to return
+ */
+static inline const char *nfc_device_name(const struct nfc_dev *dev)
+{
+ return dev_name(&dev->dev);
+}
+
+struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
+ unsigned int flags, unsigned int size,
+ unsigned int *err);
+struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp);
+
+int nfc_set_remote_general_bytes(struct nfc_dev *dev,
+ const u8 *gt, u8 gt_len);
+u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len);
+
+int nfc_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
+ u32 result);
+
+int nfc_targets_found(struct nfc_dev *dev,
+ struct nfc_target *targets, int ntargets);
+int nfc_target_lost(struct nfc_dev *dev, u32 target_idx);
+
+int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
+ u8 comm_mode, u8 rf_mode);
+
+int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
+ const u8 *gb, size_t gb_len);
+int nfc_tm_deactivated(struct nfc_dev *dev);
+int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb);
+
+void nfc_driver_failure(struct nfc_dev *dev, int err);
+
+int nfc_se_transaction(struct nfc_dev *dev, u8 se_idx,
+ struct nfc_evt_transaction *evt_transaction);
+int nfc_se_connectivity(struct nfc_dev *dev, u8 se_idx);
+int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type);
+int nfc_remove_se(struct nfc_dev *dev, u32 se_idx);
+struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx);
+
+void nfc_send_to_raw_sock(struct nfc_dev *dev, struct sk_buff *skb,
+ u8 payload_type, u8 direction);
+
+static inline int nfc_set_vendor_cmds(struct nfc_dev *dev,
+ const struct nfc_vendor_cmd *cmds,
+ int n_cmds)
+{
+ if (dev->vendor_cmds || dev->n_vendor_cmds)
+ return -EINVAL;
+
+ dev->vendor_cmds = cmds;
+ dev->n_vendor_cmds = n_cmds;
+
+ return 0;
+}
+
+struct sk_buff *__nfc_alloc_vendor_cmd_reply_skb(struct nfc_dev *dev,
+ enum nfc_attrs attr,
+ u32 oui, u32 subcmd,
+ int approxlen);
+int nfc_vendor_cmd_reply(struct sk_buff *skb);
+
+/**
+ * nfc_vendor_cmd_alloc_reply_skb - allocate vendor command reply
+ * @dev: nfc device
+ * @oui: vendor oui
+ * @approxlen: an upper bound of the length of the data that will
+ * be put into the skb
+ *
+ * This function allocates and pre-fills an skb for a reply to
+ * a vendor command. Since it is intended for a reply, calling
+ * it outside of a vendor command's doit() operation is invalid.
+ *
+ * The returned skb is pre-filled with some identifying data in
+ * a way that any data that is put into the skb (with skb_put(),
+ * nla_put() or similar) will end up being within the
+ * %NFC_ATTR_VENDOR_DATA attribute, so all that needs to be done
+ * with the skb is adding data for the corresponding userspace tool
+ * which can then read that data out of the vendor data attribute.
+ * You must not modify the skb in any other way.
+ *
+ * When done, call nfc_vendor_cmd_reply() with the skb and return
+ * its error code as the result of the doit() operation.
+ *
+ * Return: An allocated and pre-filled skb. %NULL if any errors happen.
+ */
+static inline struct sk_buff *
+nfc_vendor_cmd_alloc_reply_skb(struct nfc_dev *dev,
+ u32 oui, u32 subcmd, int approxlen)
+{
+ return __nfc_alloc_vendor_cmd_reply_skb(dev,
+ NFC_ATTR_VENDOR_DATA,
+ oui,
+ subcmd, approxlen);
+}
+
+#endif /* __NET_NFC_H */