Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
# SPDX-License-Identifier: GPL-2.0-only
config NFC_PN533
tristate
help
NXP PN533 core driver.
This driver provides core functionality for NXP PN533 NFC devices.
config NFC_PN533_USB
tristate "NFC PN533 device support (USB)"
depends on USB
select NFC_PN533
help
This module adds support for the NXP pn533 USB interface.
Select this if your platform is using the USB bus.
If you choose to build a module, it'll be called pn533_usb.
Say N if unsure.
config NFC_PN533_I2C
tristate "NFC PN533 device support (I2C)"
depends on I2C
select NFC_PN533
help
This module adds support for the NXP pn533 I2C interface.
Select this if your platform is using the I2C bus.
If you choose to build a module, it'll be called pn533_i2c.
Say N if unsure.
config NFC_PN532_UART
tristate "NFC PN532 device support (UART)"
depends on SERIAL_DEV_BUS
select NFC_PN533
help
This module adds support for the NXP pn532 UART interface.
Select this if your platform is using the UART bus.
If you choose to build a module, it'll be called pn532_uart.
Say N if unsure.
+12
View File
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for PN533 NFC driver
#
pn533_usb-objs = usb.o
pn533_i2c-objs = i2c.o
pn532_uart-objs = uart.o
obj-$(CONFIG_NFC_PN533) += pn533.o
obj-$(CONFIG_NFC_PN533_USB) += pn533_usb.o
obj-$(CONFIG_NFC_PN533_I2C) += pn533_i2c.o
obj-$(CONFIG_NFC_PN532_UART) += pn532_uart.o
+272
View File
@@ -0,0 +1,272 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for NXP PN533 NFC Chip - I2C transport layer
*
* Copyright (C) 2011 Instituto Nokia de Tecnologia
* Copyright (C) 2012-2013 Tieto Poland
* Copyright (C) 2016 HALE electronic
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/nfc.h>
#include <linux/netdevice.h>
#include <linux/interrupt.h>
#include <net/nfc/nfc.h>
#include "pn533.h"
#define VERSION "0.1"
#define PN533_I2C_DRIVER_NAME "pn533_i2c"
struct pn533_i2c_phy {
struct i2c_client *i2c_dev;
struct pn533 *priv;
bool aborted;
int hard_fault; /*
* < 0 if hardware error occurred (e.g. i2c err)
* and prevents normal operation.
*/
};
static int pn533_i2c_send_ack(struct pn533 *dev, gfp_t flags)
{
struct pn533_i2c_phy *phy = dev->phy;
struct i2c_client *client = phy->i2c_dev;
static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
/* spec 6.2.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */
return i2c_master_send(client, ack, 6);
}
static int pn533_i2c_send_frame(struct pn533 *dev,
struct sk_buff *out)
{
struct pn533_i2c_phy *phy = dev->phy;
struct i2c_client *client = phy->i2c_dev;
int rc;
if (phy->hard_fault != 0)
return phy->hard_fault;
if (phy->priv == NULL)
phy->priv = dev;
phy->aborted = false;
print_hex_dump_debug("PN533_i2c TX: ", DUMP_PREFIX_NONE, 16, 1,
out->data, out->len, false);
rc = i2c_master_send(client, out->data, out->len);
if (rc == -EREMOTEIO) { /* Retry, chip was in power down */
usleep_range(6000, 10000);
rc = i2c_master_send(client, out->data, out->len);
}
if (rc >= 0) {
if (rc != out->len)
rc = -EREMOTEIO;
else
rc = 0;
}
return rc;
}
static void pn533_i2c_abort_cmd(struct pn533 *dev, gfp_t flags)
{
struct pn533_i2c_phy *phy = dev->phy;
phy->aborted = true;
/* An ack will cancel the last issued command */
pn533_i2c_send_ack(dev, flags);
/* schedule cmd_complete_work to finish current command execution */
pn533_recv_frame(phy->priv, NULL, -ENOENT);
}
static int pn533_i2c_read(struct pn533_i2c_phy *phy, struct sk_buff **skb)
{
struct i2c_client *client = phy->i2c_dev;
int len = PN533_EXT_FRAME_HEADER_LEN +
PN533_STD_FRAME_MAX_PAYLOAD_LEN +
PN533_STD_FRAME_TAIL_LEN + 1;
int r;
*skb = alloc_skb(len, GFP_KERNEL);
if (*skb == NULL)
return -ENOMEM;
r = i2c_master_recv(client, skb_put(*skb, len), len);
if (r != len) {
nfc_err(&client->dev, "cannot read. r=%d len=%d\n", r, len);
kfree_skb(*skb);
return -EREMOTEIO;
}
if (!((*skb)->data[0] & 0x01)) {
nfc_err(&client->dev, "READY flag not set");
kfree_skb(*skb);
return -EBUSY;
}
/* remove READY byte */
skb_pull(*skb, 1);
/* trim to frame size */
skb_trim(*skb, phy->priv->ops->rx_frame_size((*skb)->data));
return 0;
}
static irqreturn_t pn533_i2c_irq_thread_fn(int irq, void *data)
{
struct pn533_i2c_phy *phy = data;
struct sk_buff *skb = NULL;
int r;
if (!phy || irq != phy->i2c_dev->irq) {
WARN_ON_ONCE(1);
return IRQ_NONE;
}
if (phy->hard_fault != 0)
return IRQ_HANDLED;
r = pn533_i2c_read(phy, &skb);
if (r == -EREMOTEIO) {
phy->hard_fault = r;
pn533_recv_frame(phy->priv, NULL, -EREMOTEIO);
return IRQ_HANDLED;
} else if ((r == -ENOMEM) || (r == -EBADMSG) || (r == -EBUSY)) {
return IRQ_HANDLED;
}
if (!phy->aborted)
pn533_recv_frame(phy->priv, skb, 0);
return IRQ_HANDLED;
}
static const struct pn533_phy_ops i2c_phy_ops = {
.send_frame = pn533_i2c_send_frame,
.send_ack = pn533_i2c_send_ack,
.abort_cmd = pn533_i2c_abort_cmd,
};
static int pn533_i2c_probe(struct i2c_client *client)
{
struct pn533_i2c_phy *phy;
struct pn533 *priv;
int r = 0;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
return -ENODEV;
}
phy = devm_kzalloc(&client->dev, sizeof(struct pn533_i2c_phy),
GFP_KERNEL);
if (!phy)
return -ENOMEM;
phy->i2c_dev = client;
i2c_set_clientdata(client, phy);
priv = pn53x_common_init(PN533_DEVICE_PN532,
PN533_PROTO_REQ_ACK_RESP,
phy, &i2c_phy_ops, NULL,
&phy->i2c_dev->dev);
if (IS_ERR(priv))
return PTR_ERR(priv);
phy->priv = priv;
r = pn532_i2c_nfc_alloc(priv, PN533_NO_TYPE_B_PROTOCOLS, &client->dev);
if (r)
goto nfc_alloc_err;
r = request_threaded_irq(client->irq, NULL, pn533_i2c_irq_thread_fn,
IRQF_TRIGGER_FALLING |
IRQF_SHARED | IRQF_ONESHOT,
PN533_I2C_DRIVER_NAME, phy);
if (r < 0) {
nfc_err(&client->dev, "Unable to register IRQ handler\n");
goto irq_rqst_err;
}
r = pn533_finalize_setup(priv);
if (r)
goto fn_setup_err;
r = nfc_register_device(priv->nfc_dev);
if (r)
goto fn_setup_err;
return r;
fn_setup_err:
free_irq(client->irq, phy);
irq_rqst_err:
nfc_free_device(priv->nfc_dev);
nfc_alloc_err:
pn53x_common_clean(phy->priv);
return r;
}
static void pn533_i2c_remove(struct i2c_client *client)
{
struct pn533_i2c_phy *phy = i2c_get_clientdata(client);
free_irq(client->irq, phy);
pn53x_unregister_nfc(phy->priv);
pn53x_common_clean(phy->priv);
}
static const struct of_device_id of_pn533_i2c_match[] __maybe_unused = {
{ .compatible = "nxp,pn532", },
/*
* NOTE: The use of the compatibles with the trailing "...-i2c" is
* deprecated and will be removed.
*/
{ .compatible = "nxp,pn533-i2c", },
{ .compatible = "nxp,pn532-i2c", },
{},
};
MODULE_DEVICE_TABLE(of, of_pn533_i2c_match);
static const struct i2c_device_id pn533_i2c_id_table[] = {
{ .name = PN533_I2C_DRIVER_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, pn533_i2c_id_table);
static struct i2c_driver pn533_i2c_driver = {
.driver = {
.name = PN533_I2C_DRIVER_NAME,
.of_match_table = of_match_ptr(of_pn533_i2c_match),
},
.probe = pn533_i2c_probe,
.id_table = pn533_i2c_id_table,
.remove = pn533_i2c_remove,
};
module_i2c_driver(pn533_i2c_driver);
MODULE_AUTHOR("Michael Thalmeier <michael.thalmeier@hale.at>");
MODULE_DESCRIPTION("PN533 I2C driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
File diff suppressed because it is too large Load Diff
+249
View File
@@ -0,0 +1,249 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Driver for NXP PN533 NFC Chip
*
* Copyright (C) 2011 Instituto Nokia de Tecnologia
* Copyright (C) 2012-2013 Tieto Poland
*/
#define PN533_DEVICE_STD 0x1
#define PN533_DEVICE_PASORI 0x2
#define PN533_DEVICE_ACR122U 0x3
#define PN533_DEVICE_PN532 0x4
#define PN533_DEVICE_PN532_AUTOPOLL 0x5
#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\
NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\
NFC_PROTO_NFC_DEP_MASK |\
NFC_PROTO_ISO14443_B_MASK)
#define PN533_NO_TYPE_B_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
NFC_PROTO_MIFARE_MASK | \
NFC_PROTO_FELICA_MASK | \
NFC_PROTO_ISO14443_MASK | \
NFC_PROTO_NFC_DEP_MASK)
/* Standard pn533 frame definitions (standard and extended)*/
#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \
+ 2) /* data[0] TFI, data[1] CC */
#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/
#define PN533_EXT_FRAME_HEADER_LEN (sizeof(struct pn533_ext_frame) \
+ 2) /* data[0] TFI, data[1] CC */
#define PN533_CMD_DATAEXCH_HEAD_LEN 1
#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
#define PN533_CMD_DATAFRAME_MAXLEN 240 /* max data length (send) */
/*
* Max extended frame payload len, excluding TFI and CC
* which are already in PN533_FRAME_HEADER_LEN.
*/
#define PN533_STD_FRAME_MAX_PAYLOAD_LEN 263
/* Preamble (1), SoPC (2), ACK Code (2), Postamble (1) */
#define PN533_STD_FRAME_ACK_SIZE 6
/*
* Preamble (1), SoPC (2), Packet Length (1), Packet Length Checksum (1),
* Specific Application Level Error Code (1) , Postamble (1)
*/
#define PN533_STD_ERROR_FRAME_SIZE 8
#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen])
#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
/* Half start code (3), LEN (4) should be 0xffff for extended frame */
#define PN533_STD_IS_EXTENDED(hdr) ((hdr)->datalen == 0xFF \
&& (hdr)->datalen_checksum == 0xFF)
#define PN533_EXT_FRAME_CHECKSUM(f) (f->data[be16_to_cpu(f->datalen)])
/* start of frame */
#define PN533_STD_FRAME_SOF 0x00FF
/* standard frame identifier: in/out/error */
#define PN533_STD_FRAME_IDENTIFIER(f) (f->data[0]) /* TFI */
#define PN533_STD_FRAME_DIR_OUT 0xD4
#define PN533_STD_FRAME_DIR_IN 0xD5
/* PN533 Commands */
#define PN533_FRAME_CMD(f) (f->data[1])
#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
#define PN533_CMD_SAM_CONFIGURATION 0x14
#define PN533_CMD_RF_CONFIGURATION 0x32
#define PN533_CMD_IN_DATA_EXCHANGE 0x40
#define PN533_CMD_IN_COMM_THRU 0x42
#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A
#define PN533_CMD_IN_ATR 0x50
#define PN533_CMD_IN_RELEASE 0x52
#define PN533_CMD_IN_JUMP_FOR_DEP 0x56
#define PN533_CMD_IN_AUTOPOLL 0x60
#define PN533_CMD_TG_INIT_AS_TARGET 0x8c
#define PN533_CMD_TG_GET_DATA 0x86
#define PN533_CMD_TG_SET_DATA 0x8e
#define PN533_CMD_TG_SET_META_DATA 0x94
#define PN533_CMD_UNDEF 0xff
#define PN533_CMD_RESPONSE(cmd) (cmd + 1)
/* PN533 Return codes */
#define PN533_CMD_RET_MASK 0x3F
#define PN533_CMD_MI_MASK 0x40
#define PN533_CMD_RET_SUCCESS 0x00
#define PN533_FRAME_DATALEN_ACK 0x00
#define PN533_FRAME_DATALEN_ERROR 0x01
#define PN533_FRAME_DATALEN_EXTENDED 0xFF
enum pn533_protocol_type {
PN533_PROTO_REQ_ACK_RESP = 0,
PN533_PROTO_REQ_RESP
};
/* Poll modulations */
enum {
PN533_POLL_MOD_106KBPS_A,
PN533_POLL_MOD_212KBPS_FELICA,
PN533_POLL_MOD_424KBPS_FELICA,
PN533_POLL_MOD_106KBPS_JEWEL,
PN533_POLL_MOD_847KBPS_B,
PN533_LISTEN_MOD,
__PN533_POLL_MOD_AFTER_LAST,
};
#define PN533_POLL_MOD_MAX (__PN533_POLL_MOD_AFTER_LAST - 1)
struct pn533_std_frame {
u8 preamble;
__be16 start_frame;
u8 datalen;
u8 datalen_checksum;
u8 data[];
} __packed;
struct pn533_ext_frame { /* Extended Information frame */
u8 preamble;
__be16 start_frame;
__be16 eif_flag; /* fixed to 0xFFFF */
__be16 datalen;
u8 datalen_checksum;
u8 data[];
} __packed;
struct pn533 {
struct nfc_dev *nfc_dev;
u32 device_type;
enum pn533_protocol_type protocol_type;
struct sk_buff_head resp_q;
struct sk_buff_head fragment_skb;
struct workqueue_struct *wq;
struct work_struct cmd_work;
struct work_struct cmd_complete_work;
struct delayed_work poll_work;
struct work_struct mi_rx_work;
struct work_struct mi_tx_work;
struct work_struct mi_tm_rx_work;
struct work_struct mi_tm_tx_work;
struct work_struct tg_work;
struct work_struct rf_work;
struct list_head cmd_queue;
struct pn533_cmd *cmd;
u8 cmd_pending;
struct mutex cmd_lock; /* protects cmd queue */
void *cmd_complete_mi_arg;
void *cmd_complete_dep_arg;
struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
u8 poll_mod_count;
u8 poll_mod_curr;
u8 poll_dep;
u32 poll_protocols;
u32 listen_protocols;
struct timer_list listen_timer;
int cancel_listen;
u8 *gb;
size_t gb_len;
u8 tgt_available_prots;
u8 tgt_active_prot;
u8 tgt_mode;
struct pn533_frame_ops *ops;
struct device *dev;
void *phy;
const struct pn533_phy_ops *phy_ops;
};
typedef int (*pn533_send_async_complete_t) (struct pn533 *dev, void *arg,
struct sk_buff *resp);
struct pn533_cmd {
struct list_head queue;
u8 code;
int status;
struct sk_buff *req;
struct sk_buff *resp;
pn533_send_async_complete_t complete_cb;
void *complete_cb_context;
};
struct pn533_frame_ops {
void (*tx_frame_init)(void *frame, u8 cmd_code);
void (*tx_frame_finish)(void *frame);
void (*tx_update_payload_len)(void *frame, int len);
int tx_header_len;
int tx_tail_len;
bool (*rx_is_frame_valid)(void *frame, struct pn533 *dev);
bool (*rx_frame_is_ack)(void *frame);
int (*rx_frame_size)(void *frame);
int rx_header_len;
int rx_tail_len;
int max_payload_len;
u8 (*get_cmd_code)(void *frame);
};
struct pn533_phy_ops {
int (*send_frame)(struct pn533 *priv,
struct sk_buff *out);
int (*send_ack)(struct pn533 *dev, gfp_t flags);
void (*abort_cmd)(struct pn533 *priv, gfp_t flags);
/*
* dev_up and dev_down are optional.
* They are used to inform the phy layer that the nfc chip
* is going to be really used very soon. The phy layer can then
* bring up it's interface to the chip and have it suspended for power
* saving reasons otherwise.
*/
int (*dev_up)(struct pn533 *priv);
int (*dev_down)(struct pn533 *priv);
};
struct pn533 *pn53x_common_init(u32 device_type,
enum pn533_protocol_type protocol_type,
void *phy,
const struct pn533_phy_ops *phy_ops,
struct pn533_frame_ops *fops,
struct device *dev);
int pn533_finalize_setup(struct pn533 *dev);
void pn53x_common_clean(struct pn533 *priv);
void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status);
int pn532_i2c_nfc_alloc(struct pn533 *priv, u32 protocols,
struct device *parent);
int pn53x_register_nfc(struct pn533 *priv, u32 protocols,
struct device *parent);
void pn53x_unregister_nfc(struct pn533 *priv);
bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame);
bool pn533_rx_frame_is_ack(void *_frame);
+339
View File
@@ -0,0 +1,339 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Driver for NXP PN532 NFC Chip - UART transport layer
*
* Copyright (C) 2018 Lemonage Software GmbH
* Author: Lars Pöschel <poeschel@lemonage.de>
* All rights reserved.
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/nfc.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/serdev.h>
#include "pn533.h"
#define PN532_UART_SKB_BUFF_LEN (PN533_CMD_DATAEXCH_DATA_MAXLEN * 2)
enum send_wakeup {
PN532_SEND_NO_WAKEUP = 0,
PN532_SEND_WAKEUP,
PN532_SEND_LAST_WAKEUP,
};
struct pn532_uart_phy {
struct serdev_device *serdev;
struct sk_buff *recv_skb;
struct pn533 *priv;
/*
* send_wakeup variable is used to control if we need to send a wakeup
* request to the pn532 chip prior to our actual command. There is a
* little propability of a race condition. We decided to not mutex the
* variable as the worst that could happen is, that we send a wakeup
* to the chip that is already awake. This does not hurt. It is a
* no-op to the chip.
*/
enum send_wakeup send_wakeup;
struct timer_list cmd_timeout;
struct sk_buff *cur_out_buf;
};
static int pn532_uart_send_frame(struct pn533 *dev,
struct sk_buff *out)
{
/* wakeup sequence and dummy bytes for waiting time */
static const u8 wakeup[] = {
0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
struct pn532_uart_phy *pn532 = dev->phy;
int err;
print_hex_dump_debug("PN532_uart TX: ", DUMP_PREFIX_NONE, 16, 1,
out->data, out->len, false);
pn532->cur_out_buf = out;
if (pn532->send_wakeup) {
err = serdev_device_write(pn532->serdev,
wakeup, sizeof(wakeup),
MAX_SCHEDULE_TIMEOUT);
if (err < 0)
return err;
}
if (pn532->send_wakeup == PN532_SEND_LAST_WAKEUP)
pn532->send_wakeup = PN532_SEND_NO_WAKEUP;
err = serdev_device_write(pn532->serdev, out->data, out->len,
MAX_SCHEDULE_TIMEOUT);
if (err < 0)
return err;
mod_timer(&pn532->cmd_timeout, HZ / 40 + jiffies);
return 0;
}
static int pn532_uart_send_ack(struct pn533 *dev, gfp_t flags)
{
/* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */
static const u8 ack[PN533_STD_FRAME_ACK_SIZE] = {
0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
struct pn532_uart_phy *pn532 = dev->phy;
int err;
err = serdev_device_write(pn532->serdev, ack, sizeof(ack),
MAX_SCHEDULE_TIMEOUT);
if (err < 0)
return err;
return 0;
}
static void pn532_uart_abort_cmd(struct pn533 *dev, gfp_t flags)
{
/* An ack will cancel the last issued command */
pn532_uart_send_ack(dev, flags);
/* schedule cmd_complete_work to finish current command execution */
pn533_recv_frame(dev, NULL, -ENOENT);
}
static int pn532_dev_up(struct pn533 *dev)
{
struct pn532_uart_phy *pn532 = dev->phy;
int ret = 0;
ret = serdev_device_open(pn532->serdev);
if (ret)
return ret;
pn532->send_wakeup = PN532_SEND_LAST_WAKEUP;
return ret;
}
static int pn532_dev_down(struct pn533 *dev)
{
struct pn532_uart_phy *pn532 = dev->phy;
serdev_device_close(pn532->serdev);
pn532->send_wakeup = PN532_SEND_WAKEUP;
return 0;
}
static const struct pn533_phy_ops uart_phy_ops = {
.send_frame = pn532_uart_send_frame,
.send_ack = pn532_uart_send_ack,
.abort_cmd = pn532_uart_abort_cmd,
.dev_up = pn532_dev_up,
.dev_down = pn532_dev_down,
};
static void pn532_cmd_timeout(struct timer_list *t)
{
struct pn532_uart_phy *dev = timer_container_of(dev, t, cmd_timeout);
pn532_uart_send_frame(dev->priv, dev->cur_out_buf);
}
/*
* scans the buffer if it contains a pn532 frame. It is not checked if the
* frame is really valid. This is later done with pn533_rx_frame_is_valid.
* This is useful for malformed or errornous transmitted frames. Adjusts the
* bufferposition where the frame starts, since pn533_recv_frame expects a
* well formed frame.
*/
static int pn532_uart_rx_is_frame(struct sk_buff *skb)
{
struct pn533_std_frame *std;
struct pn533_ext_frame *ext;
u16 frame_len;
int i;
for (i = 0; i + PN533_STD_FRAME_ACK_SIZE <= skb->len; i++) {
std = (struct pn533_std_frame *)&skb->data[i];
/* search start code */
if (std->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
continue;
/* frame type */
switch (std->datalen) {
case PN533_FRAME_DATALEN_ACK:
if (std->datalen_checksum == 0xff) {
skb_pull(skb, i);
return 1;
}
break;
case PN533_FRAME_DATALEN_ERROR:
if ((std->datalen_checksum == 0xff) &&
(skb->len >=
PN533_STD_ERROR_FRAME_SIZE)) {
skb_pull(skb, i);
return 1;
}
break;
case PN533_FRAME_DATALEN_EXTENDED:
ext = (struct pn533_ext_frame *)&skb->data[i];
frame_len = be16_to_cpu(ext->datalen);
if (skb->len >= frame_len +
sizeof(struct pn533_ext_frame) +
2 /* CKS + Postamble */) {
skb_pull(skb, i);
return 1;
}
break;
default: /* normal information frame */
frame_len = std->datalen;
if (skb->len >= frame_len +
sizeof(struct pn533_std_frame) +
2 /* CKS + Postamble */) {
skb_pull(skb, i);
return 1;
}
break;
}
}
return 0;
}
static size_t pn532_receive_buf(struct serdev_device *serdev,
const u8 *data, size_t count)
{
struct pn532_uart_phy *dev = serdev_device_get_drvdata(serdev);
size_t i;
timer_delete(&dev->cmd_timeout);
for (i = 0; i < count; i++) {
if (!dev->recv_skb) {
dev->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN,
GFP_KERNEL);
if (!dev->recv_skb)
return i;
}
if (unlikely(!skb_tailroom(dev->recv_skb)))
skb_trim(dev->recv_skb, 0);
skb_put_u8(dev->recv_skb, *data++);
if (!pn532_uart_rx_is_frame(dev->recv_skb))
continue;
pn533_recv_frame(dev->priv, dev->recv_skb, 0);
dev->recv_skb = NULL;
}
return i;
}
static const struct serdev_device_ops pn532_serdev_ops = {
.receive_buf = pn532_receive_buf,
.write_wakeup = serdev_device_write_wakeup,
};
static const struct of_device_id pn532_uart_of_match[] = {
{ .compatible = "nxp,pn532", },
{},
};
MODULE_DEVICE_TABLE(of, pn532_uart_of_match);
static int pn532_uart_probe(struct serdev_device *serdev)
{
struct pn532_uart_phy *pn532;
struct pn533 *priv;
int err;
err = -ENOMEM;
pn532 = kzalloc_obj(*pn532);
if (!pn532)
goto err_exit;
pn532->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN, GFP_KERNEL);
if (!pn532->recv_skb)
goto err_free;
pn532->serdev = serdev;
serdev_device_set_drvdata(serdev, pn532);
serdev_device_set_client_ops(serdev, &pn532_serdev_ops);
err = serdev_device_open(serdev);
if (err) {
dev_err(&serdev->dev, "Unable to open device\n");
goto err_skb;
}
err = serdev_device_set_baudrate(serdev, 115200);
if (err != 115200) {
err = -EINVAL;
goto err_serdev;
}
serdev_device_set_flow_control(serdev, false);
pn532->send_wakeup = PN532_SEND_WAKEUP;
timer_setup(&pn532->cmd_timeout, pn532_cmd_timeout, 0);
priv = pn53x_common_init(PN533_DEVICE_PN532_AUTOPOLL,
PN533_PROTO_REQ_ACK_RESP,
pn532, &uart_phy_ops, NULL,
&pn532->serdev->dev);
if (IS_ERR(priv)) {
err = PTR_ERR(priv);
goto err_serdev;
}
pn532->priv = priv;
err = pn533_finalize_setup(pn532->priv);
if (err)
goto err_clean;
serdev_device_close(serdev);
err = pn53x_register_nfc(priv, PN533_NO_TYPE_B_PROTOCOLS, &serdev->dev);
if (err) {
pn53x_common_clean(pn532->priv);
goto err_skb;
}
return err;
err_clean:
pn53x_common_clean(pn532->priv);
err_serdev:
serdev_device_close(serdev);
err_skb:
kfree_skb(pn532->recv_skb);
err_free:
kfree(pn532);
err_exit:
return err;
}
static void pn532_uart_remove(struct serdev_device *serdev)
{
struct pn532_uart_phy *pn532 = serdev_device_get_drvdata(serdev);
pn53x_unregister_nfc(pn532->priv);
serdev_device_close(serdev);
pn53x_common_clean(pn532->priv);
timer_shutdown_sync(&pn532->cmd_timeout);
kfree_skb(pn532->recv_skb);
kfree(pn532);
}
static struct serdev_device_driver pn532_uart_driver = {
.probe = pn532_uart_probe,
.remove = pn532_uart_remove,
.driver = {
.name = "pn532_uart",
.of_match_table = pn532_uart_of_match,
},
};
module_serdev_device_driver(pn532_uart_driver);
MODULE_AUTHOR("Lars Pöschel <poeschel@lemonage.de>");
MODULE_DESCRIPTION("PN532 UART driver");
MODULE_LICENSE("GPL");
+636
View File
@@ -0,0 +1,636 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for NXP PN533 NFC Chip - USB transport layer
*
* Copyright (C) 2011 Instituto Nokia de Tecnologia
* Copyright (C) 2012-2013 Tieto Poland
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/nfc.h>
#include <linux/netdevice.h>
#include <net/nfc/nfc.h>
#include "pn533.h"
#define VERSION "0.1"
#define PN533_VENDOR_ID 0x4CC
#define PN533_PRODUCT_ID 0x2533
#define SCM_VENDOR_ID 0x4E6
#define SCL3711_PRODUCT_ID 0x5591
#define SONY_VENDOR_ID 0x054c
#define PASORI_PRODUCT_ID 0x02e1
#define ACS_VENDOR_ID 0x072f
#define ACR122U_PRODUCT_ID 0x2200
static const struct usb_device_id pn533_usb_table[] = {
{ USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID),
.driver_info = PN533_DEVICE_STD },
{ USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID),
.driver_info = PN533_DEVICE_STD },
{ USB_DEVICE(SONY_VENDOR_ID, PASORI_PRODUCT_ID),
.driver_info = PN533_DEVICE_PASORI },
{ USB_DEVICE(ACS_VENDOR_ID, ACR122U_PRODUCT_ID),
.driver_info = PN533_DEVICE_ACR122U },
{ }
};
MODULE_DEVICE_TABLE(usb, pn533_usb_table);
struct pn533_usb_phy {
struct usb_device *udev;
struct usb_interface *interface;
struct urb *out_urb;
struct urb *in_urb;
struct urb *ack_urb;
u8 *ack_buffer;
struct pn533 *priv;
};
static void pn533_recv_response(struct urb *urb)
{
struct pn533_usb_phy *phy = urb->context;
struct sk_buff *skb = NULL;
if (!urb->status) {
skb = alloc_skb(urb->actual_length, GFP_ATOMIC);
if (!skb) {
nfc_err(&phy->udev->dev, "failed to alloc memory\n");
} else {
skb_put_data(skb, urb->transfer_buffer,
urb->actual_length);
}
}
pn533_recv_frame(phy->priv, skb, urb->status);
}
static int pn533_submit_urb_for_response(struct pn533_usb_phy *phy, gfp_t flags)
{
phy->in_urb->complete = pn533_recv_response;
return usb_submit_urb(phy->in_urb, flags);
}
static void pn533_recv_ack(struct urb *urb)
{
struct pn533_usb_phy *phy = urb->context;
struct pn533 *priv = phy->priv;
struct pn533_cmd *cmd = priv->cmd;
struct pn533_std_frame *in_frame;
int rc;
cmd->status = urb->status;
switch (urb->status) {
case 0:
break; /* success */
case -ECONNRESET:
case -ENOENT:
dev_dbg(&phy->udev->dev,
"The urb has been stopped (status %d)\n",
urb->status);
goto sched_wq;
case -ESHUTDOWN:
default:
nfc_err(&phy->udev->dev,
"Urb failure (status %d)\n", urb->status);
goto sched_wq;
}
in_frame = phy->in_urb->transfer_buffer;
if (!pn533_rx_frame_is_ack(in_frame)) {
nfc_err(&phy->udev->dev, "Received an invalid ack\n");
cmd->status = -EIO;
goto sched_wq;
}
rc = pn533_submit_urb_for_response(phy, GFP_ATOMIC);
if (rc) {
nfc_err(&phy->udev->dev,
"usb_submit_urb failed with result %d\n", rc);
cmd->status = rc;
goto sched_wq;
}
return;
sched_wq:
queue_work(priv->wq, &priv->cmd_complete_work);
}
static int pn533_submit_urb_for_ack(struct pn533_usb_phy *phy, gfp_t flags)
{
phy->in_urb->complete = pn533_recv_ack;
return usb_submit_urb(phy->in_urb, flags);
}
static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags)
{
struct pn533_usb_phy *phy = dev->phy;
static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
/* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */
if (!phy->ack_buffer) {
phy->ack_buffer = kmemdup(ack, sizeof(ack), flags);
if (!phy->ack_buffer)
return -ENOMEM;
}
phy->ack_urb->transfer_buffer = phy->ack_buffer;
phy->ack_urb->transfer_buffer_length = sizeof(ack);
return usb_submit_urb(phy->ack_urb, flags);
}
struct pn533_out_arg {
struct pn533_usb_phy *phy;
struct completion done;
};
static int pn533_usb_send_frame(struct pn533 *dev,
struct sk_buff *out)
{
struct pn533_usb_phy *phy = dev->phy;
struct pn533_out_arg arg;
void *cntx;
int rc;
if (phy->priv == NULL)
phy->priv = dev;
phy->out_urb->transfer_buffer = out->data;
phy->out_urb->transfer_buffer_length = out->len;
print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
out->data, out->len, false);
arg.phy = phy;
init_completion(&arg.done);
cntx = phy->out_urb->context;
phy->out_urb->context = &arg;
rc = usb_submit_urb(phy->out_urb, GFP_KERNEL);
if (rc)
return rc;
wait_for_completion(&arg.done);
phy->out_urb->context = cntx;
if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
/* request for response for sent packet directly */
rc = pn533_submit_urb_for_response(phy, GFP_KERNEL);
if (rc)
goto error;
} else if (dev->protocol_type == PN533_PROTO_REQ_ACK_RESP) {
/* request for ACK if that's the case */
rc = pn533_submit_urb_for_ack(phy, GFP_KERNEL);
if (rc)
goto error;
}
return 0;
error:
usb_unlink_urb(phy->out_urb);
return rc;
}
static void pn533_usb_abort_cmd(struct pn533 *dev, gfp_t flags)
{
struct pn533_usb_phy *phy = dev->phy;
/* ACR122U does not support any command which aborts last
* issued command i.e. as ACK for standard PN533. Additionally,
* it behaves stange, sending broken or incorrect responses,
* when we cancel urb before the chip will send response.
*/
if (dev->device_type == PN533_DEVICE_ACR122U)
return;
/* An ack will cancel the last issued command */
pn533_usb_send_ack(dev, flags);
/* cancel the urb request */
usb_kill_urb(phy->in_urb);
}
/* ACR122 specific structs and functions */
/* ACS ACR122 pn533 frame definitions */
#define PN533_ACR122_TX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_tx_frame) \
+ 2)
#define PN533_ACR122_TX_FRAME_TAIL_LEN 0
#define PN533_ACR122_RX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_rx_frame) \
+ 2)
#define PN533_ACR122_RX_FRAME_TAIL_LEN 2
#define PN533_ACR122_FRAME_MAX_PAYLOAD_LEN PN533_STD_FRAME_MAX_PAYLOAD_LEN
/* CCID messages types */
#define PN533_ACR122_PC_TO_RDR_ICCPOWERON 0x62
#define PN533_ACR122_PC_TO_RDR_ESCAPE 0x6B
#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83
struct pn533_acr122_ccid_hdr {
u8 type;
u32 datalen;
u8 slot;
u8 seq;
/*
* 3 msg specific bytes or status, error and 1 specific
* byte for reposnse msg
*/
u8 params[3];
} __packed;
struct pn533_acr122_apdu_hdr {
u8 class;
u8 ins;
u8 p1;
u8 p2;
} __packed;
struct pn533_acr122_tx_frame {
struct pn533_acr122_ccid_hdr ccid;
struct pn533_acr122_apdu_hdr apdu;
u8 datalen;
u8 data[]; /* pn533 frame: TFI ... */
} __packed;
struct pn533_acr122_rx_frame {
struct pn533_acr122_ccid_hdr ccid;
u8 data[]; /* pn533 frame : TFI ... */
} __packed;
static void pn533_acr122_tx_frame_init(void *_frame, u8 cmd_code)
{
struct pn533_acr122_tx_frame *frame = _frame;
frame->ccid.type = PN533_ACR122_PC_TO_RDR_ESCAPE;
/* sizeof(apdu_hdr) + sizeof(datalen) */
frame->ccid.datalen = sizeof(frame->apdu) + 1;
frame->ccid.slot = 0;
frame->ccid.seq = 0;
frame->ccid.params[0] = 0;
frame->ccid.params[1] = 0;
frame->ccid.params[2] = 0;
frame->data[0] = PN533_STD_FRAME_DIR_OUT;
frame->data[1] = cmd_code;
frame->datalen = 2; /* data[0] + data[1] */
frame->apdu.class = 0xFF;
frame->apdu.ins = 0;
frame->apdu.p1 = 0;
frame->apdu.p2 = 0;
}
static void pn533_acr122_tx_frame_finish(void *_frame)
{
struct pn533_acr122_tx_frame *frame = _frame;
frame->ccid.datalen += frame->datalen;
}
static void pn533_acr122_tx_update_payload_len(void *_frame, int len)
{
struct pn533_acr122_tx_frame *frame = _frame;
frame->datalen += len;
}
static bool pn533_acr122_is_rx_frame_valid(void *_frame, struct pn533 *dev)
{
struct pn533_acr122_rx_frame *frame = _frame;
if (frame->ccid.type != 0x83)
return false;
if (!frame->ccid.datalen)
return false;
if (frame->data[frame->ccid.datalen - 2] == 0x63)
return false;
return true;
}
static int pn533_acr122_rx_frame_size(void *frame)
{
struct pn533_acr122_rx_frame *f = frame;
/* f->ccid.datalen already includes tail length */
return sizeof(struct pn533_acr122_rx_frame) + f->ccid.datalen;
}
static u8 pn533_acr122_get_cmd_code(void *frame)
{
struct pn533_acr122_rx_frame *f = frame;
return PN533_FRAME_CMD(f);
}
static struct pn533_frame_ops pn533_acr122_frame_ops = {
.tx_frame_init = pn533_acr122_tx_frame_init,
.tx_frame_finish = pn533_acr122_tx_frame_finish,
.tx_update_payload_len = pn533_acr122_tx_update_payload_len,
.tx_header_len = PN533_ACR122_TX_FRAME_HEADER_LEN,
.tx_tail_len = PN533_ACR122_TX_FRAME_TAIL_LEN,
.rx_is_frame_valid = pn533_acr122_is_rx_frame_valid,
.rx_header_len = PN533_ACR122_RX_FRAME_HEADER_LEN,
.rx_tail_len = PN533_ACR122_RX_FRAME_TAIL_LEN,
.rx_frame_size = pn533_acr122_rx_frame_size,
.max_payload_len = PN533_ACR122_FRAME_MAX_PAYLOAD_LEN,
.get_cmd_code = pn533_acr122_get_cmd_code,
};
struct pn533_acr122_poweron_rdr_arg {
int rc;
struct completion done;
};
static void pn533_acr122_poweron_rdr_resp(struct urb *urb)
{
struct pn533_acr122_poweron_rdr_arg *arg = urb->context;
print_hex_dump_debug("ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1,
urb->transfer_buffer, urb->transfer_buffer_length,
false);
arg->rc = urb->status;
complete(&arg->done);
}
static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
{
/* Power on th reader (CCID cmd) */
u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON,
0, 0, 0, 0, 0, 0, 3, 0, 0};
char *buffer;
int transferred;
int rc;
void *cntx;
struct pn533_acr122_poweron_rdr_arg arg;
buffer = kmemdup(cmd, sizeof(cmd), GFP_KERNEL);
if (!buffer)
return -ENOMEM;
init_completion(&arg.done);
cntx = phy->in_urb->context; /* backup context */
phy->in_urb->complete = pn533_acr122_poweron_rdr_resp;
phy->in_urb->context = &arg;
print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1,
cmd, sizeof(cmd), false);
rc = usb_bulk_msg(phy->udev, phy->out_urb->pipe, buffer, sizeof(cmd),
&transferred, 5000);
kfree(buffer);
if (rc || (transferred != sizeof(cmd))) {
nfc_err(&phy->udev->dev,
"Reader power on cmd error %d\n", rc);
return rc ?: -EINVAL;
}
rc = usb_submit_urb(phy->in_urb, GFP_KERNEL);
if (rc) {
nfc_err(&phy->udev->dev,
"Can't submit reader poweron cmd response %d\n", rc);
return rc;
}
wait_for_completion(&arg.done);
phy->in_urb->context = cntx; /* restore context */
return arg.rc;
}
static void pn533_out_complete(struct urb *urb)
{
struct pn533_out_arg *arg = urb->context;
struct pn533_usb_phy *phy = arg->phy;
switch (urb->status) {
case 0:
break; /* success */
case -ECONNRESET:
case -ENOENT:
dev_dbg(&phy->udev->dev,
"The urb has been stopped (status %d)\n",
urb->status);
break;
case -ESHUTDOWN:
default:
nfc_err(&phy->udev->dev,
"Urb failure (status %d)\n",
urb->status);
}
complete(&arg->done);
}
static void pn533_ack_complete(struct urb *urb)
{
struct pn533_usb_phy *phy = urb->context;
switch (urb->status) {
case 0:
break; /* success */
case -ECONNRESET:
case -ENOENT:
dev_dbg(&phy->udev->dev,
"The urb has been stopped (status %d)\n",
urb->status);
break;
case -ESHUTDOWN:
default:
nfc_err(&phy->udev->dev,
"Urb failure (status %d)\n",
urb->status);
}
}
static const struct pn533_phy_ops usb_phy_ops = {
.send_frame = pn533_usb_send_frame,
.send_ack = pn533_usb_send_ack,
.abort_cmd = pn533_usb_abort_cmd,
};
static int pn533_usb_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_endpoint_descriptor *ep_in, *ep_out;
struct pn533 *priv;
struct pn533_usb_phy *phy;
u32 protocols;
enum pn533_protocol_type protocol_type = PN533_PROTO_REQ_ACK_RESP;
struct pn533_frame_ops *fops = NULL;
unsigned char *in_buf;
int in_buf_len = PN533_EXT_FRAME_HEADER_LEN +
PN533_STD_FRAME_MAX_PAYLOAD_LEN +
PN533_STD_FRAME_TAIL_LEN;
int rc;
phy = devm_kzalloc(&interface->dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
in_buf = kzalloc(in_buf_len, GFP_KERNEL);
if (!in_buf)
return -ENOMEM;
phy->udev = interface_to_usbdev(interface);
phy->interface = interface;
rc = usb_find_common_endpoints(interface->cur_altsetting, &ep_in,
&ep_out, NULL, NULL);
if (rc) {
nfc_err(&interface->dev,
"Could not find bulk-in or bulk-out endpoint\n");
goto error;
}
phy->in_urb = usb_alloc_urb(0, GFP_KERNEL);
phy->out_urb = usb_alloc_urb(0, GFP_KERNEL);
phy->ack_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!phy->in_urb || !phy->out_urb || !phy->ack_urb) {
rc = -ENOMEM;
goto error;
}
usb_fill_bulk_urb(phy->in_urb, phy->udev,
usb_rcvbulkpipe(phy->udev, usb_endpoint_num(ep_in)),
in_buf, in_buf_len, NULL, phy);
usb_fill_bulk_urb(phy->out_urb, phy->udev,
usb_sndbulkpipe(phy->udev, usb_endpoint_num(ep_out)),
NULL, 0, pn533_out_complete, phy);
usb_fill_bulk_urb(phy->ack_urb, phy->udev,
usb_sndbulkpipe(phy->udev, usb_endpoint_num(ep_out)),
NULL, 0, pn533_ack_complete, phy);
switch (id->driver_info) {
case PN533_DEVICE_STD:
protocols = PN533_ALL_PROTOCOLS;
break;
case PN533_DEVICE_PASORI:
protocols = PN533_NO_TYPE_B_PROTOCOLS;
break;
case PN533_DEVICE_ACR122U:
protocols = PN533_NO_TYPE_B_PROTOCOLS;
fops = &pn533_acr122_frame_ops;
protocol_type = PN533_PROTO_REQ_RESP;
rc = pn533_acr122_poweron_rdr(phy);
if (rc < 0) {
nfc_err(&interface->dev,
"Couldn't poweron the reader (error %d)\n", rc);
goto error;
}
break;
default:
nfc_err(&interface->dev, "Unknown device type %lu\n",
id->driver_info);
rc = -EINVAL;
goto error;
}
priv = pn53x_common_init(id->driver_info, protocol_type,
phy, &usb_phy_ops, fops,
&phy->udev->dev);
if (IS_ERR(priv)) {
rc = PTR_ERR(priv);
goto error;
}
phy->priv = priv;
rc = pn533_finalize_setup(priv);
if (rc)
goto err_clean;
usb_set_intfdata(interface, phy);
rc = pn53x_register_nfc(priv, protocols, &interface->dev);
if (rc)
goto err_clean;
return 0;
err_clean:
pn53x_common_clean(priv);
error:
usb_kill_urb(phy->in_urb);
usb_kill_urb(phy->out_urb);
usb_kill_urb(phy->ack_urb);
usb_free_urb(phy->in_urb);
usb_free_urb(phy->out_urb);
usb_free_urb(phy->ack_urb);
kfree(in_buf);
kfree(phy->ack_buffer);
return rc;
}
static void pn533_usb_disconnect(struct usb_interface *interface)
{
struct pn533_usb_phy *phy = usb_get_intfdata(interface);
if (!phy)
return;
pn53x_unregister_nfc(phy->priv);
pn53x_common_clean(phy->priv);
usb_set_intfdata(interface, NULL);
usb_kill_urb(phy->in_urb);
usb_kill_urb(phy->out_urb);
usb_kill_urb(phy->ack_urb);
kfree(phy->in_urb->transfer_buffer);
usb_free_urb(phy->in_urb);
usb_free_urb(phy->out_urb);
usb_free_urb(phy->ack_urb);
kfree(phy->ack_buffer);
nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n");
}
static struct usb_driver pn533_usb_driver = {
.name = "pn533_usb",
.probe = pn533_usb_probe,
.disconnect = pn533_usb_disconnect,
.id_table = pn533_usb_table,
};
module_usb_driver(pn533_usb_driver);
MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
MODULE_AUTHOR("Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
MODULE_AUTHOR("Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>");
MODULE_DESCRIPTION("PN533 USB driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");