Commit 3aacd7fe authored by Christophe Ricard's avatar Christophe Ricard Committed by Samuel Ortiz
Browse files

nfc: st-nci: Move loopback usage from HCI to NCI



NCI provides possible way to run loopback testing has done over HCI.

For us it offers many advantages:
- It simplifies the code: No more need for a vendor_cmds structure
- Loopback over HCI may not be supported in future st-nci firmware

Signed-off-by: default avatarChristophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 1c53855f
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -113,8 +113,6 @@ static struct nci_hci_gate st_nci_gates[] = {

	{NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE,
					ST_NCI_HOST_CONTROLLER_ID},
	{NCI_HCI_LOOPBACK_GATE, NCI_HCI_INVALID_PIPE,
					ST_NCI_HOST_CONTROLLER_ID},

	/* Secure element pipes are created by secure element host */
	{ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
@@ -385,9 +383,6 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
	case ST_NCI_CONNECTIVITY_GATE:
		st_nci_hci_connectivity_event_received(ndev, host, event, skb);
	break;
	case NCI_HCI_LOOPBACK_GATE:
		st_nci_hci_loopback_event_received(ndev, event, skb);
	break;
	}
}
EXPORT_SYMBOL_GPL(st_nci_hci_event_received);
+2 −11
Original line number Diff line number Diff line
@@ -92,8 +92,7 @@ struct st_nci_se_info {
 *	white list).
 * @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
 *	technology. When using this command to anti-collision is done.
 * @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
 *	connectivity.
 * @LOOPBACK: Allow to echo a command and test the Dh to CLF connectivity.
 * @HCI_DM_VDC_MEASUREMENT_VALUE: Allow to measure the field applied on the
 *	CLF antenna. A value between 0 and 0x0f is returned. 0 is maximum.
 * @HCI_DM_FWUPD_START: Allow to put CLF into firmware update mode. It is a
@@ -115,7 +114,7 @@ enum nfc_vendor_cmds {
	HCI_DM_RESET,
	HCI_GET_PARAM,
	HCI_DM_FIELD_GENERATOR,
	HCI_LOOPBACK,
	LOOPBACK,
	HCI_DM_FWUPD_START,
	HCI_DM_FWUPD_END,
	HCI_DM_VDC_MEASUREMENT_VALUE,
@@ -123,17 +122,11 @@ enum nfc_vendor_cmds {
	MANUFACTURER_SPECIFIC,
};

struct st_nci_vendor_info {
	struct completion req_completion;
	struct sk_buff *rx_skb;
};

struct st_nci_info {
	struct llt_ndlc *ndlc;
	unsigned long flags;

	struct st_nci_se_info se_info;
	struct st_nci_vendor_info vendor_info;
};

void st_nci_remove(struct nci_dev *ndev);
@@ -155,8 +148,6 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
						struct sk_buff *skb);

void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
					struct sk_buff *skb);
int st_nci_vendor_cmds_init(struct nci_dev *ndev);

#endif /* __LOCAL_ST_NCI_H_ */
+12 −50
Original line number Diff line number Diff line
@@ -333,62 +333,28 @@ static int st_nci_hci_dm_vdc_value_comparison(struct nfc_dev *dev, void *data,
	return r;
}

void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
					struct sk_buff *skb)
{
	struct st_nci_info *info = nci_get_drvdata(ndev);

	switch (event) {
	case ST_NCI_EVT_POST_DATA:
		info->vendor_info.rx_skb = skb;
	break;
	default:
		nfc_err(&ndev->nfc_dev->dev, "Unexpected event on loopback gate\n");
	}
	complete(&info->vendor_info.req_completion);
}
EXPORT_SYMBOL(st_nci_hci_loopback_event_received);

static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,
static int st_nci_loopback(struct nfc_dev *dev, void *data,
			   size_t data_len)
{
	int r;
	struct sk_buff *msg;
	struct sk_buff *msg, *skb;
	struct nci_dev *ndev = nfc_get_drvdata(dev);
	struct st_nci_info *info = nci_get_drvdata(ndev);

	if (data_len <= 0)
		return -EPROTO;

	reinit_completion(&info->vendor_info.req_completion);
	info->vendor_info.rx_skb = NULL;

	r = nci_hci_send_event(ndev, NCI_HCI_LOOPBACK_GATE,
			       ST_NCI_EVT_POST_DATA, data, data_len);
	if (r != data_len) {
		r = -EPROTO;
		goto exit;
	}

	wait_for_completion_interruptible(&info->vendor_info.req_completion);

	if (!info->vendor_info.rx_skb ||
	    info->vendor_info.rx_skb->len != data_len) {
		r = -EPROTO;
		goto exit;
	}
	r = nci_nfcc_loopback(ndev, data, data_len, &skb);
	if (r < 0)
		return r;

	msg = nfc_vendor_cmd_alloc_reply_skb(ndev->nfc_dev,
					ST_NCI_VENDOR_OUI,
					HCI_LOOPBACK,
					info->vendor_info.rx_skb->len);
	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
					     LOOPBACK, skb->len);
	if (!msg) {
		r = -ENOMEM;
		goto free_skb;
	}

	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
		    info->vendor_info.rx_skb->data)) {
	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
		kfree_skb(msg);
		r = -ENOBUFS;
		goto free_skb;
@@ -396,8 +362,7 @@ static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,

	r = nfc_vendor_cmd_reply(msg);
free_skb:
	kfree_skb(info->vendor_info.rx_skb);
exit:
	kfree_skb(skb);
	return r;
}

@@ -485,8 +450,8 @@ static struct nfc_vendor_cmd st_nci_vendor_cmds[] = {
	},
	{
		.vendor_id = ST_NCI_VENDOR_OUI,
		.subcmd = HCI_LOOPBACK,
		.doit = st_nci_hci_loopback,
		.subcmd = LOOPBACK,
		.doit = st_nci_loopback,
	},
	{
		.vendor_id = ST_NCI_VENDOR_OUI,
@@ -507,9 +472,6 @@ static struct nfc_vendor_cmd st_nci_vendor_cmds[] = {

int st_nci_vendor_cmds_init(struct nci_dev *ndev)
{
	struct st_nci_info *info = nci_get_drvdata(ndev);

	init_completion(&info->vendor_info.req_completion);
	return nfc_set_vendor_cmds(ndev->nfc_dev, st_nci_vendor_cmds,
				   sizeof(st_nci_vendor_cmds));
}