Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1f1a7da authored by Vincent Cuissard's avatar Vincent Cuissard Committed by Samuel Ortiz
Browse files

NFC: nfcmrvl: add support of HCI-based transport



In some configuration NCI packet can be encapsulated in HCI
packets. This patch had the support of this.

Signed-off-by: default avatarVincent Cuissard <cuissard@marvell.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent d18ee5a5
Loading
Loading
Loading
Loading
+33 −2
Original line number Diff line number Diff line
@@ -63,6 +63,17 @@ static int nfcmrvl_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
	if (!test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
		return -EBUSY;

	if (priv->hci_muxed) {
		unsigned char *hdr;
		unsigned char len = skb->len;

		hdr = (char *) skb_push(skb, NFCMRVL_HCI_EVENT_HEADER_SIZE);
		hdr[0] = NFCMRVL_HCI_COMMAND_CODE;
		hdr[1] = NFCMRVL_HCI_OGF;
		hdr[2] = NFCMRVL_HCI_OCF;
		hdr[3] = len;
	}

	return priv->if_ops->nci_send(priv, skb);
}

@@ -80,10 +91,12 @@ static struct nci_ops nfcmrvl_nci_ops = {

struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
						 struct nfcmrvl_if_ops *ops,
						 struct device *dev)
						 struct device *dev,
						 unsigned int flags)
{
	struct nfcmrvl_private *priv;
	int rc;
	int headroom = 0;
	u32 protocols;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -93,6 +106,10 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
	priv->drv_data = drv_data;
	priv->if_ops = ops;
	priv->dev = dev;
	priv->hci_muxed = (flags & NFCMRVL_DEV_FLAG_HCI_MUXED) ? 1 : 0;

	if (priv->hci_muxed)
		headroom = NFCMRVL_HCI_EVENT_HEADER_SIZE;

	protocols = NFC_PROTO_JEWEL_MASK
		| NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
@@ -100,7 +117,8 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
		| NFC_PROTO_ISO14443_B_MASK
		| NFC_PROTO_NFC_DEP_MASK;

	priv->ndev = nci_allocate_device(&nfcmrvl_nci_ops, protocols, 0, 0);
	priv->ndev = nci_allocate_device(&nfcmrvl_nci_ops, protocols,
					 headroom, 0);
	if (!priv->ndev) {
		nfc_err(dev, "nci_allocate_device failed\n");
		rc = -ENOMEM;
@@ -144,6 +162,19 @@ int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, void *data, int count)
		return -ENOMEM;

	memcpy(skb_put(skb, count), data, count);

	if (priv->hci_muxed) {
		if (skb->data[0] == NFCMRVL_HCI_EVENT_CODE &&
		    skb->data[1] == NFCMRVL_HCI_NFC_EVENT_CODE) {
			/* Data packet, let's extract NCI payload */
			skb_pull(skb, NFCMRVL_HCI_EVENT_HEADER_SIZE);
		} else {
			/* Skip this packet */
			kfree_skb(skb);
			return 0;
		}
	}

	nci_recv_frame(priv->ndev, skb);

	return count;
+18 −1
Original line number Diff line number Diff line
@@ -27,7 +27,23 @@
#define NFCMRVL_GPIO_PIN_NFC_ACTIVE		0xB
#define NFCMRVL_NCI_MAX_EVENT_SIZE		260

/*
** HCI defines
*/

#define NFCMRVL_HCI_EVENT_HEADER_SIZE		0x04
#define NFCMRVL_HCI_EVENT_CODE			0x04
#define NFCMRVL_HCI_NFC_EVENT_CODE		0xFF
#define NFCMRVL_HCI_COMMAND_CODE		0x01
#define NFCMRVL_HCI_OGF				0x81
#define NFCMRVL_HCI_OCF				0xFE

#define NFCMRVL_DEV_FLAG_HCI_MUXED		(1 << 0)

struct nfcmrvl_private {

	/* Tell if NCI packets are encapsulated in HCI ones */
	int hci_muxed;
	struct nci_dev *ndev;
	unsigned long flags;
	void *drv_data;
@@ -45,4 +61,5 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv);
int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, void *data, int count);
struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
						 struct nfcmrvl_if_ops *ops,
						 struct device *dev);
						 struct device *dev,
						 unsigned int flags);
+1 −1
Original line number Diff line number Diff line
@@ -329,7 +329,7 @@ static int nfcmrvl_probe(struct usb_interface *intf,
	init_usb_anchor(&drv_data->deferred);

	priv = nfcmrvl_nci_register_dev(drv_data, &usb_ops,
					&drv_data->udev->dev);
					&drv_data->udev->dev, 0);
	if (IS_ERR(priv))
		return PTR_ERR(priv);