diff --git a/Documentation/devicetree/bindings/net/nfc/pn533-i2c.txt b/Documentation/devicetree/bindings/net/nfc/pn533-i2c.txt new file mode 100644 index 000000000000..1aea822d4530 --- /dev/null +++ b/Documentation/devicetree/bindings/net/nfc/pn533-i2c.txt @@ -0,0 +1,31 @@ +* NXP Semiconductors PN532 NFC Controller + +Required properties: +- compatible: Should be "nxp,pn532-i2c" or "nxp,pn533-i2c". +- clock-frequency: I²C work frequency. +- reg: address on the bus +- interrupt-parent: phandle for the interrupt gpio controller +- interrupts: GPIO interrupt to which the chip is connected + +Optional SoC Specific Properties: +- pinctrl-names: Contains only one value - "default". +- pintctrl-0: Specifies the pin control groups used for this controller. + +Example (for ARM-based BeagleBone with PN532 on I2C2): + +&i2c2 { + + status = "okay"; + + pn532: pn532@24 { + + compatible = "nxp,pn532-i2c"; + + reg = <0x24>; + clock-frequency = <400000>; + + interrupt-parent = <&gpio1>; + interrupts = <17 IRQ_TYPE_EDGE_FALLING>; + + }; +}; diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 7437c9dfd8fc..ea8321a483f9 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig @@ -5,16 +5,6 @@ menu "Near Field Communication (NFC) devices" depends on NFC -config NFC_PN533 - tristate "NXP PN533 USB driver" - depends on USB - help - NXP PN533 USB driver. - This driver provides support for NFC NXP PN533 devices. - - Say Y here to compile support for PN533 devices into the - kernel or say M to compile it as module (pn533). - config NFC_WILINK tristate "Texas Instruments NFC WiLink driver" depends on TI_ST && NFC_NCI @@ -70,6 +60,7 @@ config NFC_PORT100 source "drivers/nfc/fdp/Kconfig" source "drivers/nfc/pn544/Kconfig" +source "drivers/nfc/pn533/Kconfig" source "drivers/nfc/microread/Kconfig" source "drivers/nfc/nfcmrvl/Kconfig" source "drivers/nfc/st21nfca/Kconfig" diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index 0a99e67daa10..bab8ef06ae35 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_NFC_FDP) += fdp/ obj-$(CONFIG_NFC_PN544) += pn544/ obj-$(CONFIG_NFC_MICROREAD) += microread/ -obj-$(CONFIG_NFC_PN533) += pn533.o +obj-$(CONFIG_NFC_PN533) += pn533/ obj-$(CONFIG_NFC_WILINK) += nfcwilink.o obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o obj-$(CONFIG_NFC_SIM) += nfcsim.o diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c index ccb07a1b153d..e44a7a2f4061 100644 --- a/drivers/nfc/fdp/fdp.c +++ b/drivers/nfc/fdp/fdp.c @@ -102,7 +102,8 @@ static int fdp_nci_create_conn(struct nci_dev *ndev) if (r) return r; - return nci_get_conn_info_by_id(ndev, 0); + return nci_get_conn_info_by_dest_type_params(ndev, + FDP_PATCH_CONN_DEST, NULL); } static inline int fdp_nci_get_versions(struct nci_dev *ndev) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 11520f472f98..36099e557730 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -418,7 +418,6 @@ MODULE_DEVICE_TABLE(acpi, acpi_id); static struct i2c_driver nxp_nci_i2c_driver = { .driver = { .name = NXP_NCI_I2C_DRIVER_NAME, - .owner = THIS_MODULE, .acpi_match_table = ACPI_PTR(acpi_id), .of_match_table = of_match_ptr(of_nxp_nci_i2c_match), }, diff --git a/drivers/nfc/pn533/Kconfig b/drivers/nfc/pn533/Kconfig new file mode 100644 index 000000000000..d94122dd30e4 --- /dev/null +++ b/drivers/nfc/pn533/Kconfig @@ -0,0 +1,27 @@ +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. diff --git a/drivers/nfc/pn533/Makefile b/drivers/nfc/pn533/Makefile new file mode 100644 index 000000000000..51d24c622fcb --- /dev/null +++ b/drivers/nfc/pn533/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for PN533 NFC driver +# +pn533_usb-objs = usb.o +pn533_i2c-objs = i2c.o + +obj-$(CONFIG_NFC_PN533) += pn533.o +obj-$(CONFIG_NFC_PN533_USB) += pn533_usb.o +obj-$(CONFIG_NFC_PN533_I2C) += pn533_i2c.o diff --git a/drivers/nfc/pn533/i2c.c b/drivers/nfc/pn533/i2c.c new file mode 100644 index 000000000000..1dc89248e58e --- /dev/null +++ b/drivers/nfc/pn533/i2c.c @@ -0,0 +1,281 @@ +/* + * 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 + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; + u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; + /* spec 6.2.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ + int rc; + + rc = i2c_master_send(client, ack, 6); + + return rc; +} + +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 i2c_client *client; + struct sk_buff *skb = NULL; + int r; + + if (!phy || irq != phy->i2c_dev->irq) { + WARN_ON_ONCE(1); + return IRQ_NONE; + } + + client = phy->i2c_dev; + dev_dbg(&client->dev, "IRQ\n"); + + 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 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, + const struct i2c_device_id *id) +{ + struct pn533_i2c_phy *phy; + struct pn533 *priv; + int r = 0; + + dev_dbg(&client->dev, "%s\n", __func__); + dev_dbg(&client->dev, "IRQ: %d\n", client->irq); + + 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); + + 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"); + + priv = pn533_register_device(PN533_DEVICE_PN532, + PN533_NO_TYPE_B_PROTOCOLS, + PN533_PROTO_REQ_ACK_RESP, + phy, &i2c_phy_ops, NULL, + &phy->i2c_dev->dev, + &client->dev); + + if (IS_ERR(priv)) { + r = PTR_ERR(priv); + goto err_register; + } + + phy->priv = priv; + + return 0; + +err_register: + free_irq(client->irq, phy); + + return r; +} + +static int pn533_i2c_remove(struct i2c_client *client) +{ + struct pn533_i2c_phy *phy = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "%s\n", __func__); + + pn533_unregister_device(phy->priv); + + free_irq(client->irq, phy); + + return 0; +} + +static const struct of_device_id of_pn533_i2c_match[] = { + { .compatible = "nxp,pn533-i2c", }, + { .compatible = "nxp,pn532-i2c", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_pn533_i2c_match); + +static struct i2c_device_id pn533_i2c_id_table[] = { + { PN533_I2C_DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pn533_i2c_id_table); + +static struct i2c_driver pn533_i2c_driver = { + .driver = { + .name = PN533_I2C_DRIVER_NAME, + .owner = THIS_MODULE, + .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 "); +MODULE_DESCRIPTION("PN533 I2C driver ver " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533/pn533.c similarity index 67% rename from drivers/nfc/pn533.c rename to drivers/nfc/pn533/pn533.c index bb3d5ea9869c..d9c55830b2b2 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533/pn533.c @@ -1,4 +1,6 @@ /* + * Driver for NXP PN533 NFC Chip - core functions + * * Copyright (C) 2011 Instituto Nokia de Tecnologia * Copyright (C) 2012-2013 Tieto Poland * @@ -20,137 +22,18 @@ #include #include #include -#include #include #include #include +#include "pn533.h" -#define VERSION "0.2" - -#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 - -#define PN533_DEVICE_STD 0x1 -#define PN533_DEVICE_PASORI 0x2 -#define PN533_DEVICE_ACR122U 0x3 - -#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) - -static const struct usb_device_id pn533_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_table); +#define VERSION "0.3" /* How much time we spend listening for initiators */ #define PN533_LISTEN_TIME 2 /* Delay between each poll frame (ms) */ #define PN533_POLL_INTERVAL 10 -/* 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_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 - -#define PN533_STD_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2), - Postamble (1) */ -#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 - -/* 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 - -/* PN533 Commands */ -#define PN533_FRAME_CMD(f) (f->data[1]) - -#define PN533_CMD_GET_FIRMWARE_VERSION 0x02 -#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_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 - -struct pn533; - -typedef int (*pn533_send_async_complete_t) (struct pn533 *dev, void *arg, - struct sk_buff *resp); - /* structs for pn533 commands */ /* PN533_CMD_GET_FIRMWARE_VERSION */ @@ -220,19 +103,6 @@ union pn533_cmd_poll_initdata { } __packed felica; }; -/* 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_poll_modulations { struct { u8 maxtg; @@ -336,219 +206,6 @@ struct pn533_cmd_jump_dep_response { #define PN533_INIT_TARGET_RESP_ACTIVE 0x1 #define PN533_INIT_TARGET_RESP_DEP 0x4 -enum pn533_protocol_type { - PN533_PROTO_REQ_ACK_RESP = 0, - PN533_PROTO_REQ_RESP -}; - -struct pn533 { - struct usb_device *udev; - struct usb_interface *interface; - struct nfc_dev *nfc_dev; - u32 device_type; - enum pn533_protocol_type protocol_type; - - struct urb *out_urb; - struct urb *in_urb; - - 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 pn533_cmd { - struct list_head queue; - u8 code; - int status; - struct sk_buff *req; - struct sk_buff *resp; - int resp_len; - pn533_send_async_complete_t complete_cb; - void *complete_cb_context; -}; - -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_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); - 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_acr122_ccid_hdr { - u8 type; - u32 datalen; - u8 slot; - u8 seq; - u8 params[3]; /* 3 msg specific bytes or status, error and 1 specific - byte for reposnse msg */ - u8 data[]; /* payload */ -} __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; - frame->ccid.datalen = sizeof(frame->apdu) + 1; /* sizeof(apdu_hdr) + - sizeof(datalen) */ - 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, -}; - /* The rule: value(high byte) + value(low byte) + checksum = 0 */ static inline u8 pn533_ext_checksum(u16 value) { @@ -642,8 +299,10 @@ static bool pn533_std_rx_frame_is_valid(void *_frame, struct pn533 *dev) return true; } -static bool pn533_std_rx_frame_is_ack(struct pn533_std_frame *frame) +bool pn533_rx_frame_is_ack(void *_frame) { + struct pn533_std_frame *frame = _frame; + if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF)) return false; @@ -652,6 +311,7 @@ static bool pn533_std_rx_frame_is_ack(struct pn533_std_frame *frame) return true; } +EXPORT_SYMBOL_GPL(pn533_rx_frame_is_ack); static inline int pn533_std_rx_frame_size(void *frame) { @@ -680,6 +340,14 @@ static u8 pn533_std_get_cmd_code(void *frame) return PN533_FRAME_CMD(f); } +bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame) +{ + return (dev->ops->get_cmd_code(frame) == + PN533_CMD_RESPONSE(dev->cmd->code)); +} +EXPORT_SYMBOL_GPL(pn533_rx_frame_is_cmd_response); + + static struct pn533_frame_ops pn533_std_frame_ops = { .tx_frame_init = pn533_std_tx_frame_init, .tx_frame_finish = pn533_std_tx_frame_finish, @@ -696,172 +364,6 @@ static struct pn533_frame_ops pn533_std_frame_ops = { .get_cmd_code = pn533_std_get_cmd_code, }; -static bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame) -{ - return (dev->ops->get_cmd_code(frame) == - PN533_CMD_RESPONSE(dev->cmd->code)); -} - -static void pn533_recv_response(struct urb *urb) -{ - struct pn533 *dev = urb->context; - struct pn533_cmd *cmd = dev->cmd; - u8 *in_frame; - - cmd->status = urb->status; - - switch (urb->status) { - case 0: - break; /* success */ - case -ECONNRESET: - case -ENOENT: - dev_dbg(&dev->interface->dev, - "The urb has been canceled (status %d)\n", - urb->status); - goto sched_wq; - case -ESHUTDOWN: - default: - nfc_err(&dev->interface->dev, - "Urb failure (status %d)\n", urb->status); - goto sched_wq; - } - - in_frame = dev->in_urb->transfer_buffer; - - dev_dbg(&dev->interface->dev, "Received a frame\n"); - print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame, - dev->ops->rx_frame_size(in_frame), false); - - if (!dev->ops->rx_is_frame_valid(in_frame, dev)) { - nfc_err(&dev->interface->dev, "Received an invalid frame\n"); - cmd->status = -EIO; - goto sched_wq; - } - - if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) { - nfc_err(&dev->interface->dev, - "It it not the response to the last command\n"); - cmd->status = -EIO; - goto sched_wq; - } - -sched_wq: - queue_work(dev->wq, &dev->cmd_complete_work); -} - -static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags) -{ - dev->in_urb->complete = pn533_recv_response; - - return usb_submit_urb(dev->in_urb, flags); -} - -static void pn533_recv_ack(struct urb *urb) -{ - struct pn533 *dev = urb->context; - struct pn533_cmd *cmd = dev->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(&dev->interface->dev, - "The urb has been stopped (status %d)\n", - urb->status); - goto sched_wq; - case -ESHUTDOWN: - default: - nfc_err(&dev->interface->dev, - "Urb failure (status %d)\n", urb->status); - goto sched_wq; - } - - in_frame = dev->in_urb->transfer_buffer; - - if (!pn533_std_rx_frame_is_ack(in_frame)) { - nfc_err(&dev->interface->dev, "Received an invalid ack\n"); - cmd->status = -EIO; - goto sched_wq; - } - - rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); - if (rc) { - nfc_err(&dev->interface->dev, - "usb_submit_urb failed with result %d\n", rc); - cmd->status = rc; - goto sched_wq; - } - - return; - -sched_wq: - queue_work(dev->wq, &dev->cmd_complete_work); -} - -static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags) -{ - dev->in_urb->complete = pn533_recv_ack; - - return usb_submit_urb(dev->in_urb, flags); -} - -static int pn533_send_ack(struct pn533 *dev, gfp_t flags) -{ - u8 ack[PN533_STD_FRAME_ACK_SIZE] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; - /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ - int rc; - - dev->out_urb->transfer_buffer = ack; - dev->out_urb->transfer_buffer_length = sizeof(ack); - rc = usb_submit_urb(dev->out_urb, flags); - - return rc; -} - -static int __pn533_send_frame_async(struct pn533 *dev, - struct sk_buff *out, - struct sk_buff *in, - int in_len) -{ - int rc; - - dev->out_urb->transfer_buffer = out->data; - dev->out_urb->transfer_buffer_length = out->len; - - dev->in_urb->transfer_buffer = in->data; - dev->in_urb->transfer_buffer_length = in_len; - - print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1, - out->data, out->len, false); - - rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); - if (rc) - return rc; - - if (dev->protocol_type == PN533_PROTO_REQ_RESP) { - /* request for response for sent packet directly */ - rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); - 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(dev, GFP_KERNEL); - if (rc) - goto error; - } - - return 0; - -error: - usb_unlink_urb(dev->out_urb); - return rc; -} - static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code, struct sk_buff *skb) { @@ -897,7 +399,6 @@ static int pn533_send_async_complete(struct pn533 *dev) goto done; } - skb_put(resp, dev->ops->rx_frame_size(resp->data)); skb_pull(resp, dev->ops->rx_header_len); skb_trim(resp, resp->len - dev->ops->rx_tail_len); @@ -910,15 +411,14 @@ done: } static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, - struct sk_buff *req, struct sk_buff *resp, - int resp_len, + struct sk_buff *req, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { struct pn533_cmd *cmd; int rc = 0; - dev_dbg(&dev->interface->dev, "Sending command 0x%x\n", cmd_code); + dev_dbg(dev->dev, "Sending command 0x%x\n", cmd_code); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) @@ -926,8 +426,6 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, cmd->code = cmd_code; cmd->req = req; - cmd->resp = resp; - cmd->resp_len = resp_len; cmd->complete_cb = complete_cb; cmd->complete_cb_context = complete_cb_context; @@ -936,7 +434,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, mutex_lock(&dev->cmd_lock); if (!dev->cmd_pending) { - rc = __pn533_send_frame_async(dev, req, resp, resp_len); + rc = dev->phy_ops->send_frame(dev, req); if (rc) goto error; @@ -945,7 +443,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, goto unlock; } - dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x\n", + dev_dbg(dev->dev, "%s Queueing command 0x%x\n", __func__, cmd_code); INIT_LIST_HEAD(&cmd->queue); @@ -965,20 +463,10 @@ static int pn533_send_data_async(struct pn533 *dev, u8 cmd_code, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { - struct sk_buff *resp; int rc; - int resp_len = dev->ops->rx_header_len + - dev->ops->max_payload_len + - dev->ops->rx_tail_len; - resp = nfc_alloc_recv_skb(resp_len, GFP_KERNEL); - if (!resp) - return -ENOMEM; - - rc = __pn533_send_async(dev, cmd_code, req, resp, resp_len, complete_cb, + rc = __pn533_send_async(dev, cmd_code, req, complete_cb, complete_cb_context); - if (rc) - dev_kfree_skb(resp); return rc; } @@ -988,20 +476,10 @@ static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { - struct sk_buff *resp; int rc; - int resp_len = dev->ops->rx_header_len + - dev->ops->max_payload_len + - dev->ops->rx_tail_len; - resp = alloc_skb(resp_len, GFP_KERNEL); - if (!resp) - return -ENOMEM; - - rc = __pn533_send_async(dev, cmd_code, req, resp, resp_len, complete_cb, + rc = __pn533_send_async(dev, cmd_code, req, complete_cb, complete_cb_context); - if (rc) - dev_kfree_skb(resp); return rc; } @@ -1019,39 +497,25 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { - struct sk_buff *resp; struct pn533_cmd *cmd; int rc; - int resp_len = dev->ops->rx_header_len + - dev->ops->max_payload_len + - dev->ops->rx_tail_len; - - resp = alloc_skb(resp_len, GFP_KERNEL); - if (!resp) - return -ENOMEM; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - dev_kfree_skb(resp); + if (!cmd) return -ENOMEM; - } cmd->code = cmd_code; cmd->req = req; - cmd->resp = resp; - cmd->resp_len = resp_len; cmd->complete_cb = complete_cb; cmd->complete_cb_context = complete_cb_context; pn533_build_cmd_frame(dev, cmd_code, req); - rc = __pn533_send_frame_async(dev, req, resp, resp_len); - if (rc < 0) { - dev_kfree_skb(resp); + rc = dev->phy_ops->send_frame(dev, req); + if (rc < 0) kfree(cmd); - } else { + else dev->cmd = cmd; - } return rc; } @@ -1086,10 +550,9 @@ static void pn533_wq_cmd(struct work_struct *work) mutex_unlock(&dev->cmd_lock); - rc = __pn533_send_frame_async(dev, cmd->req, cmd->resp, cmd->resp_len); + rc = dev->phy_ops->send_frame(dev, cmd->req); if (rc < 0) { dev_kfree_skb(cmd->req); - dev_kfree_skb(cmd->resp); kfree(cmd); return; } @@ -1121,7 +584,7 @@ static int pn533_send_sync_complete(struct pn533 *dev, void *_arg, * 1. negative in case of error during TX path -> req should be freed * * 2. negative in case of error during RX path -> req should not be freed - * as it's been already freed at the begining of RX path by + * as it's been already freed at the beginning of RX path by * async_complete_cb. * * 3. valid pointer in case of succesfult RX path @@ -1129,7 +592,7 @@ static int pn533_send_sync_complete(struct pn533 *dev, void *_arg, * A caller has to check a return value with IS_ERR macro. If the test pass, * the returned pointer is valid. * - * */ + */ static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code, struct sk_buff *req) { @@ -1150,43 +613,6 @@ static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code, return arg.resp; } -static void pn533_send_complete(struct urb *urb) -{ - struct pn533 *dev = urb->context; - - switch (urb->status) { - case 0: - break; /* success */ - case -ECONNRESET: - case -ENOENT: - dev_dbg(&dev->interface->dev, - "The urb has been stopped (status %d)\n", - urb->status); - break; - case -ESHUTDOWN: - default: - nfc_err(&dev->interface->dev, "Urb failure (status %d)\n", - urb->status); - } -} - -static void pn533_abort_cmd(struct pn533 *dev, gfp_t flags) -{ - /* 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_send_ack(dev, flags); - - /* cancel the urb request */ - usb_kill_urb(dev->in_urb); -} - static struct sk_buff *pn533_alloc_skb(struct pn533 *dev, unsigned int size) { struct sk_buff *skb; @@ -1233,8 +659,10 @@ static bool pn533_target_type_a_is_valid(struct pn533_target_type_a *type_a, if (target_data_len < sizeof(struct pn533_target_type_a)) return false; - /* The lenght check of nfcid[] and ats[] are not being performed because - the values are not being used */ + /* + * The length check of nfcid[] and ats[] are not being performed because + * the values are not being used + */ /* Requirement 4.6.3.3 from NFC Forum Digital Spec */ ssd = PN533_TYPE_A_SENS_RES_SSD(type_a->sens_res); @@ -1437,13 +865,14 @@ static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data, return 0; } +static void pn533_poll_reset_mod_list(struct pn533 *dev); static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, int tgdata_len) { struct nfc_target nfc_tgt; int rc; - dev_dbg(&dev->interface->dev, "%s: modulation=%d\n", + dev_dbg(dev->dev, "%s: modulation=%d\n", __func__, dev->poll_mod_curr); if (tg != 1) @@ -1466,7 +895,7 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len); break; default: - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Unknown current poll modulation\n"); return -EPROTO; } @@ -1475,17 +904,18 @@ static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, return rc; if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "The Tg found doesn't have the desired protocol\n"); return -EAGAIN; } - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "Target found - supported protocols: 0x%x\n", nfc_tgt.supported_protocols); dev->tgt_available_prots = nfc_tgt.supported_protocols; + pn533_poll_reset_mod_list(dev); nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1); return 0; @@ -1540,7 +970,8 @@ static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) int rc, tgdata_len; /* Toggle the DEP polling */ - dev->poll_dep = 1; + if (dev->poll_protocols & NFC_PROTO_NFC_DEP_MASK) + dev->poll_dep = 1; nbtg = resp->data[0]; tg = resp->data[1]; @@ -1551,10 +982,8 @@ static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) rc = pn533_target_found(dev, tg, tgdata, tgdata_len); /* We must stop the poll after a valid target found */ - if (rc == 0) { - pn533_poll_reset_mod_list(dev); + if (rc == 0) return 0; - } } return -EAGAIN; @@ -1577,8 +1006,10 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) 0x0, 0x0, 0x0, 0x40}; /* SEL_RES for DEP */ - unsigned int skb_len = 36 + /* mode (1), mifare (6), - felica (18), nfcid3 (10), gb_len (1) */ + unsigned int skb_len = 36 + /* + * mode (1), mifare (6), + * felica (18), nfcid3 (10), gb_len (1) + */ gbytes_len + 1; /* len Tk*/ @@ -1614,8 +1045,6 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) return skb; } -#define PN533_CMD_DATAEXCH_HEAD_LEN 1 -#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 static void pn533_wq_tm_mi_recv(struct work_struct *work); static struct sk_buff *pn533_build_response(struct pn533 *dev); @@ -1626,7 +1055,7 @@ static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, u8 status, ret, mi; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) { skb_queue_purge(&dev->resp_q); @@ -1675,7 +1104,7 @@ static void pn533_wq_tm_mi_recv(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 0); if (!skb) @@ -1689,8 +1118,6 @@ static void pn533_wq_tm_mi_recv(struct work_struct *work) if (rc < 0) dev_kfree_skb(skb); - - return; } static int pn533_tm_send_complete(struct pn533 *dev, void *arg, @@ -1701,7 +1128,7 @@ static void pn533_wq_tm_mi_send(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); /* Grab the first skb in the queue */ skb = skb_dequeue(&dev->fragment_skb); @@ -1723,13 +1150,13 @@ static void pn533_wq_tm_mi_send(struct work_struct *work) if (rc == 0) /* success */ return; - dev_err(&dev->interface->dev, + dev_err(dev->dev, "Error %d when trying to perform set meta data_exchange", rc); dev_kfree_skb(skb); error: - pn533_send_ack(dev, GFP_KERNEL); + dev->phy_ops->send_ack(dev, GFP_KERNEL); queue_work(dev->wq, &dev->cmd_work); } @@ -1739,7 +1166,7 @@ static void pn533_wq_tg_get_data(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 0); if (!skb) @@ -1750,8 +1177,6 @@ static void pn533_wq_tg_get_data(struct work_struct *work) if (rc < 0) dev_kfree_skb(skb); - - return; } #define ATR_REQ_GB_OFFSET 17 @@ -1761,7 +1186,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) size_t gb_len; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (resp->len < ATR_REQ_GB_OFFSET + 1) return -EINVAL; @@ -1769,7 +1194,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) mode = resp->data[0]; cmd = &resp->data[1]; - dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", + dev_dbg(dev->dev, "Target mode 0x%x len %d\n", mode, resp->len); if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) == @@ -1785,7 +1210,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, comm_mode, gb, gb_len); if (rc < 0) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error when signaling target activation\n"); return rc; } @@ -1800,7 +1225,7 @@ static void pn533_listen_mode_timer(unsigned long data) { struct pn533 *dev = (struct pn533 *)data; - dev_dbg(&dev->interface->dev, "Listen mode timeout\n"); + dev_dbg(dev->dev, "Listen mode timeout\n"); dev->cancel_listen = 1; @@ -1815,12 +1240,12 @@ static int pn533_rf_complete(struct pn533 *dev, void *arg, { int rc = 0; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); - nfc_err(&dev->interface->dev, "RF setting error %d\n", rc); + nfc_err(dev->dev, "RF setting error %d\n", rc); return rc; } @@ -1838,7 +1263,7 @@ static void pn533_wq_rf(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, 2); if (!skb) @@ -1851,10 +1276,8 @@ static void pn533_wq_rf(struct work_struct *work) pn533_rf_complete, NULL); if (rc < 0) { dev_kfree_skb(skb); - nfc_err(&dev->interface->dev, "RF setting error %d\n", rc); + nfc_err(dev->dev, "RF setting error %d\n", rc); } - - return; } static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, @@ -1879,7 +1302,7 @@ static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, return 0; } - dev_dbg(&dev->interface->dev, "Creating new target"); + dev_dbg(dev->dev, "Creating new target"); nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; nfc_target.nfcid1_len = 10; @@ -1917,7 +1340,7 @@ static int pn533_poll_dep(struct nfc_dev *nfc_dev) u8 *next, nfcid3[NFC_NFCID3_MAXSIZE]; u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - dev_dbg(&dev->interface->dev, "%s", __func__); + dev_dbg(dev->dev, "%s", __func__); if (!dev->gb) { dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len); @@ -1974,21 +1397,20 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, struct pn533_poll_modulations *cur_mod; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); - nfc_err(&dev->interface->dev, "%s Poll complete error %d\n", + nfc_err(dev->dev, "%s Poll complete error %d\n", __func__, rc); if (rc == -ENOENT) { if (dev->poll_mod_count != 0) return rc; - else - goto stop_poll; + goto stop_poll; } else if (rc < 0) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error %d when running poll\n", rc); goto stop_poll; } @@ -2008,7 +1430,7 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, goto done; if (!dev->poll_mod_count) { - dev_dbg(&dev->interface->dev, "Polling has been stopped\n"); + dev_dbg(dev->dev, "Polling has been stopped\n"); goto done; } @@ -2021,7 +1443,7 @@ done: return rc; stop_poll: - nfc_err(&dev->interface->dev, "Polling operation has been stopped\n"); + nfc_err(dev->dev, "Polling operation has been stopped\n"); pn533_poll_reset_mod_list(dev); dev->poll_protocols = 0; @@ -2051,10 +1473,10 @@ static int pn533_send_poll_frame(struct pn533 *dev) mod = dev->poll_mod_active[dev->poll_mod_curr]; - dev_dbg(&dev->interface->dev, "%s mod len %d\n", + dev_dbg(dev->dev, "%s mod len %d\n", __func__, mod->len); - if (dev->poll_dep) { + if ((dev->poll_protocols & NFC_PROTO_NFC_DEP_MASK) && dev->poll_dep) { dev->poll_dep = 0; return pn533_poll_dep(dev->nfc_dev); } @@ -2068,7 +1490,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) } if (!skb) { - nfc_err(&dev->interface->dev, "Failed to allocate skb\n"); + nfc_err(dev->dev, "Failed to allocate skb\n"); return -ENOMEM; } @@ -2076,7 +1498,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) NULL); if (rc < 0) { dev_kfree_skb(skb); - nfc_err(&dev->interface->dev, "Polling loop error %d\n", rc); + nfc_err(dev->dev, "Polling loop error %d\n", rc); } return rc; @@ -2090,13 +1512,13 @@ static void pn533_wq_poll(struct work_struct *work) cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "%s cancel_listen %d modulation len %d\n", __func__, dev->cancel_listen, cur_mod->len); if (dev->cancel_listen == 1) { dev->cancel_listen = 0; - pn533_abort_cmd(dev, GFP_ATOMIC); + dev->phy_ops->abort_cmd(dev, GFP_ATOMIC); } rc = pn533_send_poll_frame(dev); @@ -2105,8 +1527,6 @@ static void pn533_wq_poll(struct work_struct *work) if (cur_mod->len == 0 && dev->poll_mod_count > 1) mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ); - - return; } static int pn533_start_poll(struct nfc_dev *nfc_dev, @@ -2117,18 +1537,18 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, u8 rand_mod; int rc; - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "%s: im protocols 0x%x tm protocols 0x%x\n", __func__, im_protocols, tm_protocols); if (dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Cannot poll with a target already activated\n"); return -EBUSY; } if (dev->tgt_mode) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Cannot poll while already being activated\n"); return -EBUSY; } @@ -2166,12 +1586,12 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) del_timer(&dev->listen_timer); if (!dev->poll_mod_count) { - dev_dbg(&dev->interface->dev, + dev_dbg(dev->dev, "Polling operation was not running\n"); return; } - pn533_abort_cmd(dev, GFP_KERNEL); + dev->phy_ops->abort_cmd(dev, GFP_KERNEL); flush_delayed_work(&dev->poll_work); pn533_poll_reset_mod_list(dev); } @@ -2184,7 +1604,7 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) struct sk_buff *skb; struct sk_buff *resp; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/ if (!skb) @@ -2200,7 +1620,7 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) rsp = (struct pn533_cmd_activate_response *)resp->data; rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Target activation failed (error 0x%x)\n", rc); dev_kfree_skb(resp); return -EIO; @@ -2220,28 +1640,28 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, struct pn533 *dev = nfc_get_drvdata(nfc_dev); int rc; - dev_dbg(&dev->interface->dev, "%s: protocol=%u\n", __func__, protocol); + dev_dbg(dev->dev, "%s: protocol=%u\n", __func__, protocol); if (dev->poll_mod_count) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Cannot activate while polling\n"); return -EBUSY; } if (dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "There is already an active target\n"); return -EBUSY; } if (!dev->tgt_available_prots) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "There is no available target to activate\n"); return -EINVAL; } if (!(dev->tgt_available_prots & (1 << protocol))) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Target doesn't support requested proto %u\n", protocol); return -EINVAL; @@ -2250,7 +1670,7 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, if (protocol == NFC_PROTO_NFC_DEP) { rc = pn533_activate_target_nfcdep(dev); if (rc) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Activating target with DEP failed %d\n", rc); return rc; } @@ -2262,18 +1682,41 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, return 0; } +static int pn533_deactivate_target_complete(struct pn533 *dev, void *arg, + struct sk_buff *resp) +{ + int rc = 0; + + dev_dbg(dev->dev, "%s\n", __func__); + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + + nfc_err(dev->dev, "Target release error %d\n", rc); + + return rc; + } + + rc = resp->data[0] & PN533_CMD_RET_MASK; + if (rc != PN533_CMD_RET_SUCCESS) + nfc_err(dev->dev, + "Error 0x%x when releasing the target\n", rc); + + dev_kfree_skb(resp); + return rc; +} + static void pn533_deactivate_target(struct nfc_dev *nfc_dev, struct nfc_target *target, u8 mode) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); struct sk_buff *skb; - struct sk_buff *resp; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, "There is no active target\n"); + nfc_err(dev->dev, "There is no active target\n"); return; } @@ -2286,17 +1729,12 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, *skb_put(skb, 1) = 1; /* TG*/ - resp = pn533_send_cmd_sync(dev, PN533_CMD_IN_RELEASE, skb); - if (IS_ERR(resp)) - return; - - rc = resp->data[0] & PN533_CMD_RET_MASK; - if (rc != PN533_CMD_RET_SUCCESS) - nfc_err(&dev->interface->dev, - "Error 0x%x when releasing the target\n", rc); - - dev_kfree_skb(resp); - return; + rc = pn533_send_cmd_async(dev, PN533_CMD_IN_RELEASE, skb, + pn533_deactivate_target_complete, NULL); + if (rc < 0) { + dev_kfree_skb(skb); + nfc_err(dev->dev, "Target release error %d\n", rc); + } } @@ -2315,7 +1753,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (dev->tgt_available_prots && !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "The target does not support DEP\n"); rc = -EINVAL; goto error; @@ -2325,7 +1763,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Bringing DEP link up failed (error 0x%x)\n", rc); goto error; } @@ -2333,7 +1771,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (!dev->tgt_available_prots) { struct nfc_target nfc_target; - dev_dbg(&dev->interface->dev, "Creating new target\n"); + dev_dbg(dev->dev, "Creating new target\n"); nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; nfc_target.nfcid1_len = 10; @@ -2371,16 +1809,16 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE]; u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (dev->poll_mod_count) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Cannot bring the DEP link up while polling\n"); return -EBUSY; } if (dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "There is already an active target\n"); return -EBUSY; } @@ -2451,12 +1889,12 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); pn533_poll_reset_mod_list(dev); if (dev->tgt_mode || dev->tgt_active_prot) - pn533_abort_cmd(dev, GFP_KERNEL); + dev->phy_ops->abort_cmd(dev, GFP_KERNEL); dev->tgt_active_prot = 0; dev->tgt_mode = 0; @@ -2476,7 +1914,7 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) struct sk_buff *skb, *tmp, *t; unsigned int skb_len = 0, tmp_len = 0; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (skb_queue_empty(&dev->resp_q)) return NULL; @@ -2489,7 +1927,7 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) skb_queue_walk_safe(&dev->resp_q, tmp, t) skb_len += tmp->len; - dev_dbg(&dev->interface->dev, "%s total length %d\n", + dev_dbg(dev->dev, "%s total length %d\n", __func__, skb_len); skb = alloc_skb(skb_len, GFP_KERNEL); @@ -2517,7 +1955,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, int rc = 0; u8 status, ret, mi; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) { rc = PTR_ERR(resp); @@ -2531,7 +1969,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, skb_pull(resp, sizeof(status)); if (ret != PN533_CMD_RET_SUCCESS) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Exchanging data failed (error 0x%x)\n", ret); rc = -EIO; goto error; @@ -2572,6 +2010,51 @@ _error: return rc; } +/* + * Receive an incoming pn533 frame. skb contains only header and payload. + * If skb == NULL, it is a notification that the link below is dead. + */ +void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status) +{ + if (!dev->cmd) + goto sched_wq; + + dev->cmd->status = status; + + if (status != 0) { + dev_dbg(dev->dev, "%s: Error received: %d\n", __func__, status); + goto sched_wq; + } + + if (skb == NULL) { + pr_err("NULL Frame -> link is dead\n"); + goto sched_wq; + } + + if (pn533_rx_frame_is_ack(skb->data)) { + dev_dbg(dev->dev, "%s: Received ACK frame\n", __func__); + dev_kfree_skb(skb); + return; + } + + print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, skb->data, + dev->ops->rx_frame_size(skb->data), false); + + if (!dev->ops->rx_is_frame_valid(skb->data, dev)) { + nfc_err(dev->dev, "Received an invalid frame\n"); + dev->cmd->status = -EIO; + } else if (!pn533_rx_frame_is_cmd_response(dev, skb->data)) { + nfc_err(dev->dev, "It it not the response to the last command\n"); + dev->cmd->status = -EIO; + } + + dev->cmd->resp = skb; + +sched_wq: + queue_work(dev->wq, &dev->cmd_complete_work); +} +EXPORT_SYMBOL(pn533_recv_frame); + /* Split the Tx skb into small chunks */ static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb) { @@ -2627,10 +2110,10 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, struct pn533_data_exchange_arg *arg = NULL; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (!dev->tgt_active_prot) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Can't exchange data if there is no active target\n"); rc = -EINVAL; goto error; @@ -2694,7 +2177,7 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg, { u8 status; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); if (IS_ERR(resp)) return PTR_ERR(resp); @@ -2726,7 +2209,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) struct pn533 *dev = nfc_get_drvdata(nfc_dev); int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); /* let's split in multiple chunks if size's too big */ if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { @@ -2764,7 +2247,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN); if (!skb) @@ -2796,14 +2279,14 @@ static void pn533_wq_mi_recv(struct work_struct *work) if (rc == 0) /* success */ return; - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error %d when trying to perform data_exchange\n", rc); dev_kfree_skb(skb); kfree(dev->cmd_complete_mi_arg); error: - pn533_send_ack(dev, GFP_KERNEL); + dev->phy_ops->send_ack(dev, GFP_KERNEL); queue_work(dev->wq, &dev->cmd_work); } @@ -2813,7 +2296,7 @@ static void pn533_wq_mi_send(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); /* Grab the first skb in the queue */ skb = skb_dequeue(&dev->fragment_skb); @@ -2840,7 +2323,8 @@ static void pn533_wq_mi_send(struct work_struct *work) default: /* Still some fragments? */ - rc = pn533_send_cmd_direct_async(dev,PN533_CMD_IN_DATA_EXCHANGE, + rc = pn533_send_cmd_direct_async(dev, + PN533_CMD_IN_DATA_EXCHANGE, skb, pn533_data_exchange_complete, dev->cmd_complete_dep_arg); @@ -2851,14 +2335,14 @@ static void pn533_wq_mi_send(struct work_struct *work) if (rc == 0) /* success */ return; - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error %d when trying to perform data_exchange\n", rc); dev_kfree_skb(skb); kfree(dev->cmd_complete_dep_arg); error: - pn533_send_ack(dev, GFP_KERNEL); + dev->phy_ops->send_ack(dev, GFP_KERNEL); queue_work(dev->wq, &dev->cmd_work); } @@ -2869,7 +2353,7 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, struct sk_buff *resp; int skb_len; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ @@ -2916,7 +2400,7 @@ static int pn533_pasori_fw_reset(struct pn533 *dev) struct sk_buff *skb; struct sk_buff *resp; - dev_dbg(&dev->interface->dev, "%s\n", __func__); + dev_dbg(dev->dev, "%s\n", __func__); skb = pn533_alloc_skb(dev, sizeof(u8)); if (!skb) @@ -2933,71 +2417,6 @@ static int pn533_pasori_fw_reset(struct pn533 *dev) return 0; } -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; - - dev_dbg(&urb->dev->dev, "%s\n", __func__); - - 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 *dev) -{ - /* Power on th reader (CCID cmd) */ - u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON, - 0, 0, 0, 0, 0, 0, 3, 0, 0}; - u8 buf[255]; - int rc; - void *cntx; - struct pn533_acr122_poweron_rdr_arg arg; - - dev_dbg(&dev->interface->dev, "%s\n", __func__); - - init_completion(&arg.done); - cntx = dev->in_urb->context; /* backup context */ - - dev->in_urb->transfer_buffer = buf; - dev->in_urb->transfer_buffer_length = 255; - dev->in_urb->complete = pn533_acr122_poweron_rdr_resp; - dev->in_urb->context = &arg; - - dev->out_urb->transfer_buffer = cmd; - dev->out_urb->transfer_buffer_length = sizeof(cmd); - - print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, - cmd, sizeof(cmd), false); - - rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); - if (rc) { - nfc_err(&dev->interface->dev, - "Reader power on cmd error %d\n", rc); - return rc; - } - - rc = usb_submit_urb(dev->in_urb, GFP_KERNEL); - if (rc) { - nfc_err(&dev->interface->dev, - "Can't submit reader poweron cmd response %d\n", rc); - return rc; - } - - wait_for_completion(&arg.done); - dev->in_urb->context = cntx; /* restore context */ - - return arg.rc; -} - static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); @@ -3009,15 +2428,44 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD, (u8 *)&rf_field, 1); if (rc) { - nfc_err(&dev->interface->dev, "Error on setting RF field\n"); + nfc_err(dev->dev, "Error on setting RF field\n"); return rc; } return rc; } +static int pn532_sam_configuration(struct nfc_dev *nfc_dev) +{ + struct pn533 *dev = nfc_get_drvdata(nfc_dev); + struct sk_buff *skb; + struct sk_buff *resp; + + skb = pn533_alloc_skb(dev, 1); + if (!skb) + return -ENOMEM; + + *skb_put(skb, 1) = 0x01; + + resp = pn533_send_cmd_sync(dev, PN533_CMD_SAM_CONFIGURATION, skb); + if (IS_ERR(resp)) + return PTR_ERR(resp); + + dev_kfree_skb(resp); + return 0; +} + static int pn533_dev_up(struct nfc_dev *nfc_dev) { + struct pn533 *dev = nfc_get_drvdata(nfc_dev); + + if (dev->device_type == PN533_DEVICE_PN532) { + int rc = pn532_sam_configuration(nfc_dev); + + if (rc) + return rc; + } + return pn533_rf_field(nfc_dev, 1); } @@ -3050,6 +2498,7 @@ static int pn533_setup(struct pn533 *dev) case PN533_DEVICE_STD: case PN533_DEVICE_PASORI: case PN533_DEVICE_ACR122U: + case PN533_DEVICE_PN532: max_retries.mx_rty_atr = 0x2; max_retries.mx_rty_psl = 0x1; max_retries.mx_rty_passive_act = @@ -3062,7 +2511,7 @@ static int pn533_setup(struct pn533 *dev) break; default: - nfc_err(&dev->interface->dev, "Unknown device type %d\n", + nfc_err(dev->dev, "Unknown device type %d\n", dev->device_type); return -EINVAL; } @@ -3070,7 +2519,7 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES, (u8 *)&max_retries, sizeof(max_retries)); if (rc) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error on setting MAX_RETRIES config\n"); return rc; } @@ -3079,12 +2528,13 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, (u8 *)&timing, sizeof(timing)); if (rc) { - nfc_err(&dev->interface->dev, "Error on setting RF timings\n"); + nfc_err(dev->dev, "Error on setting RF timings\n"); return rc; } switch (dev->device_type) { case PN533_DEVICE_STD: + case PN533_DEVICE_PN532: break; case PN533_DEVICE_PASORI: @@ -3093,7 +2543,7 @@ static int pn533_setup(struct pn533 *dev) rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI, pasori_cfg, 3); if (rc) { - nfc_err(&dev->interface->dev, + nfc_err(dev->dev, "Error while settings PASORI config\n"); return rc; } @@ -3106,208 +2556,130 @@ static int pn533_setup(struct pn533 *dev) return 0; } -static int pn533_probe(struct usb_interface *interface, - const struct usb_device_id *id) +struct pn533 *pn533_register_device(u32 device_type, + u32 protocols, + enum pn533_protocol_type protocol_type, + void *phy, + struct pn533_phy_ops *phy_ops, + struct pn533_frame_ops *fops, + struct device *dev, + struct device *parent) { struct pn533_fw_version fw_ver; - struct pn533 *dev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int in_endpoint = 0; - int out_endpoint = 0; + struct pn533 *priv; int rc = -ENOMEM; - int i; - u32 protocols; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return ERR_PTR(-ENOMEM); - dev->udev = usb_get_dev(interface_to_usbdev(interface)); - dev->interface = interface; - mutex_init(&dev->cmd_lock); + priv->phy = phy; + priv->phy_ops = phy_ops; + priv->dev = dev; + if (fops != NULL) + priv->ops = fops; + else + priv->ops = &pn533_std_frame_ops; - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; + priv->protocol_type = protocol_type; + priv->device_type = device_type; - if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) - in_endpoint = endpoint->bEndpointAddress; + mutex_init(&priv->cmd_lock); - if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) - out_endpoint = endpoint->bEndpointAddress; - } - - if (!in_endpoint || !out_endpoint) { - nfc_err(&interface->dev, - "Could not find bulk-in or bulk-out endpoint\n"); - rc = -ENODEV; - goto error; - } - - dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); - dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); - - if (!dev->in_urb || !dev->out_urb) + INIT_WORK(&priv->cmd_work, pn533_wq_cmd); + INIT_WORK(&priv->cmd_complete_work, pn533_wq_cmd_complete); + INIT_WORK(&priv->mi_rx_work, pn533_wq_mi_recv); + INIT_WORK(&priv->mi_tx_work, pn533_wq_mi_send); + INIT_WORK(&priv->tg_work, pn533_wq_tg_get_data); + INIT_WORK(&priv->mi_tm_rx_work, pn533_wq_tm_mi_recv); + INIT_WORK(&priv->mi_tm_tx_work, pn533_wq_tm_mi_send); + INIT_DELAYED_WORK(&priv->poll_work, pn533_wq_poll); + INIT_WORK(&priv->rf_work, pn533_wq_rf); + priv->wq = alloc_ordered_workqueue("pn533", 0); + if (priv->wq == NULL) goto error; - usb_fill_bulk_urb(dev->in_urb, dev->udev, - usb_rcvbulkpipe(dev->udev, in_endpoint), - NULL, 0, NULL, dev); - usb_fill_bulk_urb(dev->out_urb, dev->udev, - usb_sndbulkpipe(dev->udev, out_endpoint), - NULL, 0, pn533_send_complete, dev); + init_timer(&priv->listen_timer); + priv->listen_timer.data = (unsigned long) priv; + priv->listen_timer.function = pn533_listen_mode_timer; - INIT_WORK(&dev->cmd_work, pn533_wq_cmd); - INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete); - INIT_WORK(&dev->mi_rx_work, pn533_wq_mi_recv); - INIT_WORK(&dev->mi_tx_work, pn533_wq_mi_send); - INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); - INIT_WORK(&dev->mi_tm_rx_work, pn533_wq_tm_mi_recv); - INIT_WORK(&dev->mi_tm_tx_work, pn533_wq_tm_mi_send); - INIT_DELAYED_WORK(&dev->poll_work, pn533_wq_poll); - INIT_WORK(&dev->rf_work, pn533_wq_rf); - dev->wq = alloc_ordered_workqueue("pn533", 0); - if (dev->wq == NULL) - goto error; + skb_queue_head_init(&priv->resp_q); + skb_queue_head_init(&priv->fragment_skb); - init_timer(&dev->listen_timer); - dev->listen_timer.data = (unsigned long) dev; - dev->listen_timer.function = pn533_listen_mode_timer; - - skb_queue_head_init(&dev->resp_q); - skb_queue_head_init(&dev->fragment_skb); - - INIT_LIST_HEAD(&dev->cmd_queue); - - usb_set_intfdata(interface, dev); - - dev->ops = &pn533_std_frame_ops; - - dev->protocol_type = PN533_PROTO_REQ_ACK_RESP; - dev->device_type = id->driver_info; - switch (dev->device_type) { - 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; - dev->ops = &pn533_acr122_frame_ops; - dev->protocol_type = PN533_PROTO_REQ_RESP, - - rc = pn533_acr122_poweron_rdr(dev); - if (rc < 0) { - nfc_err(&dev->interface->dev, - "Couldn't poweron the reader (error %d)\n", rc); - goto destroy_wq; - } - break; - - default: - nfc_err(&dev->interface->dev, "Unknown device type %d\n", - dev->device_type); - rc = -EINVAL; - goto destroy_wq; - } + INIT_LIST_HEAD(&priv->cmd_queue); memset(&fw_ver, 0, sizeof(fw_ver)); - rc = pn533_get_firmware_version(dev, &fw_ver); + rc = pn533_get_firmware_version(priv, &fw_ver); if (rc < 0) goto destroy_wq; - nfc_info(&dev->interface->dev, - "NXP PN5%02X firmware ver %d.%d now attached\n", + nfc_info(dev, "NXP PN5%02X firmware ver %d.%d now attached\n", fw_ver.ic, fw_ver.ver, fw_ver.rev); - dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, - dev->ops->tx_header_len + + priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, + priv->ops->tx_header_len + PN533_CMD_DATAEXCH_HEAD_LEN, - dev->ops->tx_tail_len); - if (!dev->nfc_dev) { + priv->ops->tx_tail_len); + if (!priv->nfc_dev) { rc = -ENOMEM; goto destroy_wq; } - nfc_set_parent_dev(dev->nfc_dev, &interface->dev); - nfc_set_drvdata(dev->nfc_dev, dev); + nfc_set_parent_dev(priv->nfc_dev, parent); + nfc_set_drvdata(priv->nfc_dev, priv); - rc = nfc_register_device(dev->nfc_dev); + rc = nfc_register_device(priv->nfc_dev); if (rc) goto free_nfc_dev; - rc = pn533_setup(dev); + rc = pn533_setup(priv); if (rc) goto unregister_nfc_dev; - return 0; + return priv; unregister_nfc_dev: - nfc_unregister_device(dev->nfc_dev); + nfc_unregister_device(priv->nfc_dev); free_nfc_dev: - nfc_free_device(dev->nfc_dev); + nfc_free_device(priv->nfc_dev); destroy_wq: - destroy_workqueue(dev->wq); + destroy_workqueue(priv->wq); error: - usb_free_urb(dev->in_urb); - usb_free_urb(dev->out_urb); - usb_put_dev(dev->udev); - kfree(dev); - return rc; + kfree(priv); + return ERR_PTR(rc); } +EXPORT_SYMBOL_GPL(pn533_register_device); -static void pn533_disconnect(struct usb_interface *interface) +void pn533_unregister_device(struct pn533 *priv) { - struct pn533 *dev; struct pn533_cmd *cmd, *n; - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); + nfc_unregister_device(priv->nfc_dev); + nfc_free_device(priv->nfc_dev); - nfc_unregister_device(dev->nfc_dev); - nfc_free_device(dev->nfc_dev); + flush_delayed_work(&priv->poll_work); + destroy_workqueue(priv->wq); - usb_kill_urb(dev->in_urb); - usb_kill_urb(dev->out_urb); + skb_queue_purge(&priv->resp_q); - flush_delayed_work(&dev->poll_work); - destroy_workqueue(dev->wq); + del_timer(&priv->listen_timer); - skb_queue_purge(&dev->resp_q); - - del_timer(&dev->listen_timer); - - list_for_each_entry_safe(cmd, n, &dev->cmd_queue, queue) { + list_for_each_entry_safe(cmd, n, &priv->cmd_queue, queue) { list_del(&cmd->queue); kfree(cmd); } - usb_free_urb(dev->in_urb); - usb_free_urb(dev->out_urb); - kfree(dev); - - nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); + kfree(priv); } +EXPORT_SYMBOL_GPL(pn533_unregister_device); -static struct usb_driver pn533_driver = { - .name = "pn533", - .probe = pn533_probe, - .disconnect = pn533_disconnect, - .id_table = pn533_table, -}; - -module_usb_driver(pn533_driver); MODULE_AUTHOR("Lauro Ramos Venancio "); MODULE_AUTHOR("Aloisio Almeida Jr "); MODULE_AUTHOR("Waldemar Rymarkiewicz "); -MODULE_DESCRIPTION("PN533 usb driver ver " VERSION); +MODULE_DESCRIPTION("PN533 driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/nfc/pn533/pn533.h b/drivers/nfc/pn533/pn533.h new file mode 100644 index 000000000000..553c7d171fd1 --- /dev/null +++ b/drivers/nfc/pn533/pn533.h @@ -0,0 +1,238 @@ +/* + * Driver for NXP PN533 NFC Chip + * + * Copyright (C) 2011 Instituto Nokia de Tecnologia + * Copyright (C) 2012-2013 Tieto Poland + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 . + */ + +#define PN533_DEVICE_STD 0x1 +#define PN533_DEVICE_PASORI 0x2 +#define PN533_DEVICE_ACR122U 0x3 +#define PN533_DEVICE_PN532 0x4 + +#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 +#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_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 + + +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; + 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); +}; + + +struct pn533 *pn533_register_device(u32 device_type, + u32 protocols, + enum pn533_protocol_type protocol_type, + void *phy, + struct pn533_phy_ops *phy_ops, + struct pn533_frame_ops *fops, + struct device *dev, + struct device *parent); + +void pn533_unregister_device(struct pn533 *priv); +void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status); + +bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame); +bool pn533_rx_frame_is_ack(void *_frame); diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c new file mode 100644 index 000000000000..8ca060324b6a --- /dev/null +++ b/drivers/nfc/pn533/usb.c @@ -0,0 +1,597 @@ +/* + * Driver for NXP PN533 NFC Chip - USB transport layer + * + * Copyright (C) 2011 Instituto Nokia de Tecnologia + * Copyright (C) 2012-2013 Tieto Poland + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#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 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_KERNEL); + if (!skb) { + nfc_err(&phy->udev->dev, "failed to alloc memory\n"); + } else { + memcpy(skb_put(skb, urb->actual_length), + 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; + u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; + /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ + int rc; + + phy->out_urb->transfer_buffer = ack; + phy->out_urb->transfer_buffer_length = sizeof(ack); + rc = usb_submit_urb(phy->out_urb, flags); + + return rc; +} + +static int pn533_usb_send_frame(struct pn533 *dev, + struct sk_buff *out) +{ + struct pn533_usb_phy *phy = dev->phy; + 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); + + rc = usb_submit_urb(phy->out_urb, GFP_KERNEL); + if (rc) + return rc; + + if (dev->protocol_type == PN533_PROTO_REQ_RESP) { + /* request for response for sent packet directly */ + rc = pn533_submit_urb_for_response(phy, GFP_ATOMIC); + 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 fucntions */ + +/* 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]; + u8 data[]; /* payload */ +} __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; + + dev_dbg(&urb->dev->dev, "%s\n", __func__); + + 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}; + int rc; + void *cntx; + struct pn533_acr122_poweron_rdr_arg arg; + + dev_dbg(&phy->udev->dev, "%s\n", __func__); + + 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; + + phy->out_urb->transfer_buffer = cmd; + phy->out_urb->transfer_buffer_length = sizeof(cmd); + + print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, + cmd, sizeof(cmd), false); + + rc = usb_submit_urb(phy->out_urb, GFP_KERNEL); + if (rc) { + nfc_err(&phy->udev->dev, + "Reader power on cmd error %d\n", rc); + return rc; + } + + 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_send_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 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 pn533 *priv; + struct pn533_usb_phy *phy; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int in_endpoint = 0; + int out_endpoint = 0; + int rc = -ENOMEM; + int i; + 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; + + phy = devm_kzalloc(&interface->dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + in_buf = kzalloc(in_buf_len, GFP_KERNEL); + if (!in_buf) { + rc = -ENOMEM; + goto out_free_phy; + } + + phy->udev = usb_get_dev(interface_to_usbdev(interface)); + phy->interface = interface; + + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) + in_endpoint = endpoint->bEndpointAddress; + + if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) + out_endpoint = endpoint->bEndpointAddress; + } + + if (!in_endpoint || !out_endpoint) { + nfc_err(&interface->dev, + "Could not find bulk-in or bulk-out endpoint\n"); + rc = -ENODEV; + goto error; + } + + phy->in_urb = usb_alloc_urb(0, GFP_KERNEL); + phy->out_urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!phy->in_urb || !phy->out_urb) + goto error; + + usb_fill_bulk_urb(phy->in_urb, phy->udev, + usb_rcvbulkpipe(phy->udev, in_endpoint), + in_buf, in_buf_len, NULL, phy); + + usb_fill_bulk_urb(phy->out_urb, phy->udev, + usb_sndbulkpipe(phy->udev, out_endpoint), + NULL, 0, pn533_send_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 = pn533_register_device(id->driver_info, protocols, protocol_type, + phy, &usb_phy_ops, fops, + &phy->udev->dev, &interface->dev); + + if (IS_ERR(priv)) { + rc = PTR_ERR(priv); + goto error; + } + + phy->priv = priv; + + usb_set_intfdata(interface, phy); + + return 0; + +error: + usb_free_urb(phy->in_urb); + usb_free_urb(phy->out_urb); + usb_put_dev(phy->udev); + kfree(in_buf); +out_free_phy: + kfree(phy); + return rc; +} + +static void pn533_usb_disconnect(struct usb_interface *interface) +{ + struct pn533_usb_phy *phy = usb_get_intfdata(interface); + + if (!phy) + return; + + pn533_unregister_device(phy->priv); + + usb_set_intfdata(interface, NULL); + + usb_kill_urb(phy->in_urb); + usb_kill_urb(phy->out_urb); + + kfree(phy->in_urb->transfer_buffer); + usb_free_urb(phy->in_urb); + usb_free_urb(phy->out_urb); + + 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 "); +MODULE_AUTHOR("Aloisio Almeida Jr "); +MODULE_AUTHOR("Waldemar Rymarkiewicz "); +MODULE_DESCRIPTION("PN533 USB driver ver " VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index 45d0e667d7ae..f837c39a8017 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -1106,7 +1106,6 @@ MODULE_DEVICE_TABLE(of, of_pn544_i2c_match); static struct i2c_driver pn544_hci_i2c_driver = { .driver = { .name = PN544_HCI_I2C_DRIVER_NAME, - .owner = THIS_MODULE, .of_match_table = of_match_ptr(of_pn544_i2c_match), .acpi_match_table = ACPI_PTR(pn544_hci_i2c_acpi_match), }, diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c index 8a56b5c6e4c4..9dfae0efa922 100644 --- a/drivers/nfc/st-nci/i2c.c +++ b/drivers/nfc/st-nci/i2c.c @@ -42,7 +42,7 @@ #define ST_NCI_I2C_DRIVER_NAME "st_nci_i2c" -#define ST_NCI_GPIO_NAME_RESET "clf_reset" +#define ST_NCI_GPIO_NAME_RESET "reset" struct st_nci_i2c_phy { struct i2c_client *i2c_dev; @@ -211,19 +211,9 @@ static struct nfc_phy_ops i2c_phy_ops = { static int st_nci_i2c_acpi_request_resources(struct i2c_client *client) { struct st_nci_i2c_phy *phy = i2c_get_clientdata(client); - const struct acpi_device_id *id; struct gpio_desc *gpiod_reset; - struct device *dev; - - if (!client) - return -EINVAL; - - dev = &client->dev; - - /* Match the struct device against a given list of ACPI IDs */ - id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!id) - return -ENODEV; + struct device *dev = &client->dev; + u8 tmp; /* Get RESET GPIO from ACPI */ gpiod_reset = devm_gpiod_get_index(dev, ST_NCI_GPIO_NAME_RESET, 1, @@ -237,10 +227,18 @@ static int st_nci_i2c_acpi_request_resources(struct i2c_client *client) phy->irq_polarity = irq_get_trigger_type(client->irq); - phy->se_status.is_ese_present = - device_property_present(dev, "ese-present"); - phy->se_status.is_uicc_present = - device_property_present(dev, "uicc-present"); + phy->se_status.is_ese_present = false; + phy->se_status.is_uicc_present = false; + + if (device_property_present(dev, "ese-present")) { + device_property_read_u8(dev, "ese-present", &tmp); + phy->se_status.is_ese_present = tmp; + } + + if (device_property_present(dev, "uicc-present")) { + device_property_read_u8(dev, "uicc-present", &tmp); + phy->se_status.is_uicc_present = tmp; + } return 0; } @@ -416,7 +414,6 @@ MODULE_DEVICE_TABLE(of, of_st_nci_i2c_match); static struct i2c_driver st_nci_i2c_driver = { .driver = { - .owner = THIS_MODULE, .name = ST_NCI_I2C_DRIVER_NAME, .of_match_table = of_match_ptr(of_st_nci_i2c_match), .acpi_match_table = ACPI_PTR(st_nci_i2c_acpi_match), diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c index a53e5df803eb..56f2112e0cd8 100644 --- a/drivers/nfc/st-nci/se.c +++ b/drivers/nfc/st-nci/se.c @@ -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, @@ -222,7 +220,7 @@ int st_nci_hci_load_session(struct nci_dev *ndev) */ dm_pipe_info = (struct st_nci_pipe_info *)skb_pipe_info->data; if (dm_pipe_info->dst_gate_id == ST_NCI_APDU_READER_GATE && - dm_pipe_info->src_host_id != ST_NCI_ESE_HOST_ID) { + dm_pipe_info->src_host_id == ST_NCI_UICC_HOST_ID) { pr_err("Unexpected apdu_reader pipe on host %x\n", dm_pipe_info->src_host_id); kfree_skb(skb_pipe_info); @@ -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); @@ -520,7 +515,7 @@ int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx) * Same for eSE. */ r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_ON); - if (r == ST_NCI_HCI_HOST_ID_ESE) { + if (r == ST_NCI_ESE_HOST_ID) { st_nci_se_get_atr(ndev); r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE, ST_NCI_EVT_SE_SOFT_RESET, NULL, 0); @@ -600,10 +595,12 @@ static int st_nci_hci_network_init(struct nci_dev *ndev) * HCI will be used here only for proprietary commands. */ if (test_bit(ST_NCI_FACTORY_MODE, &info->flags)) - r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id, + r = nci_nfcee_mode_set(ndev, + ndev->hci_dev->conn_info->dest_params->id, NCI_NFCEE_DISABLE); else - r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id, + r = nci_nfcee_mode_set(ndev, + ndev->hci_dev->conn_info->dest_params->id, NCI_NFCEE_ENABLE); free_dest_params: @@ -629,17 +626,10 @@ int st_nci_discover_se(struct nci_dev *ndev) if (test_bit(ST_NCI_FACTORY_MODE, &info->flags)) return 0; - if (info->se_info.se_status->is_ese_present && - info->se_info.se_status->is_uicc_present) { + if (info->se_info.se_status->is_uicc_present) white_list[wl_size++] = ST_NCI_UICC_HOST_ID; + if (info->se_info.se_status->is_ese_present) white_list[wl_size++] = ST_NCI_ESE_HOST_ID; - } else if (!info->se_info.se_status->is_ese_present && - info->se_info.se_status->is_uicc_present) { - white_list[wl_size++] = ST_NCI_UICC_HOST_ID; - } else if (info->se_info.se_status->is_ese_present && - !info->se_info.se_status->is_uicc_present) { - white_list[wl_size++] = ST_NCI_ESE_HOST_ID; - } if (wl_size) { r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE, @@ -672,7 +662,7 @@ int st_nci_se_io(struct nci_dev *ndev, u32 se_idx, pr_debug("\n"); switch (se_idx) { - case ST_NCI_HCI_HOST_ID_ESE: + case ST_NCI_ESE_HOST_ID: info->se_info.cb = cb; info->se_info.cb_context = cb_context; mod_timer(&info->se_info.bwi_timer, jiffies + diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c index 821dfa950fa8..89e341eba3eb 100644 --- a/drivers/nfc/st-nci/spi.c +++ b/drivers/nfc/st-nci/spi.c @@ -43,7 +43,7 @@ #define ST_NCI_SPI_DRIVER_NAME "st_nci_spi" -#define ST_NCI_GPIO_NAME_RESET "clf_reset" +#define ST_NCI_GPIO_NAME_RESET "reset" struct st_nci_spi_phy { struct spi_device *spi_dev; @@ -226,19 +226,9 @@ static struct nfc_phy_ops spi_phy_ops = { static int st_nci_spi_acpi_request_resources(struct spi_device *spi_dev) { struct st_nci_spi_phy *phy = spi_get_drvdata(spi_dev); - const struct acpi_device_id *id; struct gpio_desc *gpiod_reset; - struct device *dev; - - if (!spi_dev) - return -EINVAL; - - dev = &spi_dev->dev; - - /* Match the struct device against a given list of ACPI IDs */ - id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!id) - return -ENODEV; + struct device *dev = &spi_dev->dev; + u8 tmp; /* Get RESET GPIO from ACPI */ gpiod_reset = devm_gpiod_get_index(dev, ST_NCI_GPIO_NAME_RESET, 1, @@ -252,10 +242,18 @@ static int st_nci_spi_acpi_request_resources(struct spi_device *spi_dev) phy->irq_polarity = irq_get_trigger_type(spi_dev->irq); - phy->se_status.is_ese_present = - device_property_present(dev, "ese-present"); - phy->se_status.is_uicc_present = - device_property_present(dev, "uicc-present"); + phy->se_status.is_ese_present = false; + phy->se_status.is_uicc_present = false; + + if (device_property_present(dev, "ese-present")) { + device_property_read_u8(dev, "ese-present", &tmp); + tmp = phy->se_status.is_ese_present; + } + + if (device_property_present(dev, "uicc-present")) { + device_property_read_u8(dev, "uicc-present", &tmp); + tmp = phy->se_status.is_uicc_present; + } return 0; } diff --git a/drivers/nfc/st-nci/st-nci.h b/drivers/nfc/st-nci/st-nci.h index 8b9f77b0249c..afaf138b7e1b 100644 --- a/drivers/nfc/st-nci/st-nci.h +++ b/drivers/nfc/st-nci/st-nci.h @@ -32,7 +32,6 @@ * sequence of at most 32 characters. */ #define ST_NCI_ESE_MAX_LENGTH 33 -#define ST_NCI_HCI_HOST_ID_ESE 0xc0 #define ST_NCI_DEVICE_MGNT_GATE 0x01 @@ -93,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 @@ -116,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, @@ -124,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); @@ -156,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_ */ diff --git a/drivers/nfc/st-nci/vendor_cmds.c b/drivers/nfc/st-nci/vendor_cmds.c index b5debce4ae0b..1a836c77c268 100644 --- a/drivers/nfc/st-nci/vendor_cmds.c +++ b/drivers/nfc/st-nci/vendor_cmds.c @@ -333,62 +333,28 @@ exit: 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, - size_t data_len) +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_nfcc_loopback(ndev, data, data_len, &skb); + if (r < 0) + return r; - 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; - } - - 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)); } diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c index dd8b150fbffa..dacb9166081b 100644 --- a/drivers/nfc/st21nfca/core.c +++ b/drivers/nfc/st21nfca/core.c @@ -176,7 +176,7 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev) */ info = (struct st21nfca_pipe_info *) skb_pipe_info->data; if (info->dst_gate_id == ST21NFCA_APDU_READER_GATE && - info->src_host_id != ST21NFCA_ESE_HOST_ID) { + info->src_host_id == NFC_HCI_UICC_HOST_ID) { pr_err("Unexpected apdu_reader pipe on host %x\n", info->src_host_id); kfree_skb(skb_pipe_info); @@ -262,17 +262,10 @@ static int st21nfca_hci_ready(struct nfc_hci_dev *hdev) int wl_size = 0; int r; - if (info->se_status->is_ese_present && - info->se_status->is_uicc_present) { + if (info->se_status->is_uicc_present) white_list[wl_size++] = NFC_HCI_UICC_HOST_ID; + if (info->se_status->is_ese_present) white_list[wl_size++] = ST21NFCA_ESE_HOST_ID; - } else if (!info->se_status->is_ese_present && - info->se_status->is_uicc_present) { - white_list[wl_size++] = NFC_HCI_UICC_HOST_ID; - } else if (info->se_status->is_ese_present && - !info->se_status->is_uicc_present) { - white_list[wl_size++] = ST21NFCA_ESE_HOST_ID; - } if (wl_size) { r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c index 1f44a151d206..5a82f553906c 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c @@ -62,7 +62,7 @@ #define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c" -#define ST21NFCA_GPIO_NAME_EN "clf_enable" +#define ST21NFCA_GPIO_NAME_EN "enable" struct st21nfca_i2c_phy { struct i2c_client *i2c_dev; @@ -507,34 +507,34 @@ static struct nfc_phy_ops i2c_phy_ops = { static int st21nfca_hci_i2c_acpi_request_resources(struct i2c_client *client) { struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client); - const struct acpi_device_id *id; struct gpio_desc *gpiod_ena; - struct device *dev; - - if (!client) - return -EINVAL; - - dev = &client->dev; - - /* Match the struct device against a given list of ACPI IDs */ - id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!id) - return -ENODEV; + struct device *dev = &client->dev; + u8 tmp; /* Get EN GPIO from ACPI */ gpiod_ena = devm_gpiod_get_index(dev, ST21NFCA_GPIO_NAME_EN, 1, GPIOD_OUT_LOW); - if (!IS_ERR(gpiod_ena)) - phy->gpio_ena = desc_to_gpio(gpiod_ena); + if (!IS_ERR(gpiod_ena)) { + nfc_err(dev, "Unable to get ENABLE GPIO\n"); + return -ENODEV; + } phy->gpio_ena = desc_to_gpio(gpiod_ena); phy->irq_polarity = irq_get_trigger_type(client->irq); - phy->se_status.is_ese_present = - device_property_present(dev, "ese-present"); - phy->se_status.is_uicc_present = - device_property_present(dev, "uicc-present"); + phy->se_status.is_ese_present = false; + phy->se_status.is_uicc_present = false; + + if (device_property_present(dev, "ese-present")) { + device_property_read_u8(dev, "ese-present", &tmp); + phy->se_status.is_ese_present = tmp; + } + + if (device_property_present(dev, "uicc-present")) { + device_property_read_u8(dev, "uicc-present", &tmp); + phy->se_status.is_uicc_present = tmp; + } return 0; } @@ -721,7 +721,6 @@ MODULE_DEVICE_TABLE(of, of_st21nfca_i2c_match); static struct i2c_driver st21nfca_hci_i2c_driver = { .driver = { - .owner = THIS_MODULE, .name = ST21NFCA_HCI_I2C_DRIVER_NAME, .of_match_table = of_match_ptr(of_st21nfca_i2c_match), .acpi_match_table = ACPI_PTR(st21nfca_hci_i2c_acpi_match), diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c index bd56a16e4007..3a98563d4a12 100644 --- a/drivers/nfc/st21nfca/se.c +++ b/drivers/nfc/st21nfca/se.c @@ -32,8 +32,6 @@ #define ST21NFCA_EVT_CONNECTIVITY 0x10 #define ST21NFCA_EVT_TRANSACTION 0x12 -#define ST21NFCA_ESE_HOST_ID 0xc0 - #define ST21NFCA_SE_TO_HOT_PLUG 1000 /* Connectivity pipe only */ #define ST21NFCA_SE_COUNT_PIPE_UICC 0x01 diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 57ce24fb0047..87499b6b35d6 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -109,7 +109,13 @@ struct nci_ops { struct nci_conn_info { struct list_head list; - __u8 id; /* can be an RF Discovery ID or an NFCEE ID */ + /* NCI specification 4.4.2 Connection Creation + * The combination of destination type and destination specific + * parameters shall uniquely identify a single destination for the + * Logical Connection + */ + struct dest_spec_params *dest_params; + __u8 dest_type; __u8 conn_id; __u8 max_pkt_payload_len; @@ -260,7 +266,9 @@ struct nci_dev { __u32 manufact_specific_info; /* Save RF Discovery ID or NFCEE ID under conn_create */ - __u8 cur_id; + struct dest_spec_params cur_params; + /* Save destination type under conn_create */ + __u8 cur_dest_type; /* stored during nci_data_exchange */ struct sk_buff *rx_data_reassembly; @@ -298,6 +306,8 @@ int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type, size_t params_len, struct core_conn_create_dest_spec_params *params); int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id); +int nci_nfcc_loopback(struct nci_dev *ndev, void *data, size_t data_len, + struct sk_buff **resp); struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev); int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event, @@ -378,7 +388,8 @@ void nci_clear_target_list(struct nci_dev *ndev); void nci_req_complete(struct nci_dev *ndev, int result); struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev, int conn_id); -int nci_get_conn_info_by_id(struct nci_dev *ndev, u8 id); +int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type, + struct dest_spec_params *params); /* ----- NCI status code ----- */ int nci_to_errno(__u8 code); diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index fbb7a2b57b44..61fff422424f 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -64,18 +64,26 @@ struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev, return NULL; } -int nci_get_conn_info_by_id(struct nci_dev *ndev, u8 id) +int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type, + struct dest_spec_params *params) { struct nci_conn_info *conn_info; list_for_each_entry(conn_info, &ndev->conn_info_list, list) { - if (conn_info->id == id) - return conn_info->conn_id; + if (conn_info->dest_type == dest_type) { + if (!params) + return conn_info->conn_id; + if (conn_info) { + if (params->id == conn_info->dest_params->id && + params->protocol == conn_info->dest_params->protocol) + return conn_info->conn_id; + } + } } return -EINVAL; } -EXPORT_SYMBOL(nci_get_conn_info_by_id); +EXPORT_SYMBOL(nci_get_conn_info_by_dest_type_params); /* ---- NCI requests ---- */ @@ -392,6 +400,83 @@ int nci_core_init(struct nci_dev *ndev) } EXPORT_SYMBOL(nci_core_init); +struct nci_loopback_data { + u8 conn_id; + struct sk_buff *data; +}; + +static void nci_send_data_req(struct nci_dev *ndev, unsigned long opt) +{ + struct nci_loopback_data *data = (struct nci_loopback_data *)opt; + + nci_send_data(ndev, data->conn_id, data->data); +} + +static void nci_nfcc_loopback_cb(void *context, struct sk_buff *skb, int err) +{ + struct nci_dev *ndev = (struct nci_dev *)context; + struct nci_conn_info *conn_info; + + conn_info = nci_get_conn_info_by_conn_id(ndev, ndev->cur_conn_id); + if (!conn_info) { + nci_req_complete(ndev, NCI_STATUS_REJECTED); + return; + } + + conn_info->rx_skb = skb; + + nci_req_complete(ndev, NCI_STATUS_OK); +} + +int nci_nfcc_loopback(struct nci_dev *ndev, void *data, size_t data_len, + struct sk_buff **resp) +{ + int r; + struct nci_loopback_data loopback_data; + struct nci_conn_info *conn_info; + struct sk_buff *skb; + int conn_id = nci_get_conn_info_by_dest_type_params(ndev, + NCI_DESTINATION_NFCC_LOOPBACK, NULL); + + if (conn_id < 0) { + r = nci_core_conn_create(ndev, NCI_DESTINATION_NFCC_LOOPBACK, + 0, 0, NULL); + if (r != NCI_STATUS_OK) + return r; + + conn_id = nci_get_conn_info_by_dest_type_params(ndev, + NCI_DESTINATION_NFCC_LOOPBACK, + NULL); + } + + conn_info = nci_get_conn_info_by_conn_id(ndev, conn_id); + if (!conn_info) + return -EPROTO; + + /* store cb and context to be used on receiving data */ + conn_info->data_exchange_cb = nci_nfcc_loopback_cb; + conn_info->data_exchange_cb_context = ndev; + + skb = nci_skb_alloc(ndev, NCI_DATA_HDR_SIZE + data_len, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + skb_reserve(skb, NCI_DATA_HDR_SIZE); + memcpy(skb_put(skb, data_len), data, data_len); + + loopback_data.conn_id = conn_id; + loopback_data.data = skb; + + ndev->cur_conn_id = conn_id; + r = nci_request(ndev, nci_send_data_req, (unsigned long)&loopback_data, + msecs_to_jiffies(NCI_DATA_TIMEOUT)); + if (r == NCI_STATUS_OK && resp) + *resp = conn_info->rx_skb; + + return r; +} +EXPORT_SYMBOL(nci_nfcc_loopback); + static int nci_open_device(struct nci_dev *ndev) { int rc = 0; @@ -610,9 +695,6 @@ int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type, struct nci_core_conn_create_cmd *cmd; struct core_conn_create_data data; - if (!number_destination_params) - return -EINVAL; - data.length = params_len + sizeof(struct nci_core_conn_create_cmd); cmd = kzalloc(data.length, GFP_KERNEL); if (!cmd) @@ -620,17 +702,23 @@ int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type, cmd->destination_type = destination_type; cmd->number_destination_params = number_destination_params; - memcpy(cmd->params, params, params_len); data.cmd = cmd; - if (params->length > 0) - ndev->cur_id = params->value[DEST_SPEC_PARAMS_ID_INDEX]; - else - ndev->cur_id = 0; + if (params) { + memcpy(cmd->params, params, params_len); + if (params->length > 0) + memcpy(&ndev->cur_params, + ¶ms->value[DEST_SPEC_PARAMS_ID_INDEX], + sizeof(struct dest_spec_params)); + else + ndev->cur_params.id = 0; + } else { + ndev->cur_params.id = 0; + } + ndev->cur_dest_type = destination_type; - r = __nci_request(ndev, nci_core_conn_create_req, - (unsigned long)&data, + r = __nci_request(ndev, nci_core_conn_create_req, (unsigned long)&data, msecs_to_jiffies(NCI_CMD_TIMEOUT)); kfree(cmd); return r; @@ -646,6 +734,7 @@ static void nci_core_conn_close_req(struct nci_dev *ndev, unsigned long opt) int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id) { + ndev->cur_conn_id = conn_id; return __nci_request(ndev, nci_core_conn_close_req, conn_id, msecs_to_jiffies(NCI_CMD_TIMEOUT)); } diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 2ada2b39e355..1e8c1a12aaec 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c @@ -734,7 +734,7 @@ static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev, * “HCI Access”, even if the HCI Network contains multiple NFCEEs. */ ndev->hci_dev->nfcee_id = nfcee_ntf->nfcee_id; - ndev->cur_id = nfcee_ntf->nfcee_id; + ndev->cur_params.id = nfcee_ntf->nfcee_id; nci_req_complete(ndev, status); } diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c index 9b6eb913d801..e3bbf1937d0e 100644 --- a/net/nfc/nci/rsp.c +++ b/net/nfc/nci/rsp.c @@ -226,7 +226,7 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) { __u8 status = skb->data[0]; - struct nci_conn_info *conn_info; + struct nci_conn_info *conn_info = NULL; struct nci_core_conn_create_rsp *rsp; pr_debug("status 0x%x\n", status); @@ -241,7 +241,17 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, goto exit; } - conn_info->id = ndev->cur_id; + conn_info->dest_params = devm_kzalloc(&ndev->nfc_dev->dev, + sizeof(struct dest_spec_params), + GFP_KERNEL); + if (!conn_info->dest_params) { + status = NCI_STATUS_REJECTED; + goto free_conn_info; + } + + conn_info->dest_type = ndev->cur_dest_type; + conn_info->dest_params->id = ndev->cur_params.id; + conn_info->dest_params->protocol = ndev->cur_params.protocol; conn_info->conn_id = rsp->conn_id; /* Note: data_exchange_cb and data_exchange_cb_context need to @@ -251,7 +261,7 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, INIT_LIST_HEAD(&conn_info->list); list_add(&conn_info->list, &ndev->conn_info_list); - if (ndev->cur_id == ndev->hci_dev->nfcee_id) + if (ndev->cur_params.id == ndev->hci_dev->nfcee_id) ndev->hci_dev->conn_info = conn_info; conn_info->conn_id = rsp->conn_id; @@ -259,7 +269,11 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, atomic_set(&conn_info->credits_cnt, rsp->credits_cnt); } +free_conn_info: + if (status == NCI_STATUS_REJECTED) + devm_kfree(&ndev->nfc_dev->dev, conn_info); exit: + nci_req_complete(ndev, status); } @@ -271,7 +285,8 @@ static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev, pr_debug("status 0x%x\n", status); if (status == NCI_STATUS_OK) { - conn_info = nci_get_conn_info_by_conn_id(ndev, ndev->cur_id); + conn_info = nci_get_conn_info_by_conn_id(ndev, + ndev->cur_conn_id); if (conn_info) { list_del(&conn_info->list); devm_kfree(&ndev->nfc_dev->dev, conn_info);