[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/kernel/linux/v4.14/drivers/nfc/st21nfca/dep.c b/src/kernel/linux/v4.14/drivers/nfc/st21nfca/dep.c
new file mode 100644
index 0000000..3f81bfd
--- /dev/null
+++ b/src/kernel/linux/v4.14/drivers/nfc/st21nfca/dep.c
@@ -0,0 +1,692 @@
+/*
+ * Copyright (C) 2014  STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <net/nfc/hci.h>
+
+#include "st21nfca.h"
+
+#define ST21NFCA_NFCIP1_INITIATOR 0x00
+#define ST21NFCA_NFCIP1_REQ 0xd4
+#define ST21NFCA_NFCIP1_RES 0xd5
+#define ST21NFCA_NFCIP1_ATR_REQ 0x00
+#define ST21NFCA_NFCIP1_ATR_RES 0x01
+#define ST21NFCA_NFCIP1_PSL_REQ 0x04
+#define ST21NFCA_NFCIP1_PSL_RES 0x05
+#define ST21NFCA_NFCIP1_DEP_REQ 0x06
+#define ST21NFCA_NFCIP1_DEP_RES 0x07
+
+#define ST21NFCA_NFC_DEP_PFB_PNI(pfb)     ((pfb) & 0x03)
+#define ST21NFCA_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
+#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
+				((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
+#define ST21NFCA_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04)
+#define ST21NFCA_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
+#define ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT 0x10
+
+#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
+				((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
+
+#define ST21NFCA_NFC_DEP_PFB_I_PDU          0x00
+#define ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU   0x40
+#define ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
+
+#define ST21NFCA_ATR_REQ_MIN_SIZE 17
+#define ST21NFCA_ATR_REQ_MAX_SIZE 65
+#define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30
+#define ST21NFCA_GB_BIT  0x02
+
+#define ST21NFCA_EVT_SEND_DATA		0x10
+#define ST21NFCA_EVT_FIELD_ON           0x11
+#define ST21NFCA_EVT_CARD_DEACTIVATED   0x12
+#define ST21NFCA_EVT_CARD_ACTIVATED     0x13
+#define ST21NFCA_EVT_FIELD_OFF          0x14
+
+#define ST21NFCA_EVT_CARD_F_BITRATE 0x16
+#define ST21NFCA_EVT_READER_F_BITRATE 0x13
+#define	ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38)
+#define ST21NFCA_PSL_REQ_RECV_SPEED(brs) (brs & 0x07)
+#define ST21NFCA_PP2LRI(pp) ((pp & 0x30) >> 4)
+#define ST21NFCA_CARD_BITRATE_212 0x01
+#define ST21NFCA_CARD_BITRATE_424 0x02
+
+#define ST21NFCA_DEFAULT_TIMEOUT 0x0a
+
+
+#define PROTOCOL_ERR(req) pr_err("%d: ST21NFCA Protocol error: %s\n", \
+				 __LINE__, req)
+
+struct st21nfca_atr_req {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 nfcid3[NFC_NFCID3_MAXSIZE];
+	u8 did;
+	u8 bsi;
+	u8 bri;
+	u8 ppi;
+	u8 gbi[0];
+} __packed;
+
+struct st21nfca_atr_res {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 nfcid3[NFC_NFCID3_MAXSIZE];
+	u8 did;
+	u8 bsi;
+	u8 bri;
+	u8 to;
+	u8 ppi;
+	u8 gbi[0];
+} __packed;
+
+struct st21nfca_psl_req {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 did;
+	u8 brs;
+	u8 fsl;
+} __packed;
+
+struct st21nfca_psl_res {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 did;
+} __packed;
+
+struct st21nfca_dep_req_res {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 pfb;
+	u8 did;
+	u8 nad;
+} __packed;
+
+static void st21nfca_tx_work(struct work_struct *work)
+{
+	struct st21nfca_hci_info *info = container_of(work,
+						struct st21nfca_hci_info,
+						dep_info.tx_work);
+
+	struct nfc_dev *dev;
+	struct sk_buff *skb;
+
+	if (info) {
+		dev = info->hdev->ndev;
+		skb = info->dep_info.tx_pending;
+
+		device_lock(&dev->dev);
+
+		nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE,
+				ST21NFCA_WR_XCHG_DATA, skb->data, skb->len,
+				info->async_cb, info);
+		device_unlock(&dev->dev);
+		kfree_skb(skb);
+	}
+}
+
+static void st21nfca_im_send_pdu(struct st21nfca_hci_info *info,
+						struct sk_buff *skb)
+{
+	info->dep_info.tx_pending = skb;
+	schedule_work(&info->dep_info.tx_work);
+}
+
+static int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev,
+				    struct st21nfca_atr_req *atr_req)
+{
+	struct st21nfca_atr_res *atr_res;
+	struct sk_buff *skb;
+	size_t gb_len;
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	gb_len = atr_req->length - sizeof(struct st21nfca_atr_req);
+	skb = alloc_skb(atr_req->length + 1, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_put(skb, sizeof(struct st21nfca_atr_res));
+
+	atr_res = (struct st21nfca_atr_res *)skb->data;
+	memset(atr_res, 0, sizeof(struct st21nfca_atr_res));
+
+	atr_res->length = atr_req->length + 1;
+	atr_res->cmd0 = ST21NFCA_NFCIP1_RES;
+	atr_res->cmd1 = ST21NFCA_NFCIP1_ATR_RES;
+
+	memcpy(atr_res->nfcid3, atr_req->nfcid3, 6);
+	atr_res->bsi = 0x00;
+	atr_res->bri = 0x00;
+	atr_res->to = ST21NFCA_DEFAULT_TIMEOUT;
+	atr_res->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
+
+	if (gb_len) {
+		skb_put(skb, gb_len);
+
+		atr_res->ppi |= ST21NFCA_GB_BIT;
+		memcpy(atr_res->gbi, atr_req->gbi, gb_len);
+		r = nfc_set_remote_general_bytes(hdev->ndev, atr_res->gbi,
+						  gb_len);
+		if (r < 0) {
+			kfree_skb(skb);
+			return r;
+		}
+	}
+
+	info->dep_info.curr_nfc_dep_pni = 0;
+
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+				ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+	kfree_skb(skb);
+	return r;
+}
+
+static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
+				    struct sk_buff *skb)
+{
+	struct st21nfca_atr_req *atr_req;
+	size_t gb_len;
+	int r;
+
+	skb_trim(skb, skb->len - 1);
+
+	if (!skb->len) {
+		r = -EIO;
+		goto exit;
+	}
+
+	if (skb->len < ST21NFCA_ATR_REQ_MIN_SIZE) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	atr_req = (struct st21nfca_atr_req *)skb->data;
+
+	if (atr_req->length < sizeof(struct st21nfca_atr_req) ||
+	    atr_req->length > skb->len) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	r = st21nfca_tm_send_atr_res(hdev, atr_req);
+	if (r)
+		goto exit;
+
+	gb_len = skb->len - sizeof(struct st21nfca_atr_req);
+
+	r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK,
+			      NFC_COMM_PASSIVE, atr_req->gbi, gb_len);
+	if (r)
+		goto exit;
+
+	r = 0;
+
+exit:
+	return r;
+}
+
+static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev,
+				    struct st21nfca_psl_req *psl_req)
+{
+	struct st21nfca_psl_res *psl_res;
+	struct sk_buff *skb;
+	u8 bitrate[2] = {0, 0};
+	int r;
+
+	skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+	skb_put(skb, sizeof(struct st21nfca_psl_res));
+
+	psl_res = (struct st21nfca_psl_res *)skb->data;
+
+	psl_res->length = sizeof(struct st21nfca_psl_res);
+	psl_res->cmd0 = ST21NFCA_NFCIP1_RES;
+	psl_res->cmd1 = ST21NFCA_NFCIP1_PSL_RES;
+	psl_res->did = psl_req->did;
+
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+				ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+	if (r < 0)
+		goto error;
+
+	/*
+	 * ST21NFCA only support P2P passive.
+	 * PSL_REQ BRS value != 0 has only a meaning to
+	 * change technology to type F.
+	 * We change to BITRATE 424Kbits.
+	 * In other case switch to BITRATE 106Kbits.
+	 */
+	if (ST21NFCA_PSL_REQ_SEND_SPEED(psl_req->brs) &&
+	    ST21NFCA_PSL_REQ_RECV_SPEED(psl_req->brs)) {
+		bitrate[0] = ST21NFCA_CARD_BITRATE_424;
+		bitrate[1] = ST21NFCA_CARD_BITRATE_424;
+	}
+
+	/* Send an event to change bitrate change event to card f */
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+			ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2);
+error:
+	kfree_skb(skb);
+	return r;
+}
+
+static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev,
+				    struct sk_buff *skb)
+{
+	struct st21nfca_psl_req *psl_req;
+	int r;
+
+	skb_trim(skb, skb->len - 1);
+
+	if (!skb->len) {
+		r = -EIO;
+		goto exit;
+	}
+
+	psl_req = (struct st21nfca_psl_req *)skb->data;
+
+	if (skb->len < sizeof(struct st21nfca_psl_req)) {
+		r = -EIO;
+		goto exit;
+	}
+
+	r = st21nfca_tm_send_psl_res(hdev, psl_req);
+exit:
+	return r;
+}
+
+int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	*(u8 *)skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
+	*(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_RES;
+	*(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_RES;
+	*(u8 *)skb_push(skb, 1) = skb->len;
+
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+			ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+	kfree_skb(skb);
+
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_tm_send_dep_res);
+
+static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev,
+				    struct sk_buff *skb)
+{
+	struct st21nfca_dep_req_res *dep_req;
+	u8 size;
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	skb_trim(skb, skb->len - 1);
+
+	size = 4;
+
+	dep_req = (struct st21nfca_dep_req_res *)skb->data;
+	if (skb->len < size) {
+		r = -EIO;
+		goto exit;
+	}
+
+	if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_req->pfb))
+		size++;
+	if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_req->pfb))
+		size++;
+
+	if (skb->len < size) {
+		r = -EIO;
+		goto exit;
+	}
+
+	/* Receiving DEP_REQ - Decoding */
+	switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_req->pfb)) {
+	case ST21NFCA_NFC_DEP_PFB_I_PDU:
+		info->dep_info.curr_nfc_dep_pni =
+				ST21NFCA_NFC_DEP_PFB_PNI(dep_req->pfb);
+		break;
+	case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
+		pr_err("Received a ACK/NACK PDU\n");
+		break;
+	case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
+		pr_err("Received a SUPERVISOR PDU\n");
+		break;
+	}
+
+	skb_pull(skb, size);
+
+	return nfc_tm_data_received(hdev->ndev, skb);
+exit:
+	return r;
+}
+
+static int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev,
+				struct sk_buff *skb)
+{
+	u8 cmd0, cmd1;
+	int r;
+
+	cmd0 = skb->data[1];
+	switch (cmd0) {
+	case ST21NFCA_NFCIP1_REQ:
+		cmd1 = skb->data[2];
+		switch (cmd1) {
+		case ST21NFCA_NFCIP1_ATR_REQ:
+			r = st21nfca_tm_recv_atr_req(hdev, skb);
+			break;
+		case ST21NFCA_NFCIP1_PSL_REQ:
+			r = st21nfca_tm_recv_psl_req(hdev, skb);
+			break;
+		case ST21NFCA_NFCIP1_DEP_REQ:
+			r = st21nfca_tm_recv_dep_req(hdev, skb);
+			break;
+		default:
+			return 1;
+		}
+	default:
+		return 1;
+	}
+	return r;
+}
+
+/*
+ * Returns:
+ * <= 0: driver handled the event, skb consumed
+ *    1: driver does not handle the event, please do standard processing
+ */
+int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
+				u8 event, struct sk_buff *skb)
+{
+	int r = 0;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_debug("dep event: %d\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_CARD_ACTIVATED:
+		info->dep_info.curr_nfc_dep_pni = 0;
+		break;
+	case ST21NFCA_EVT_CARD_DEACTIVATED:
+		break;
+	case ST21NFCA_EVT_FIELD_ON:
+		break;
+	case ST21NFCA_EVT_FIELD_OFF:
+		break;
+	case ST21NFCA_EVT_SEND_DATA:
+		r = st21nfca_tm_event_send_data(hdev, skb);
+		if (r < 0)
+			return r;
+		return 0;
+	default:
+		nfc_err(&hdev->ndev->dev, "Unexpected event on card f gate\n");
+		return 1;
+	}
+	kfree_skb(skb);
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_dep_event_received);
+
+static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi,
+				     u8 bri, u8 lri)
+{
+	struct sk_buff *skb;
+	struct st21nfca_psl_req *psl_req;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	skb =
+	    alloc_skb(sizeof(struct st21nfca_psl_req) + 1, GFP_KERNEL);
+	if (!skb)
+		return;
+	skb_reserve(skb, 1);
+
+	skb_put(skb, sizeof(struct st21nfca_psl_req));
+	psl_req = (struct st21nfca_psl_req *) skb->data;
+
+	psl_req->length = sizeof(struct st21nfca_psl_req);
+	psl_req->cmd0 = ST21NFCA_NFCIP1_REQ;
+	psl_req->cmd1 = ST21NFCA_NFCIP1_PSL_REQ;
+	psl_req->did = did;
+	psl_req->brs = (0x30 & bsi << 4) | (bri & 0x03);
+	psl_req->fsl = lri;
+
+	*(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+	st21nfca_im_send_pdu(info, skb);
+}
+
+#define ST21NFCA_CB_TYPE_READER_F 1
+static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb,
+					int err)
+{
+	struct st21nfca_hci_info *info = context;
+	struct st21nfca_atr_res *atr_res;
+	int r;
+
+	if (err != 0)
+		return;
+
+	if (!skb)
+		return;
+
+	switch (info->async_cb_type) {
+	case ST21NFCA_CB_TYPE_READER_F:
+		skb_trim(skb, skb->len - 1);
+		atr_res = (struct st21nfca_atr_res *)skb->data;
+		r = nfc_set_remote_general_bytes(info->hdev->ndev,
+				atr_res->gbi,
+				skb->len - sizeof(struct st21nfca_atr_res));
+		if (r < 0)
+			return;
+
+		if (atr_res->to >= 0x0e)
+			info->dep_info.to = 0x0e;
+		else
+			info->dep_info.to = atr_res->to + 1;
+
+		info->dep_info.to |= 0x10;
+
+		r = nfc_dep_link_is_up(info->hdev->ndev, info->dep_info.idx,
+					NFC_COMM_PASSIVE, NFC_RF_INITIATOR);
+		if (r < 0)
+			return;
+
+		info->dep_info.curr_nfc_dep_pni = 0;
+		if (ST21NFCA_PP2LRI(atr_res->ppi) != info->dep_info.lri)
+			st21nfca_im_send_psl_req(info->hdev, atr_res->did,
+						atr_res->bsi, atr_res->bri,
+						ST21NFCA_PP2LRI(atr_res->ppi));
+		break;
+	default:
+		kfree_skb(skb);
+		break;
+	}
+}
+
+int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len)
+{
+	struct sk_buff *skb;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	struct st21nfca_atr_req *atr_req;
+	struct nfc_target *target;
+	uint size;
+
+	info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
+	size = ST21NFCA_ATR_REQ_MIN_SIZE + gb_len;
+	if (size > ST21NFCA_ATR_REQ_MAX_SIZE) {
+		PROTOCOL_ERR("14.6.1.1");
+		return -EINVAL;
+	}
+
+	skb =
+	    alloc_skb(sizeof(struct st21nfca_atr_req) + gb_len + 1, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_reserve(skb, 1);
+
+	skb_put(skb, sizeof(struct st21nfca_atr_req));
+
+	atr_req = (struct st21nfca_atr_req *)skb->data;
+	memset(atr_req, 0, sizeof(struct st21nfca_atr_req));
+
+	atr_req->cmd0 = ST21NFCA_NFCIP1_REQ;
+	atr_req->cmd1 = ST21NFCA_NFCIP1_ATR_REQ;
+	memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE);
+	target = hdev->ndev->targets;
+
+	if (target->sensf_res_len > 0)
+		memcpy(atr_req->nfcid3, target->sensf_res,
+				target->sensf_res_len);
+	else
+		get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
+
+	atr_req->did = 0x0;
+
+	atr_req->bsi = 0x00;
+	atr_req->bri = 0x00;
+	atr_req->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
+	if (gb_len) {
+		atr_req->ppi |= ST21NFCA_GB_BIT;
+		skb_put_data(skb, gb, gb_len);
+	}
+	atr_req->length = sizeof(struct st21nfca_atr_req) + hdev->gb_len;
+
+	*(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10; /* timeout */
+
+	info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
+	info->async_cb_context = info;
+	info->async_cb = st21nfca_im_recv_atr_res_cb;
+	info->dep_info.bri = atr_req->bri;
+	info->dep_info.bsi = atr_req->bsi;
+	info->dep_info.lri = ST21NFCA_PP2LRI(atr_req->ppi);
+
+	return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
+				ST21NFCA_WR_XCHG_DATA, skb->data,
+				skb->len, info->async_cb, info);
+}
+EXPORT_SYMBOL(st21nfca_im_send_atr_req);
+
+static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb,
+					int err)
+{
+	struct st21nfca_hci_info *info = context;
+	struct st21nfca_dep_req_res *dep_res;
+
+	int size;
+
+	if (err != 0)
+		return;
+
+	if (!skb)
+		return;
+
+	switch (info->async_cb_type) {
+	case ST21NFCA_CB_TYPE_READER_F:
+		dep_res = (struct st21nfca_dep_req_res *)skb->data;
+
+		size = 3;
+		if (skb->len < size)
+			goto exit;
+
+		if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_res->pfb))
+			size++;
+		if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_res->pfb))
+			size++;
+
+		if (skb->len < size)
+			goto exit;
+
+		skb_trim(skb, skb->len - 1);
+
+		/* Receiving DEP_REQ - Decoding */
+		switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) {
+		case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
+			pr_err("Received a ACK/NACK PDU\n");
+		case ST21NFCA_NFC_DEP_PFB_I_PDU:
+			info->dep_info.curr_nfc_dep_pni =
+			    ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1);
+			size++;
+			skb_pull(skb, size);
+			nfc_tm_data_received(info->hdev->ndev, skb);
+			break;
+		case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
+			pr_err("Received a SUPERVISOR PDU\n");
+			skb_pull(skb, size);
+			*(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
+			*(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
+			*(u8 *)skb_push(skb, 1) = skb->len;
+			*(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+			st21nfca_im_send_pdu(info, skb);
+			break;
+		}
+
+		return;
+	default:
+		break;
+	}
+
+exit:
+	kfree_skb(skb);
+}
+
+int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
+	info->async_cb_context = info;
+	info->async_cb = st21nfca_im_recv_dep_res_cb;
+
+	*(u8 *)skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
+	*(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
+	*(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
+	*(u8 *)skb_push(skb, 1) = skb->len;
+
+	*(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+	return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
+				      ST21NFCA_WR_XCHG_DATA,
+				      skb->data, skb->len,
+				      info->async_cb, info);
+}
+EXPORT_SYMBOL(st21nfca_im_send_dep_req);
+
+void st21nfca_dep_init(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	INIT_WORK(&info->dep_info.tx_work, st21nfca_tx_work);
+	info->dep_info.curr_nfc_dep_pni = 0;
+	info->dep_info.idx = 0;
+	info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
+}
+EXPORT_SYMBOL(st21nfca_dep_init);
+
+void st21nfca_dep_deinit(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	cancel_work_sync(&info->dep_info.tx_work);
+}
+EXPORT_SYMBOL(st21nfca_dep_deinit);