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

Commit 562d4d59 authored by Thierry Escande's avatar Thierry Escande Committed by Samuel Ortiz
Browse files

NFC: Sony Port-100 Series driver



This adds support for the Sony NFC USB dongle RC-S380, based on the
Port-100 chip. This dongle is an analog frontend and does not implement
the digital layer. This driver uses the nfc_digital module which is an
implementation of the NFC Digital Protocol stack.

This patch is a skeleton. It only registers the dongle against the NFC
digital protocol stack. All NFC digital operation functions are stubbed
out.

Signed-off-by: default avatarThierry Escande <thierry.escande@linux.intel.com>
Cc: Stephen Tiedemann <stephen.tiedemann@gmail.com>
Tested-by: default avatarCho, Yu-Chen <acho@suse.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 93ad4202
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -46,6 +46,16 @@ config NFC_SIM


	  If unsure, say N.
	  If unsure, say N.


config NFC_PORT100
	tristate "Sony NFC Port-100 Series USB device support"
	depends on USB
	depends on NFC_DIGITAL
	help
	  This adds support for Sony Port-100 chip based USB devices such as the
	  RC-S380 dongle.

	  If unsure, say N.

source "drivers/nfc/pn544/Kconfig"
source "drivers/nfc/pn544/Kconfig"
source "drivers/nfc/microread/Kconfig"
source "drivers/nfc/microread/Kconfig"


+1 −0
Original line number Original line Diff line number Diff line
@@ -8,5 +8,6 @@ obj-$(CONFIG_NFC_PN533) += pn533.o
obj-$(CONFIG_NFC_WILINK)	+= nfcwilink.o
obj-$(CONFIG_NFC_WILINK)	+= nfcwilink.o
obj-$(CONFIG_NFC_MEI_PHY)	+= mei_phy.o
obj-$(CONFIG_NFC_MEI_PHY)	+= mei_phy.o
obj-$(CONFIG_NFC_SIM)		+= nfcsim.o
obj-$(CONFIG_NFC_SIM)		+= nfcsim.o
obj-$(CONFIG_NFC_PORT100)	+= port100.o


ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG

drivers/nfc/port100.c

0 → 100644
+187 −0
Original line number Original line Diff line number Diff line
/*
 * Sony NFC Port-100 Series driver
 * Copyright (c) 2013, Intel Corporation.
 *
 * Partly based/Inspired by Stephen Tiedemann's nfcpy
 *
 * 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 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.
 *
 */

#include <linux/module.h>
#include <linux/usb.h>
#include <net/nfc/digital.h>

#define VERSION "0.1"

#define SONY_VENDOR_ID    0x054c
#define RCS380_PRODUCT_ID 0x06c1

#define PORT100_PROTOCOLS (NFC_PROTO_JEWEL_MASK    | \
			   NFC_PROTO_MIFARE_MASK   | \
			   NFC_PROTO_FELICA_MASK   | \
			   NFC_PROTO_NFC_DEP_MASK)

#define PORT100_CAPABILITIES (NFC_DIGITAL_DRV_CAPS_IN_CRC | \
			      NFC_DIGITAL_DRV_CAPS_TG_CRC)

struct port100 {
	struct nfc_digital_dev *nfc_digital_dev;

	int skb_headroom;
	int skb_tailroom;

	struct usb_device *udev;
	struct usb_interface *interface;
};

static void port100_abort_cmd(struct nfc_digital_dev *ddev)
{
}

static int port100_switch_rf(struct nfc_digital_dev *ddev, bool on)
{
	return -EOPNOTSUPP;
}

static int port100_in_configure_hw(struct nfc_digital_dev *ddev, int type,
				   int param)
{
	return -EOPNOTSUPP;
}

static int port100_in_send_cmd(struct nfc_digital_dev *ddev,
			       struct sk_buff *skb, u16 _timeout,
			       nfc_digital_cmd_complete_t cb, void *arg)
{
	return -EOPNOTSUPP;
}

static int port100_tg_configure_hw(struct nfc_digital_dev *ddev, int type,
				   int param)
{
	return -EOPNOTSUPP;
}

static int port100_tg_send_cmd(struct nfc_digital_dev *ddev,
			       struct sk_buff *skb, u16 timeout,
			       nfc_digital_cmd_complete_t cb, void *arg)
{
	return -EOPNOTSUPP;
}

static int port100_listen_mdaa(struct nfc_digital_dev *ddev,
			       struct digital_tg_mdaa_params *params,
			       u16 timeout,
			       nfc_digital_cmd_complete_t cb, void *arg)
{
	return -EOPNOTSUPP;
}

static int port100_listen(struct nfc_digital_dev *ddev, u16 timeout,
			  nfc_digital_cmd_complete_t cb, void *arg)
{
	return -EOPNOTSUPP;
}

static struct nfc_digital_ops port100_digital_ops = {
	.in_configure_hw = port100_in_configure_hw,
	.in_send_cmd = port100_in_send_cmd,

	.tg_listen_mdaa = port100_listen_mdaa,
	.tg_listen = port100_listen,
	.tg_configure_hw = port100_tg_configure_hw,
	.tg_send_cmd = port100_tg_send_cmd,

	.switch_rf = port100_switch_rf,
	.abort_cmd = port100_abort_cmd,
};

static const struct usb_device_id port100_table[] = {
	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE,
	  .idVendor		= SONY_VENDOR_ID,
	  .idProduct		= RCS380_PRODUCT_ID,
	},
	{ }
};
MODULE_DEVICE_TABLE(usb, port100_table);

static int port100_probe(struct usb_interface *interface,
			 const struct usb_device_id *id)
{
	struct port100 *dev;
	int rc;

	dev = devm_kzalloc(&interface->dev, sizeof(struct port100), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;

	dev->udev = usb_get_dev(interface_to_usbdev(interface));
	dev->interface = interface;
	usb_set_intfdata(interface, dev);

	nfc_info(&interface->dev, "Sony NFC Port-100 Series attached\n");

	dev->nfc_digital_dev = nfc_digital_allocate_device(&port100_digital_ops,
							   PORT100_PROTOCOLS,
							   PORT100_CAPABILITIES,
							   dev->skb_headroom,
							   dev->skb_tailroom);
	if (!dev->nfc_digital_dev) {
		nfc_err(&interface->dev,
			"Could not allocate nfc_digital_dev.\n");
		rc = -ENOMEM;
		goto error;
	}

	nfc_digital_set_parent_dev(dev->nfc_digital_dev, &interface->dev);
	nfc_digital_set_drvdata(dev->nfc_digital_dev, dev);

	rc = nfc_digital_register_device(dev->nfc_digital_dev);
	if (rc) {
		nfc_err(&interface->dev,
			"Could not register digital device.\n");
		goto free_nfc_dev;
	}

	return 0;

free_nfc_dev:
	nfc_digital_free_device(dev->nfc_digital_dev);

error:
	return rc;
}

static void port100_disconnect(struct usb_interface *interface)
{
	struct port100 *dev;

	dev = usb_get_intfdata(interface);
	usb_set_intfdata(interface, NULL);

	nfc_digital_unregister_device(dev->nfc_digital_dev);
	nfc_digital_free_device(dev->nfc_digital_dev);

	nfc_info(&interface->dev, "Sony Port-100 NFC device disconnected");
}

static struct usb_driver port100_driver = {
	.name =		"port100",
	.probe =	port100_probe,
	.disconnect =	port100_disconnect,
	.id_table =	port100_table,
};

module_usb_driver(port100_driver);

MODULE_DESCRIPTION("NFC Port-100 series usb driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");