2011-07-02 02:31:37 +04:00
/*
* Copyright ( C ) 2011 Instituto Nokia de Tecnologia
2013-04-03 10:02:01 +04:00
* Copyright ( C ) 2012 - 2013 Tieto Poland
2011-07-02 02:31:37 +04:00
*
* 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 , write to the
* Free Software Foundation , Inc . ,
* 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# include <linux/device.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/usb.h>
# include <linux/nfc.h>
# include <linux/netdevice.h>
2011-09-18 12:19:34 +04:00
# include <net/nfc/nfc.h>
2011-07-02 02:31:37 +04:00
2013-04-03 10:02:16 +04:00
# define VERSION "0.2"
2011-07-02 02:31:37 +04:00
# define PN533_VENDOR_ID 0x4CC
# define PN533_PRODUCT_ID 0x2533
# define SCM_VENDOR_ID 0x4E6
# define SCL3711_PRODUCT_ID 0x5591
2012-07-02 22:04:01 +04:00
# define SONY_VENDOR_ID 0x054c
# define PASORI_PRODUCT_ID 0x02e1
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
# 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
2012-07-02 22:04:01 +04:00
2012-07-04 02:14:04 +04:00
# 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 )
2012-07-02 22:04:01 +04:00
# define PN533_NO_TYPE_B_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
NFC_PROTO_MIFARE_MASK | \
NFC_PROTO_FELICA_MASK | \
2012-07-04 02:14:04 +04:00
NFC_PROTO_ISO14443_MASK | \
2012-07-02 22:04:01 +04:00
NFC_PROTO_NFC_DEP_MASK )
2011-07-02 02:31:37 +04:00
static const struct usb_device_id pn533_table [ ] = {
2012-07-02 22:04:01 +04:00
{ . match_flags = USB_DEVICE_ID_MATCH_DEVICE ,
. idVendor = PN533_VENDOR_ID ,
. idProduct = PN533_PRODUCT_ID ,
. driver_info = PN533_DEVICE_STD ,
} ,
{ . match_flags = USB_DEVICE_ID_MATCH_DEVICE ,
. idVendor = SCM_VENDOR_ID ,
. idProduct = SCL3711_PRODUCT_ID ,
. driver_info = PN533_DEVICE_STD ,
} ,
{ . match_flags = USB_DEVICE_ID_MATCH_DEVICE ,
. idVendor = SONY_VENDOR_ID ,
. idProduct = PASORI_PRODUCT_ID ,
. driver_info = PN533_DEVICE_PASORI ,
} ,
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
{ . match_flags = USB_DEVICE_ID_MATCH_DEVICE ,
. idVendor = ACS_VENDOR_ID ,
. idProduct = ACR122U_PRODUCT_ID ,
. driver_info = PN533_DEVICE_ACR122U ,
} ,
2011-07-02 02:31:37 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( usb , pn533_table ) ;
2012-05-30 19:20:25 +04:00
/* How much time we spend listening for initiators */
# define PN533_LISTEN_TIME 2
2013-06-13 17:43:27 +04:00
/* Standard pn533 frame definitions (standard and extended)*/
2013-04-03 10:01:58 +04:00
# define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \
2012-11-26 17:18:32 +04:00
+ 2 ) /* data[0] TFI, data[1] CC */
2013-04-03 10:01:58 +04:00
# define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/
2012-10-11 16:03:58 +04:00
2013-06-13 17:43:27 +04:00
# 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) */
2012-11-26 17:18:35 +04:00
/*
* Max extended frame payload len , excluding TFI and CC
* which are already in PN533_FRAME_HEADER_LEN .
*/
2013-04-03 10:01:58 +04:00
# define PN533_STD_FRAME_MAX_PAYLOAD_LEN 263
2012-11-26 17:18:35 +04:00
2013-04-03 10:01:58 +04:00
# define PN533_STD_FRAME_ACK_SIZE 6 / * Preamble (1), SoPC (2), ACK Code (2),
2012-12-10 17:42:56 +04:00
Postamble ( 1 ) */
2013-04-03 10:01:58 +04:00
# define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen])
# define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
2013-06-13 17:43:27 +04:00
/* 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)])
2011-07-02 02:31:37 +04:00
/* start of frame */
2013-04-03 10:01:58 +04:00
# define PN533_STD_FRAME_SOF 0x00FF
2011-07-02 02:31:37 +04:00
2013-04-03 10:01:58 +04:00
/* 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
2011-07-02 02:31:37 +04:00
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
/* 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
2011-07-02 02:31:37 +04:00
/* PN533 Commands */
2013-06-13 17:43:27 +04:00
# define PN533_FRAME_CMD(f) (f->data[1])
2011-07-02 02:31:37 +04:00
# define PN533_CMD_GET_FIRMWARE_VERSION 0x02
# define PN533_CMD_RF_CONFIGURATION 0x32
# define PN533_CMD_IN_DATA_EXCHANGE 0x40
2012-07-02 22:04:01 +04:00
# define PN533_CMD_IN_COMM_THRU 0x42
2011-07-02 02:31:37 +04:00
# define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A
# define PN533_CMD_IN_ATR 0x50
# define PN533_CMD_IN_RELEASE 0x52
2011-12-14 19:43:11 +04:00
# define PN533_CMD_IN_JUMP_FOR_DEP 0x56
2011-07-02 02:31:37 +04:00
2012-05-31 01:54:55 +04:00
# define PN533_CMD_TG_INIT_AS_TARGET 0x8c
2012-05-31 02:07:51 +04:00
# define PN533_CMD_TG_GET_DATA 0x86
2012-05-31 02:09:11 +04:00
# define PN533_CMD_TG_SET_DATA 0x8e
2012-11-26 17:18:34 +04:00
# define PN533_CMD_UNDEF 0xff
2012-05-31 01:54:55 +04:00
2011-07-02 02:31:37 +04:00
# 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 ;
2012-11-26 17:18:34 +04:00
typedef int ( * pn533_send_async_complete_t ) ( struct pn533 * dev , void * arg ,
struct sk_buff * resp ) ;
2011-07-02 02:31:37 +04:00
/* structs for pn533 commands */
/* PN533_CMD_GET_FIRMWARE_VERSION */
struct pn533_fw_version {
u8 ic ;
u8 ver ;
u8 rev ;
u8 support ;
} ;
/* PN533_CMD_RF_CONFIGURATION */
2013-04-11 13:45:41 +04:00
# define PN533_CFGITEM_RF_FIELD 0x01
# define PN533_CFGITEM_TIMING 0x02
2011-07-02 02:31:37 +04:00
# define PN533_CFGITEM_MAX_RETRIES 0x05
2013-04-11 13:45:41 +04:00
# define PN533_CFGITEM_PASORI 0x82
2013-07-01 19:26:58 +04:00
# define PN533_CFGITEM_RF_FIELD_AUTO_RFCA 0x2
# define PN533_CFGITEM_RF_FIELD_ON 0x1
# define PN533_CFGITEM_RF_FIELD_OFF 0x0
2011-07-02 02:31:37 +04:00
2012-05-29 23:34:08 +04:00
# define PN533_CONFIG_TIMING_102 0xb
# define PN533_CONFIG_TIMING_204 0xc
# define PN533_CONFIG_TIMING_409 0xd
# define PN533_CONFIG_TIMING_819 0xe
2011-07-02 02:31:37 +04:00
# define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00
# define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF
struct pn533_config_max_retries {
u8 mx_rty_atr ;
u8 mx_rty_psl ;
u8 mx_rty_passive_act ;
} __packed ;
2012-05-29 23:34:08 +04:00
struct pn533_config_timing {
u8 rfu ;
u8 atr_res_timeout ;
u8 dep_timeout ;
} __packed ;
2011-07-02 02:31:37 +04:00
/* PN533_CMD_IN_LIST_PASSIVE_TARGET */
/* felica commands opcode */
# define PN533_FELICA_OPC_SENSF_REQ 0
# define PN533_FELICA_OPC_SENSF_RES 1
/* felica SENSF_REQ parameters */
# define PN533_FELICA_SENSF_SC_ALL 0xFFFF
# define PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE 0
# define PN533_FELICA_SENSF_RC_SYSTEM_CODE 1
# define PN533_FELICA_SENSF_RC_ADVANCED_PROTOCOL 2
/* type B initiator_data values */
# define PN533_TYPE_B_AFI_ALL_FAMILIES 0
# define PN533_TYPE_B_POLL_METHOD_TIMESLOT 0
# define PN533_TYPE_B_POLL_METHOD_PROBABILISTIC 1
union pn533_cmd_poll_initdata {
struct {
u8 afi ;
u8 polling_method ;
} __packed type_b ;
struct {
u8 opcode ;
__be16 sc ;
u8 rc ;
u8 tsn ;
} __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 ,
2012-05-30 19:20:25 +04:00
PN533_LISTEN_MOD ,
2011-07-02 02:31:37 +04:00
__PN533_POLL_MOD_AFTER_LAST ,
} ;
# define PN533_POLL_MOD_MAX (__PN533_POLL_MOD_AFTER_LAST - 1)
struct pn533_poll_modulations {
struct {
u8 maxtg ;
u8 brty ;
union pn533_cmd_poll_initdata initiator_data ;
} __packed data ;
u8 len ;
} ;
2013-01-16 18:51:51 +04:00
static const struct pn533_poll_modulations poll_mod [ ] = {
2011-07-02 02:31:37 +04:00
[ PN533_POLL_MOD_106KBPS_A ] = {
. data = {
. maxtg = 1 ,
. brty = 0 ,
} ,
. len = 2 ,
} ,
[ PN533_POLL_MOD_212KBPS_FELICA ] = {
. data = {
. maxtg = 1 ,
. brty = 1 ,
. initiator_data . felica = {
. opcode = PN533_FELICA_OPC_SENSF_REQ ,
. sc = PN533_FELICA_SENSF_SC_ALL ,
2013-06-28 17:43:19 +04:00
. rc = PN533_FELICA_SENSF_RC_SYSTEM_CODE ,
2013-05-27 16:59:40 +04:00
. tsn = 0x03 ,
2011-07-02 02:31:37 +04:00
} ,
} ,
. len = 7 ,
} ,
[ PN533_POLL_MOD_424KBPS_FELICA ] = {
. data = {
. maxtg = 1 ,
. brty = 2 ,
. initiator_data . felica = {
. opcode = PN533_FELICA_OPC_SENSF_REQ ,
. sc = PN533_FELICA_SENSF_SC_ALL ,
2013-06-28 17:43:19 +04:00
. rc = PN533_FELICA_SENSF_RC_SYSTEM_CODE ,
2013-05-27 16:59:40 +04:00
. tsn = 0x03 ,
2011-07-02 02:31:37 +04:00
} ,
} ,
. len = 7 ,
} ,
[ PN533_POLL_MOD_106KBPS_JEWEL ] = {
. data = {
. maxtg = 1 ,
. brty = 4 ,
} ,
. len = 2 ,
} ,
[ PN533_POLL_MOD_847KBPS_B ] = {
. data = {
. maxtg = 1 ,
. brty = 8 ,
. initiator_data . type_b = {
. afi = PN533_TYPE_B_AFI_ALL_FAMILIES ,
. polling_method =
PN533_TYPE_B_POLL_METHOD_TIMESLOT ,
} ,
} ,
. len = 3 ,
} ,
2012-05-30 19:20:25 +04:00
[ PN533_LISTEN_MOD ] = {
. len = 0 ,
} ,
2011-07-02 02:31:37 +04:00
} ;
/* PN533_CMD_IN_ATR */
struct pn533_cmd_activate_response {
u8 status ;
u8 nfcid3t [ 10 ] ;
u8 didt ;
u8 bst ;
u8 brt ;
u8 to ;
u8 ppt ;
/* optional */
u8 gt [ ] ;
} __packed ;
2011-12-14 19:43:11 +04:00
struct pn533_cmd_jump_dep_response {
u8 status ;
u8 tg ;
u8 nfcid3t [ 10 ] ;
u8 didt ;
u8 bst ;
u8 brt ;
u8 to ;
u8 ppt ;
/* optional */
u8 gt [ ] ;
} __packed ;
2011-07-02 02:31:37 +04:00
2012-05-31 01:54:55 +04:00
/* PN533_TG_INIT_AS_TARGET */
# define PN533_INIT_TARGET_PASSIVE 0x1
# define PN533_INIT_TARGET_DEP 0x2
2012-06-01 15:21:13 +04:00
# define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3
# define PN533_INIT_TARGET_RESP_ACTIVE 0x1
# define PN533_INIT_TARGET_RESP_DEP 0x4
2013-04-03 10:02:12 +04:00
enum pn533_protocol_type {
PN533_PROTO_REQ_ACK_RESP = 0 ,
PN533_PROTO_REQ_RESP
} ;
2011-07-02 02:31:37 +04:00
struct pn533 {
struct usb_device * udev ;
struct usb_interface * interface ;
struct nfc_dev * nfc_dev ;
2013-04-03 10:02:10 +04:00
u32 device_type ;
2013-04-03 10:02:12 +04:00
enum pn533_protocol_type protocol_type ;
2011-07-02 02:31:37 +04:00
struct urb * out_urb ;
struct urb * in_urb ;
2012-04-10 21:43:18 +04:00
struct sk_buff_head resp_q ;
2012-04-10 21:43:17 +04:00
struct workqueue_struct * wq ;
struct work_struct cmd_work ;
2012-08-18 01:47:54 +04:00
struct work_struct cmd_complete_work ;
2012-05-30 19:20:25 +04:00
struct work_struct poll_work ;
2012-04-10 21:43:18 +04:00
struct work_struct mi_work ;
2012-05-31 02:07:51 +04:00
struct work_struct tg_work ;
2013-06-26 20:16:21 +04:00
struct work_struct rf_work ;
2013-04-03 10:02:10 +04:00
struct list_head cmd_queue ;
struct pn533_cmd * cmd ;
u8 cmd_pending ;
struct mutex cmd_lock ; /* protects cmd queue */
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:46 +04:00
void * cmd_complete_mi_arg ;
2011-07-02 02:31:37 +04:00
struct pn533_poll_modulations * poll_mod_active [ PN533_POLL_MOD_MAX + 1 ] ;
u8 poll_mod_count ;
u8 poll_mod_curr ;
u32 poll_protocols ;
2012-05-30 19:20:25 +04:00
u32 listen_protocols ;
2013-04-03 10:02:10 +04:00
struct timer_list listen_timer ;
int cancel_listen ;
2012-05-30 19:20:25 +04:00
u8 * gb ;
size_t gb_len ;
2011-07-02 02:31:37 +04:00
u8 tgt_available_prots ;
u8 tgt_active_prot ;
2012-05-31 22:01:32 +04:00
u8 tgt_mode ;
2012-07-02 22:04:01 +04:00
2012-12-10 17:43:01 +04:00
struct pn533_frame_ops * ops ;
2012-08-18 01:47:54 +04:00
} ;
struct pn533_cmd {
struct list_head queue ;
2013-04-03 10:02:06 +04:00
u8 code ;
2013-04-03 10:02:11 +04:00
int status ;
2012-11-26 17:18:34 +04:00
struct sk_buff * req ;
struct sk_buff * resp ;
2012-12-10 17:43:01 +04:00
int resp_len ;
2013-04-03 10:02:04 +04:00
pn533_send_async_complete_t complete_cb ;
void * complete_cb_context ;
2011-07-02 02:31:37 +04:00
} ;
2013-04-03 10:01:58 +04:00
struct pn533_std_frame {
2011-07-02 02:31:37 +04:00
u8 preamble ;
__be16 start_frame ;
u8 datalen ;
u8 datalen_checksum ;
u8 data [ ] ;
} __packed ;
2013-06-13 17:43:27 +04:00
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 ;
2012-12-10 17:43:01 +04:00
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 ) ;
int ( * rx_frame_size ) ( void * frame ) ;
int rx_header_len ;
int rx_tail_len ;
int max_payload_len ;
u8 ( * get_cmd_code ) ( void * frame ) ;
} ;
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
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_acr122_rx_frame * frame = _frame ;
if ( frame - > ccid . type ! = 0x83 )
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 ;
2013-06-13 17:43:27 +04:00
return PN533_FRAME_CMD ( f ) ;
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
}
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 ,
} ;
2013-06-13 17:43:27 +04:00
/* The rule: value(high byte) + value(low byte) + checksum = 0 */
static inline u8 pn533_ext_checksum ( u16 value )
{
return ~ ( u8 ) ( ( ( value & 0xFF00 ) > > 8 ) + ( u8 ) ( value & 0xFF ) ) + 1 ;
}
2011-07-02 02:31:37 +04:00
/* The rule: value + checksum = 0 */
2013-04-03 10:01:58 +04:00
static inline u8 pn533_std_checksum ( u8 value )
2011-07-02 02:31:37 +04:00
{
return ~ value + 1 ;
}
/* The rule: sum(data elements) + checksum = 0 */
2013-04-03 10:01:58 +04:00
static u8 pn533_std_data_checksum ( u8 * data , int datalen )
2011-07-02 02:31:37 +04:00
{
u8 sum = 0 ;
int i ;
for ( i = 0 ; i < datalen ; i + + )
sum + = data [ i ] ;
2013-04-03 10:01:58 +04:00
return pn533_std_checksum ( sum ) ;
2011-07-02 02:31:37 +04:00
}
2013-04-03 10:01:58 +04:00
static void pn533_std_tx_frame_init ( void * _frame , u8 cmd_code )
2011-07-02 02:31:37 +04:00
{
2013-04-03 10:01:58 +04:00
struct pn533_std_frame * frame = _frame ;
2012-12-10 17:43:01 +04:00
2011-07-02 02:31:37 +04:00
frame - > preamble = 0 ;
2013-04-03 10:01:58 +04:00
frame - > start_frame = cpu_to_be16 ( PN533_STD_FRAME_SOF ) ;
PN533_STD_FRAME_IDENTIFIER ( frame ) = PN533_STD_FRAME_DIR_OUT ;
2013-06-13 17:43:27 +04:00
PN533_FRAME_CMD ( frame ) = cmd_code ;
2011-07-02 02:31:37 +04:00
frame - > datalen = 2 ;
}
2013-04-03 10:01:58 +04:00
static void pn533_std_tx_frame_finish ( void * _frame )
2011-07-02 02:31:37 +04:00
{
2013-04-03 10:01:58 +04:00
struct pn533_std_frame * frame = _frame ;
2012-12-10 17:43:01 +04:00
2013-04-03 10:01:58 +04:00
frame - > datalen_checksum = pn533_std_checksum ( frame - > datalen ) ;
2011-07-02 02:31:37 +04:00
2013-04-03 10:01:58 +04:00
PN533_STD_FRAME_CHECKSUM ( frame ) =
pn533_std_data_checksum ( frame - > data , frame - > datalen ) ;
2011-07-02 02:31:37 +04:00
2013-04-03 10:01:58 +04:00
PN533_STD_FRAME_POSTAMBLE ( frame ) = 0 ;
2011-07-02 02:31:37 +04:00
}
2013-04-03 10:01:58 +04:00
static void pn533_std_tx_update_payload_len ( void * _frame , int len )
2012-12-10 17:43:01 +04:00
{
2013-04-03 10:01:58 +04:00
struct pn533_std_frame * frame = _frame ;
2012-12-10 17:43:01 +04:00
frame - > datalen + = len ;
}
2013-04-03 10:01:58 +04:00
static bool pn533_std_rx_frame_is_valid ( void * _frame )
2011-07-02 02:31:37 +04:00
{
u8 checksum ;
2013-06-13 17:43:27 +04:00
struct pn533_std_frame * stdf = _frame ;
2011-07-02 02:31:37 +04:00
2013-06-13 17:43:27 +04:00
if ( stdf - > start_frame ! = cpu_to_be16 ( PN533_STD_FRAME_SOF ) )
2011-07-02 02:31:37 +04:00
return false ;
2013-06-13 17:43:27 +04:00
if ( likely ( ! PN533_STD_IS_EXTENDED ( stdf ) ) ) {
/* Standard frame code */
checksum = pn533_std_checksum ( stdf - > datalen ) ;
if ( checksum ! = stdf - > datalen_checksum )
return false ;
checksum = pn533_std_data_checksum ( stdf - > data , stdf - > datalen ) ;
if ( checksum ! = PN533_STD_FRAME_CHECKSUM ( stdf ) )
return false ;
} else {
/* Extended */
struct pn533_ext_frame * eif = _frame ;
checksum = pn533_ext_checksum ( be16_to_cpu ( eif - > datalen ) ) ;
if ( checksum ! = eif - > datalen_checksum )
return false ;
/* check data checksum */
checksum = pn533_std_data_checksum ( eif - > data ,
be16_to_cpu ( eif - > datalen ) ) ;
if ( checksum ! = PN533_EXT_FRAME_CHECKSUM ( eif ) )
return false ;
}
2011-07-02 02:31:37 +04:00
return true ;
}
2013-04-03 10:01:58 +04:00
static bool pn533_std_rx_frame_is_ack ( struct pn533_std_frame * frame )
2011-07-02 02:31:37 +04:00
{
2013-04-03 10:01:58 +04:00
if ( frame - > start_frame ! = cpu_to_be16 ( PN533_STD_FRAME_SOF ) )
2011-07-02 02:31:37 +04:00
return false ;
if ( frame - > datalen ! = 0 | | frame - > datalen_checksum ! = 0xFF )
return false ;
return true ;
}
2013-04-03 10:01:58 +04:00
static inline int pn533_std_rx_frame_size ( void * frame )
2012-12-10 17:43:01 +04:00
{
2013-04-03 10:01:58 +04:00
struct pn533_std_frame * f = frame ;
2012-12-10 17:43:01 +04:00
2013-06-13 17:43:27 +04:00
/* check for Extended Information frame */
if ( PN533_STD_IS_EXTENDED ( f ) ) {
struct pn533_ext_frame * eif = frame ;
return sizeof ( struct pn533_ext_frame )
+ be16_to_cpu ( eif - > datalen ) + PN533_STD_FRAME_TAIL_LEN ;
}
2013-04-03 10:01:58 +04:00
return sizeof ( struct pn533_std_frame ) + f - > datalen +
PN533_STD_FRAME_TAIL_LEN ;
2012-12-10 17:43:01 +04:00
}
2013-04-03 10:01:58 +04:00
static u8 pn533_std_get_cmd_code ( void * frame )
2012-12-10 17:43:01 +04:00
{
2013-04-03 10:01:58 +04:00
struct pn533_std_frame * f = frame ;
2013-06-13 17:43:27 +04:00
struct pn533_ext_frame * eif = frame ;
2012-12-10 17:43:01 +04:00
2013-06-13 17:43:27 +04:00
if ( PN533_STD_IS_EXTENDED ( f ) )
return PN533_FRAME_CMD ( eif ) ;
else
return PN533_FRAME_CMD ( f ) ;
2012-12-10 17:43:01 +04:00
}
2013-01-16 18:51:51 +04:00
static struct pn533_frame_ops pn533_std_frame_ops = {
2013-04-03 10:01:58 +04:00
. tx_frame_init = pn533_std_tx_frame_init ,
. tx_frame_finish = pn533_std_tx_frame_finish ,
. tx_update_payload_len = pn533_std_tx_update_payload_len ,
. tx_header_len = PN533_STD_FRAME_HEADER_LEN ,
. tx_tail_len = PN533_STD_FRAME_TAIL_LEN ,
. rx_is_frame_valid = pn533_std_rx_frame_is_valid ,
. rx_frame_size = pn533_std_rx_frame_size ,
. rx_header_len = PN533_STD_FRAME_HEADER_LEN ,
. rx_tail_len = PN533_STD_FRAME_TAIL_LEN ,
. max_payload_len = PN533_STD_FRAME_MAX_PAYLOAD_LEN ,
. get_cmd_code = pn533_std_get_cmd_code ,
2012-12-10 17:43:01 +04:00
} ;
static bool pn533_rx_frame_is_cmd_response ( struct pn533 * dev , void * frame )
2011-07-02 02:31:37 +04:00
{
2013-04-03 10:02:05 +04:00
return ( dev - > ops - > get_cmd_code ( frame ) = =
2013-04-03 10:02:06 +04:00
PN533_CMD_RESPONSE ( dev - > cmd - > code ) ) ;
2011-07-02 02:31:37 +04:00
}
static void pn533_recv_response ( struct urb * urb )
{
struct pn533 * dev = urb - > context ;
2013-04-03 10:02:11 +04:00
struct pn533_cmd * cmd = dev - > cmd ;
2012-12-10 17:43:01 +04:00
u8 * in_frame ;
2011-07-02 02:31:37 +04:00
2013-04-03 10:02:11 +04:00
cmd - > status = urb - > status ;
2011-07-02 02:31:37 +04:00
switch ( urb - > status ) {
case 0 :
2012-12-10 17:42:54 +04:00
break ; /* success */
2011-07-02 02:31:37 +04:00
case - ECONNRESET :
case - ENOENT :
2012-12-10 17:42:49 +04:00
nfc_dev_dbg ( & dev - > interface - > dev ,
2012-12-10 17:42:54 +04:00
" The urb has been canceled (status %d) " ,
urb - > status ) ;
2012-04-10 21:43:17 +04:00
goto sched_wq ;
2012-12-10 17:42:54 +04:00
case - ESHUTDOWN :
2011-07-02 02:31:37 +04:00
default :
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
2012-12-10 17:42:54 +04:00
" Urb failure (status %d) " , urb - > status ) ;
2012-04-10 21:43:17 +04:00
goto sched_wq ;
2011-07-02 02:31:37 +04:00
}
in_frame = dev - > in_urb - > transfer_buffer ;
2012-12-10 17:42:55 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " Received a frame. " ) ;
2013-03-20 14:27:57 +04:00
print_hex_dump_debug ( " PN533 RX: " , DUMP_PREFIX_NONE , 16 , 1 , in_frame ,
dev - > ops - > rx_frame_size ( in_frame ) , false ) ;
2012-12-10 17:42:47 +04:00
2012-12-10 17:43:01 +04:00
if ( ! dev - > ops - > rx_is_frame_valid ( in_frame ) ) {
2011-07-02 02:31:37 +04:00
nfc_dev_err ( & dev - > interface - > dev , " Received an invalid frame " ) ;
2013-04-03 10:02:11 +04:00
cmd - > status = - EIO ;
2012-04-10 21:43:17 +04:00
goto sched_wq ;
2011-07-02 02:31:37 +04:00
}
2012-12-10 17:43:01 +04:00
if ( ! pn533_rx_frame_is_cmd_response ( dev , in_frame ) ) {
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" It it not the response to the last command " ) ;
2013-04-03 10:02:11 +04:00
cmd - > status = - EIO ;
2012-04-10 21:43:17 +04:00
goto sched_wq ;
2011-07-02 02:31:37 +04:00
}
2013-06-13 17:43:27 +04:00
if ( PN533_STD_IS_EXTENDED ( ( struct pn533_std_frame * ) in_frame ) )
dev - > ops - > rx_header_len = PN533_EXT_FRAME_HEADER_LEN ;
else
dev - > ops - > rx_header_len = PN533_STD_FRAME_HEADER_LEN ;
2012-04-10 21:43:17 +04:00
sched_wq :
2012-08-18 01:47:54 +04:00
queue_work ( dev - > wq , & dev - > cmd_complete_work ) ;
2011-07-02 02:31:37 +04:00
}
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 ;
2013-04-03 10:02:11 +04:00
struct pn533_cmd * cmd = dev - > cmd ;
2013-04-03 10:01:58 +04:00
struct pn533_std_frame * in_frame ;
2011-07-02 02:31:37 +04:00
int rc ;
2013-04-03 10:02:11 +04:00
cmd - > status = urb - > status ;
2011-07-02 02:31:37 +04:00
switch ( urb - > status ) {
case 0 :
2012-12-10 17:42:54 +04:00
break ; /* success */
2011-07-02 02:31:37 +04:00
case - ECONNRESET :
case - ENOENT :
2012-12-10 17:42:49 +04:00
nfc_dev_dbg ( & dev - > interface - > dev ,
2012-12-10 17:42:54 +04:00
" The urb has been stopped (status %d) " ,
urb - > status ) ;
2012-04-10 21:43:17 +04:00
goto sched_wq ;
2012-12-10 17:42:54 +04:00
case - ESHUTDOWN :
2011-07-02 02:31:37 +04:00
default :
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
2012-12-10 17:42:54 +04:00
" Urb failure (status %d) " , urb - > status ) ;
2012-04-10 21:43:17 +04:00
goto sched_wq ;
2011-07-02 02:31:37 +04:00
}
in_frame = dev - > in_urb - > transfer_buffer ;
2013-04-03 10:01:58 +04:00
if ( ! pn533_std_rx_frame_is_ack ( in_frame ) ) {
2011-07-02 02:31:37 +04:00
nfc_dev_err ( & dev - > interface - > dev , " Received an invalid ack " ) ;
2013-04-03 10:02:11 +04:00
cmd - > status = - EIO ;
2012-04-10 21:43:17 +04:00
goto sched_wq ;
2011-07-02 02:31:37 +04:00
}
rc = pn533_submit_urb_for_response ( dev , GFP_ATOMIC ) ;
if ( rc ) {
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" usb_submit_urb failed with result %d " , rc ) ;
2013-04-03 10:02:11 +04:00
cmd - > status = rc ;
2012-04-10 21:43:17 +04:00
goto sched_wq ;
2011-07-02 02:31:37 +04:00
}
return ;
2012-04-10 21:43:17 +04:00
sched_wq :
2012-08-18 01:47:54 +04:00
queue_work ( dev - > wq , & dev - > cmd_complete_work ) ;
2011-07-02 02:31:37 +04:00
}
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 )
{
2013-04-03 10:01:58 +04:00
u8 ack [ PN533_STD_FRAME_ACK_SIZE ] = { 0x00 , 0x00 , 0xff , 0x00 , 0xff , 0x00 } ;
2012-12-10 17:42:56 +04:00
/* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */
2011-07-02 02:31:37 +04:00
int rc ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:42:56 +04:00
dev - > out_urb - > transfer_buffer = ack ;
dev - > out_urb - > transfer_buffer_length = sizeof ( ack ) ;
2011-07-02 02:31:37 +04:00
rc = usb_submit_urb ( dev - > out_urb , flags ) ;
return rc ;
}
2012-12-10 17:42:57 +04:00
static int __pn533_send_frame_async ( struct pn533 * dev ,
struct sk_buff * out ,
struct sk_buff * in ,
2013-04-03 10:02:08 +04:00
int in_len )
2011-07-02 02:31:37 +04:00
{
int rc ;
2012-12-10 17:42:57 +04:00
dev - > out_urb - > transfer_buffer = out - > data ;
dev - > out_urb - > transfer_buffer_length = out - > len ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:57 +04:00
dev - > in_urb - > transfer_buffer = in - > data ;
dev - > in_urb - > transfer_buffer_length = in_len ;
2011-07-02 02:31:37 +04:00
2013-03-20 14:27:57 +04:00
print_hex_dump_debug ( " PN533 TX: " , DUMP_PREFIX_NONE , 16 , 1 ,
out - > data , out - > len , false ) ;
2012-12-10 17:42:47 +04:00
2012-11-26 17:18:33 +04:00
rc = usb_submit_urb ( dev - > out_urb , GFP_KERNEL ) ;
2011-07-02 02:31:37 +04:00
if ( rc )
return rc ;
2013-04-03 10:02:12 +04:00
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 ;
}
2011-07-02 02:31:37 +04:00
return 0 ;
error :
usb_unlink_urb ( dev - > out_urb ) ;
return rc ;
}
2012-12-10 17:43:01 +04:00
static void pn533_build_cmd_frame ( struct pn533 * dev , u8 cmd_code ,
struct sk_buff * skb )
2012-11-26 17:18:34 +04:00
{
/* payload is already there, just update datalen */
int payload_len = skb - > len ;
2012-12-10 17:43:01 +04:00
struct pn533_frame_ops * ops = dev - > ops ;
2012-11-26 17:18:34 +04:00
2012-12-10 17:43:01 +04:00
skb_push ( skb , ops - > tx_header_len ) ;
skb_put ( skb , ops - > tx_tail_len ) ;
2012-11-26 17:18:34 +04:00
2012-12-10 17:43:01 +04:00
ops - > tx_frame_init ( skb - > data , cmd_code ) ;
ops - > tx_update_payload_len ( skb - > data , payload_len ) ;
ops - > tx_frame_finish ( skb - > data ) ;
2012-11-26 17:18:34 +04:00
}
2013-04-03 10:02:08 +04:00
static int pn533_send_async_complete ( struct pn533 * dev )
2012-11-26 17:18:34 +04:00
{
2013-04-03 10:02:08 +04:00
struct pn533_cmd * cmd = dev - > cmd ;
2013-04-03 10:02:11 +04:00
int status = cmd - > status ;
2012-11-26 17:18:34 +04:00
2013-04-03 10:02:04 +04:00
struct sk_buff * req = cmd - > req ;
struct sk_buff * resp = cmd - > resp ;
2012-11-26 17:18:34 +04:00
int rc ;
dev_kfree_skb ( req ) ;
2012-12-10 17:42:59 +04:00
if ( status < 0 ) {
2013-04-03 10:02:04 +04:00
rc = cmd - > complete_cb ( dev , cmd - > complete_cb_context ,
ERR_PTR ( status ) ) ;
2012-11-26 17:18:34 +04:00
dev_kfree_skb ( resp ) ;
2013-04-03 10:02:05 +04:00
goto done ;
2012-11-26 17:18:34 +04:00
}
2012-12-10 17:43:01 +04:00
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 ) ;
2012-11-26 17:18:34 +04:00
2013-04-03 10:02:04 +04:00
rc = cmd - > complete_cb ( dev , cmd - > complete_cb_context , resp ) ;
2012-11-26 17:18:34 +04:00
2013-04-03 10:02:05 +04:00
done :
2013-04-03 10:02:04 +04:00
kfree ( cmd ) ;
2013-04-03 10:02:05 +04:00
dev - > cmd = NULL ;
2012-11-26 17:18:34 +04:00
return rc ;
}
static int __pn533_send_async ( struct pn533 * dev , u8 cmd_code ,
struct sk_buff * req , struct sk_buff * resp ,
int resp_len ,
pn533_send_async_complete_t complete_cb ,
void * complete_cb_context )
{
struct pn533_cmd * cmd ;
int rc = 0 ;
2012-12-10 17:42:55 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " Sending command 0x%x " , cmd_code ) ;
2012-11-26 17:18:34 +04:00
2013-04-03 10:02:04 +04:00
cmd = kzalloc ( sizeof ( * cmd ) , GFP_KERNEL ) ;
if ( ! cmd )
2012-11-26 17:18:34 +04:00
return - ENOMEM ;
2013-04-03 10:02:06 +04:00
cmd - > code = cmd_code ;
2013-04-03 10:02:04 +04:00
cmd - > req = req ;
cmd - > resp = resp ;
cmd - > resp_len = resp_len ;
cmd - > complete_cb = complete_cb ;
cmd - > complete_cb_context = complete_cb_context ;
2012-11-26 17:18:34 +04:00
2012-12-10 17:43:01 +04:00
pn533_build_cmd_frame ( dev , cmd_code , req ) ;
2012-11-26 17:18:34 +04:00
mutex_lock ( & dev - > cmd_lock ) ;
if ( ! dev - > cmd_pending ) {
2013-04-03 10:02:08 +04:00
rc = __pn533_send_frame_async ( dev , req , resp , resp_len ) ;
2012-11-26 17:18:34 +04:00
if ( rc )
goto error ;
dev - > cmd_pending = 1 ;
2013-04-03 10:02:05 +04:00
dev - > cmd = cmd ;
2012-11-26 17:18:34 +04:00
goto unlock ;
}
2012-12-10 17:42:55 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s Queueing command 0x%x " , __func__ ,
cmd_code ) ;
2012-11-26 17:18:34 +04:00
INIT_LIST_HEAD ( & cmd - > queue ) ;
list_add_tail ( & cmd - > queue , & dev - > cmd_queue ) ;
goto unlock ;
error :
2013-04-03 10:02:04 +04:00
kfree ( cmd ) ;
2012-11-26 17:18:34 +04:00
unlock :
mutex_unlock ( & dev - > cmd_lock ) ;
return rc ;
2012-11-26 17:18:35 +04:00
}
static int pn533_send_data_async ( struct pn533 * dev , u8 cmd_code ,
struct sk_buff * req ,
pn533_send_async_complete_t complete_cb ,
void * complete_cb_context )
{
struct sk_buff * resp ;
int rc ;
2012-12-10 17:43:01 +04:00
int resp_len = dev - > ops - > rx_header_len +
dev - > ops - > max_payload_len +
dev - > ops - > rx_tail_len ;
2012-11-26 17:18:35 +04:00
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 ,
complete_cb_context ) ;
if ( rc )
dev_kfree_skb ( resp ) ;
return rc ;
2012-11-26 17:18:34 +04:00
}
static int pn533_send_cmd_async ( struct pn533 * dev , u8 cmd_code ,
struct sk_buff * req ,
pn533_send_async_complete_t complete_cb ,
void * complete_cb_context )
{
struct sk_buff * resp ;
int rc ;
2012-12-10 17:43:01 +04:00
int resp_len = dev - > ops - > rx_header_len +
dev - > ops - > max_payload_len +
dev - > ops - > rx_tail_len ;
2012-11-26 17:18:34 +04:00
2012-12-10 17:43:01 +04:00
resp = alloc_skb ( resp_len , GFP_KERNEL ) ;
2012-11-26 17:18:34 +04:00
if ( ! resp )
return - ENOMEM ;
2012-12-10 17:43:01 +04:00
rc = __pn533_send_async ( dev , cmd_code , req , resp , resp_len , complete_cb ,
complete_cb_context ) ;
2012-11-26 17:18:34 +04:00
if ( rc )
dev_kfree_skb ( resp ) ;
return rc ;
}
2012-12-10 17:42:46 +04:00
/*
* pn533_send_cmd_direct_async
*
* The function sends a piority cmd directly to the chip omiting the cmd
* queue . It ' s intended to be used by chaining mechanism of received responses
* where the host has to request every single chunk of data before scheduling
* next cmd from the queue .
*/
static int pn533_send_cmd_direct_async ( struct pn533 * dev , u8 cmd_code ,
struct sk_buff * req ,
pn533_send_async_complete_t complete_cb ,
void * complete_cb_context )
{
struct sk_buff * resp ;
2013-04-03 10:02:04 +04:00
struct pn533_cmd * cmd ;
2012-12-10 17:42:46 +04:00
int rc ;
2012-12-10 17:43:01 +04:00
int resp_len = dev - > ops - > rx_header_len +
dev - > ops - > max_payload_len +
dev - > ops - > rx_tail_len ;
2012-12-10 17:42:46 +04:00
resp = alloc_skb ( resp_len , GFP_KERNEL ) ;
if ( ! resp )
return - ENOMEM ;
2013-04-03 10:02:04 +04:00
cmd = kzalloc ( sizeof ( * cmd ) , GFP_KERNEL ) ;
if ( ! cmd ) {
2012-12-10 17:42:46 +04:00
dev_kfree_skb ( resp ) ;
return - ENOMEM ;
}
2013-04-03 10:02:06 +04:00
cmd - > code = cmd_code ;
2013-04-03 10:02:04 +04:00
cmd - > req = req ;
cmd - > resp = resp ;
cmd - > resp_len = resp_len ;
cmd - > complete_cb = complete_cb ;
cmd - > complete_cb_context = complete_cb_context ;
2012-12-10 17:42:46 +04:00
2012-12-10 17:43:01 +04:00
pn533_build_cmd_frame ( dev , cmd_code , req ) ;
2012-12-10 17:42:46 +04:00
2013-04-03 10:02:08 +04:00
rc = __pn533_send_frame_async ( dev , req , resp , resp_len ) ;
2012-12-10 17:42:46 +04:00
if ( rc < 0 ) {
dev_kfree_skb ( resp ) ;
2013-04-03 10:02:04 +04:00
kfree ( cmd ) ;
2013-04-03 10:02:05 +04:00
} else {
dev - > cmd = cmd ;
2012-12-10 17:42:46 +04:00
}
return rc ;
}
2013-04-03 10:02:09 +04:00
static void pn533_wq_cmd_complete ( struct work_struct * work )
{
struct pn533 * dev = container_of ( work , struct pn533 , cmd_complete_work ) ;
int rc ;
rc = pn533_send_async_complete ( dev ) ;
if ( rc ! = - EINPROGRESS )
queue_work ( dev - > wq , & dev - > cmd_work ) ;
}
2012-08-18 01:47:54 +04:00
static void pn533_wq_cmd ( struct work_struct * work )
{
struct pn533 * dev = container_of ( work , struct pn533 , cmd_work ) ;
struct pn533_cmd * cmd ;
2013-04-03 10:02:03 +04:00
int rc ;
2012-08-18 01:47:54 +04:00
mutex_lock ( & dev - > cmd_lock ) ;
if ( list_empty ( & dev - > cmd_queue ) ) {
dev - > cmd_pending = 0 ;
mutex_unlock ( & dev - > cmd_lock ) ;
return ;
}
cmd = list_first_entry ( & dev - > cmd_queue , struct pn533_cmd , queue ) ;
2012-10-25 19:29:45 +04:00
list_del ( & cmd - > queue ) ;
2012-08-18 01:47:54 +04:00
mutex_unlock ( & dev - > cmd_lock ) ;
2013-04-03 10:02:08 +04:00
rc = __pn533_send_frame_async ( dev , cmd - > req , cmd - > resp , cmd - > resp_len ) ;
2013-04-03 10:02:03 +04:00
if ( rc < 0 ) {
dev_kfree_skb ( cmd - > req ) ;
dev_kfree_skb ( cmd - > resp ) ;
2013-04-03 10:02:04 +04:00
kfree ( cmd ) ;
2013-04-03 10:02:05 +04:00
return ;
2013-04-03 10:02:03 +04:00
}
2013-04-03 10:02:05 +04:00
dev - > cmd = cmd ;
2012-08-18 01:47:54 +04:00
}
2011-07-02 02:31:37 +04:00
struct pn533_sync_cmd_response {
2012-11-26 17:18:36 +04:00
struct sk_buff * resp ;
2011-07-02 02:31:37 +04:00
struct completion done ;
} ;
2012-11-26 17:18:36 +04:00
static int pn533_send_sync_complete ( struct pn533 * dev , void * _arg ,
struct sk_buff * resp )
{
struct pn533_sync_cmd_response * arg = _arg ;
arg - > resp = resp ;
complete ( & arg - > done ) ;
return 0 ;
}
/* pn533_send_cmd_sync
*
* Please note the req parameter is freed inside the function to
* limit a number of return value interpretations by the caller .
*
* 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
* async_complete_cb .
*
* 3. valid pointer in case of succesfult RX path
*
* 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 )
{
int rc ;
struct pn533_sync_cmd_response arg ;
init_completion ( & arg . done ) ;
rc = pn533_send_cmd_async ( dev , cmd_code , req ,
pn533_send_sync_complete , & arg ) ;
if ( rc ) {
dev_kfree_skb ( req ) ;
return ERR_PTR ( rc ) ;
}
wait_for_completion ( & arg . done ) ;
return arg . resp ;
}
2011-07-02 02:31:37 +04:00
static void pn533_send_complete ( struct urb * urb )
{
struct pn533 * dev = urb - > context ;
switch ( urb - > status ) {
case 0 :
2012-12-10 17:42:54 +04:00
break ; /* success */
2011-07-02 02:31:37 +04:00
case - ECONNRESET :
case - ENOENT :
2012-12-10 17:42:49 +04:00
nfc_dev_dbg ( & dev - > interface - > dev ,
2012-12-10 17:42:54 +04:00
" The urb has been stopped (status %d) " ,
urb - > status ) ;
2011-07-02 02:31:37 +04:00
break ;
2012-12-10 17:42:54 +04:00
case - ESHUTDOWN :
2011-07-02 02:31:37 +04:00
default :
2012-12-10 17:42:54 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" Urb failure (status %d) " , urb - > status ) ;
2011-07-02 02:31:37 +04:00
}
}
2013-04-03 10:02:14 +04:00
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 ) ;
}
2012-12-10 17:43:01 +04:00
static struct sk_buff * pn533_alloc_skb ( struct pn533 * dev , unsigned int size )
2012-11-26 17:18:37 +04:00
{
struct sk_buff * skb ;
2012-12-10 17:43:01 +04:00
skb = alloc_skb ( dev - > ops - > tx_header_len +
2012-11-26 17:18:37 +04:00
size +
2012-12-10 17:43:01 +04:00
dev - > ops - > tx_tail_len , GFP_KERNEL ) ;
2012-11-26 17:18:37 +04:00
if ( skb )
2012-12-10 17:43:01 +04:00
skb_reserve ( skb , dev - > ops - > tx_header_len ) ;
2012-11-26 17:18:37 +04:00
return skb ;
}
2011-07-02 02:31:37 +04:00
struct pn533_target_type_a {
__be16 sens_res ;
u8 sel_res ;
u8 nfcid_len ;
u8 nfcid_data [ ] ;
} __packed ;
# define PN533_TYPE_A_SENS_RES_NFCID1(x) ((u8)((be16_to_cpu(x) & 0x00C0) >> 6))
# define PN533_TYPE_A_SENS_RES_SSD(x) ((u8)((be16_to_cpu(x) & 0x001F) >> 0))
# define PN533_TYPE_A_SENS_RES_PLATCONF(x) ((u8)((be16_to_cpu(x) & 0x0F00) >> 8))
# define PN533_TYPE_A_SENS_RES_SSD_JEWEL 0x00
# define PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL 0x0C
# define PN533_TYPE_A_SEL_PROT(x) (((x) & 0x60) >> 5)
# define PN533_TYPE_A_SEL_CASCADE(x) (((x) & 0x04) >> 2)
# define PN533_TYPE_A_SEL_PROT_MIFARE 0
# define PN533_TYPE_A_SEL_PROT_ISO14443 1
# define PN533_TYPE_A_SEL_PROT_DEP 2
# define PN533_TYPE_A_SEL_PROT_ISO14443_DEP 3
static bool pn533_target_type_a_is_valid ( struct pn533_target_type_a * type_a ,
int target_data_len )
{
u8 ssd ;
u8 platconf ;
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 */
/* Requirement 4.6.3.3 from NFC Forum Digital Spec */
ssd = PN533_TYPE_A_SENS_RES_SSD ( type_a - > sens_res ) ;
platconf = PN533_TYPE_A_SENS_RES_PLATCONF ( type_a - > sens_res ) ;
if ( ( ssd = = PN533_TYPE_A_SENS_RES_SSD_JEWEL & &
2012-12-10 17:42:51 +04:00
platconf ! = PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL ) | |
( ssd ! = PN533_TYPE_A_SENS_RES_SSD_JEWEL & &
platconf = = PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL ) )
2011-07-02 02:31:37 +04:00
return false ;
/* Requirements 4.8.2.1, 4.8.2.3, 4.8.2.5 and 4.8.2.7 from NFC Forum */
if ( PN533_TYPE_A_SEL_CASCADE ( type_a - > sel_res ) ! = 0 )
return false ;
return true ;
}
static int pn533_target_found_type_a ( struct nfc_target * nfc_tgt , u8 * tgt_data ,
int tgt_data_len )
{
struct pn533_target_type_a * tgt_type_a ;
2012-12-10 17:42:50 +04:00
tgt_type_a = ( struct pn533_target_type_a * ) tgt_data ;
2011-07-02 02:31:37 +04:00
if ( ! pn533_target_type_a_is_valid ( tgt_type_a , tgt_data_len ) )
return - EPROTO ;
switch ( PN533_TYPE_A_SEL_PROT ( tgt_type_a - > sel_res ) ) {
case PN533_TYPE_A_SEL_PROT_MIFARE :
nfc_tgt - > supported_protocols = NFC_PROTO_MIFARE_MASK ;
break ;
case PN533_TYPE_A_SEL_PROT_ISO14443 :
nfc_tgt - > supported_protocols = NFC_PROTO_ISO14443_MASK ;
break ;
case PN533_TYPE_A_SEL_PROT_DEP :
nfc_tgt - > supported_protocols = NFC_PROTO_NFC_DEP_MASK ;
break ;
case PN533_TYPE_A_SEL_PROT_ISO14443_DEP :
nfc_tgt - > supported_protocols = NFC_PROTO_ISO14443_MASK |
NFC_PROTO_NFC_DEP_MASK ;
break ;
}
nfc_tgt - > sens_res = be16_to_cpu ( tgt_type_a - > sens_res ) ;
nfc_tgt - > sel_res = tgt_type_a - > sel_res ;
2012-03-05 04:03:33 +04:00
nfc_tgt - > nfcid1_len = tgt_type_a - > nfcid_len ;
memcpy ( nfc_tgt - > nfcid1 , tgt_type_a - > nfcid_data , nfc_tgt - > nfcid1_len ) ;
2011-07-02 02:31:37 +04:00
return 0 ;
}
struct pn533_target_felica {
u8 pol_res ;
u8 opcode ;
2013-05-27 17:29:11 +04:00
u8 nfcid2 [ NFC_NFCID2_MAXSIZE ] ;
2011-07-02 02:31:37 +04:00
u8 pad [ 8 ] ;
/* optional */
u8 syst_code [ ] ;
} __packed ;
# define PN533_FELICA_SENSF_NFCID2_DEP_B1 0x01
# define PN533_FELICA_SENSF_NFCID2_DEP_B2 0xFE
static bool pn533_target_felica_is_valid ( struct pn533_target_felica * felica ,
int target_data_len )
{
if ( target_data_len < sizeof ( struct pn533_target_felica ) )
return false ;
if ( felica - > opcode ! = PN533_FELICA_OPC_SENSF_RES )
return false ;
return true ;
}
static int pn533_target_found_felica ( struct nfc_target * nfc_tgt , u8 * tgt_data ,
int tgt_data_len )
{
struct pn533_target_felica * tgt_felica ;
2012-12-10 17:42:50 +04:00
tgt_felica = ( struct pn533_target_felica * ) tgt_data ;
2011-07-02 02:31:37 +04:00
if ( ! pn533_target_felica_is_valid ( tgt_felica , tgt_data_len ) )
return - EPROTO ;
2012-12-10 17:42:51 +04:00
if ( ( tgt_felica - > nfcid2 [ 0 ] = = PN533_FELICA_SENSF_NFCID2_DEP_B1 ) & &
( tgt_felica - > nfcid2 [ 1 ] = = PN533_FELICA_SENSF_NFCID2_DEP_B2 ) )
2011-07-02 02:31:37 +04:00
nfc_tgt - > supported_protocols = NFC_PROTO_NFC_DEP_MASK ;
else
nfc_tgt - > supported_protocols = NFC_PROTO_FELICA_MASK ;
2012-03-05 04:03:45 +04:00
memcpy ( nfc_tgt - > sensf_res , & tgt_felica - > opcode , 9 ) ;
nfc_tgt - > sensf_res_len = 9 ;
2013-05-27 17:29:11 +04:00
memcpy ( nfc_tgt - > nfcid2 , tgt_felica - > nfcid2 , NFC_NFCID2_MAXSIZE ) ;
nfc_tgt - > nfcid2_len = NFC_NFCID2_MAXSIZE ;
2011-07-02 02:31:37 +04:00
return 0 ;
}
struct pn533_target_jewel {
__be16 sens_res ;
u8 jewelid [ 4 ] ;
} __packed ;
static bool pn533_target_jewel_is_valid ( struct pn533_target_jewel * jewel ,
int target_data_len )
{
u8 ssd ;
u8 platconf ;
if ( target_data_len < sizeof ( struct pn533_target_jewel ) )
return false ;
/* Requirement 4.6.3.3 from NFC Forum Digital Spec */
ssd = PN533_TYPE_A_SENS_RES_SSD ( jewel - > sens_res ) ;
platconf = PN533_TYPE_A_SENS_RES_PLATCONF ( jewel - > sens_res ) ;
if ( ( ssd = = PN533_TYPE_A_SENS_RES_SSD_JEWEL & &
2012-12-10 17:42:51 +04:00
platconf ! = PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL ) | |
( ssd ! = PN533_TYPE_A_SENS_RES_SSD_JEWEL & &
platconf = = PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL ) )
2011-07-02 02:31:37 +04:00
return false ;
return true ;
}
static int pn533_target_found_jewel ( struct nfc_target * nfc_tgt , u8 * tgt_data ,
int tgt_data_len )
{
struct pn533_target_jewel * tgt_jewel ;
2012-12-10 17:42:50 +04:00
tgt_jewel = ( struct pn533_target_jewel * ) tgt_data ;
2011-07-02 02:31:37 +04:00
if ( ! pn533_target_jewel_is_valid ( tgt_jewel , tgt_data_len ) )
return - EPROTO ;
nfc_tgt - > supported_protocols = NFC_PROTO_JEWEL_MASK ;
nfc_tgt - > sens_res = be16_to_cpu ( tgt_jewel - > sens_res ) ;
2012-03-05 04:03:46 +04:00
nfc_tgt - > nfcid1_len = 4 ;
memcpy ( nfc_tgt - > nfcid1 , tgt_jewel - > jewelid , nfc_tgt - > nfcid1_len ) ;
2011-07-02 02:31:37 +04:00
return 0 ;
}
struct pn533_type_b_prot_info {
u8 bitrate ;
u8 fsci_type ;
u8 fwi_adc_fo ;
} __packed ;
# define PN533_TYPE_B_PROT_FCSI(x) (((x) & 0xF0) >> 4)
# define PN533_TYPE_B_PROT_TYPE(x) (((x) & 0x0F) >> 0)
# define PN533_TYPE_B_PROT_TYPE_RFU_MASK 0x8
struct pn533_type_b_sens_res {
u8 opcode ;
u8 nfcid [ 4 ] ;
u8 appdata [ 4 ] ;
struct pn533_type_b_prot_info prot_info ;
} __packed ;
# define PN533_TYPE_B_OPC_SENSB_RES 0x50
struct pn533_target_type_b {
struct pn533_type_b_sens_res sensb_res ;
u8 attrib_res_len ;
u8 attrib_res [ ] ;
} __packed ;
static bool pn533_target_type_b_is_valid ( struct pn533_target_type_b * type_b ,
int target_data_len )
{
if ( target_data_len < sizeof ( struct pn533_target_type_b ) )
return false ;
if ( type_b - > sensb_res . opcode ! = PN533_TYPE_B_OPC_SENSB_RES )
return false ;
if ( PN533_TYPE_B_PROT_TYPE ( type_b - > sensb_res . prot_info . fsci_type ) &
PN533_TYPE_B_PROT_TYPE_RFU_MASK )
return false ;
return true ;
}
static int pn533_target_found_type_b ( struct nfc_target * nfc_tgt , u8 * tgt_data ,
int tgt_data_len )
{
struct pn533_target_type_b * tgt_type_b ;
2012-12-10 17:42:50 +04:00
tgt_type_b = ( struct pn533_target_type_b * ) tgt_data ;
2011-07-02 02:31:37 +04:00
if ( ! pn533_target_type_b_is_valid ( tgt_type_b , tgt_data_len ) )
return - EPROTO ;
2012-07-04 02:14:04 +04:00
nfc_tgt - > supported_protocols = NFC_PROTO_ISO14443_B_MASK ;
2011-07-02 02:31:37 +04:00
return 0 ;
}
2012-12-10 17:42:48 +04:00
static int pn533_target_found ( struct pn533 * dev , u8 tg , u8 * tgdata ,
int tgdata_len )
2011-07-02 02:31:37 +04:00
{
struct nfc_target nfc_tgt ;
int rc ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s - modulation=%d " , __func__ ,
2012-12-10 17:42:48 +04:00
dev - > poll_mod_curr ) ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:48 +04:00
if ( tg ! = 1 )
2011-07-02 02:31:37 +04:00
return - EPROTO ;
2012-03-05 04:03:39 +04:00
memset ( & nfc_tgt , 0 , sizeof ( struct nfc_target ) ) ;
2011-07-02 02:31:37 +04:00
switch ( dev - > poll_mod_curr ) {
case PN533_POLL_MOD_106KBPS_A :
2012-12-10 17:42:48 +04:00
rc = pn533_target_found_type_a ( & nfc_tgt , tgdata , tgdata_len ) ;
2011-07-02 02:31:37 +04:00
break ;
case PN533_POLL_MOD_212KBPS_FELICA :
case PN533_POLL_MOD_424KBPS_FELICA :
2012-12-10 17:42:48 +04:00
rc = pn533_target_found_felica ( & nfc_tgt , tgdata , tgdata_len ) ;
2011-07-02 02:31:37 +04:00
break ;
case PN533_POLL_MOD_106KBPS_JEWEL :
2012-12-10 17:42:48 +04:00
rc = pn533_target_found_jewel ( & nfc_tgt , tgdata , tgdata_len ) ;
2011-07-02 02:31:37 +04:00
break ;
case PN533_POLL_MOD_847KBPS_B :
2012-12-10 17:42:48 +04:00
rc = pn533_target_found_type_b ( & nfc_tgt , tgdata , tgdata_len ) ;
2011-07-02 02:31:37 +04:00
break ;
default :
2012-12-10 17:42:48 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" Unknown current poll modulation " ) ;
2011-07-02 02:31:37 +04:00
return - EPROTO ;
}
if ( rc )
return rc ;
if ( ! ( nfc_tgt . supported_protocols & dev - > poll_protocols ) ) {
2012-12-10 17:42:48 +04:00
nfc_dev_dbg ( & dev - > interface - > dev ,
" The Tg found doesn't have the desired protocol " ) ;
2011-07-02 02:31:37 +04:00
return - EAGAIN ;
}
2012-12-10 17:42:48 +04:00
nfc_dev_dbg ( & dev - > interface - > dev ,
" Target found - supported protocols: 0x%x " ,
nfc_tgt . supported_protocols ) ;
2011-07-02 02:31:37 +04:00
dev - > tgt_available_prots = nfc_tgt . supported_protocols ;
nfc_targets_found ( dev - > nfc_dev , & nfc_tgt , 1 ) ;
return 0 ;
}
2012-05-30 19:20:25 +04:00
static inline void pn533_poll_next_mod ( struct pn533 * dev )
{
dev - > poll_mod_curr = ( dev - > poll_mod_curr + 1 ) % dev - > poll_mod_count ;
}
2011-07-02 02:31:37 +04:00
static void pn533_poll_reset_mod_list ( struct pn533 * dev )
{
dev - > poll_mod_count = 0 ;
}
static void pn533_poll_add_mod ( struct pn533 * dev , u8 mod_index )
{
dev - > poll_mod_active [ dev - > poll_mod_count ] =
2012-12-10 17:42:50 +04:00
( struct pn533_poll_modulations * ) & poll_mod [ mod_index ] ;
2011-07-02 02:31:37 +04:00
dev - > poll_mod_count + + ;
}
2012-05-30 19:20:25 +04:00
static void pn533_poll_create_mod_list ( struct pn533 * dev ,
u32 im_protocols , u32 tm_protocols )
2011-07-02 02:31:37 +04:00
{
pn533_poll_reset_mod_list ( dev ) ;
2012-12-10 17:42:52 +04:00
if ( ( im_protocols & NFC_PROTO_MIFARE_MASK ) | |
( im_protocols & NFC_PROTO_ISO14443_MASK ) | |
( im_protocols & NFC_PROTO_NFC_DEP_MASK ) )
2011-07-02 02:31:37 +04:00
pn533_poll_add_mod ( dev , PN533_POLL_MOD_106KBPS_A ) ;
2012-12-10 17:42:52 +04:00
if ( im_protocols & NFC_PROTO_FELICA_MASK | |
im_protocols & NFC_PROTO_NFC_DEP_MASK ) {
2011-07-02 02:31:37 +04:00
pn533_poll_add_mod ( dev , PN533_POLL_MOD_212KBPS_FELICA ) ;
pn533_poll_add_mod ( dev , PN533_POLL_MOD_424KBPS_FELICA ) ;
}
2012-05-30 19:20:25 +04:00
if ( im_protocols & NFC_PROTO_JEWEL_MASK )
2011-07-02 02:31:37 +04:00
pn533_poll_add_mod ( dev , PN533_POLL_MOD_106KBPS_JEWEL ) ;
2012-07-04 02:14:04 +04:00
if ( im_protocols & NFC_PROTO_ISO14443_B_MASK )
2011-07-02 02:31:37 +04:00
pn533_poll_add_mod ( dev , PN533_POLL_MOD_847KBPS_B ) ;
2012-05-30 19:20:25 +04:00
if ( tm_protocols )
pn533_poll_add_mod ( dev , PN533_LISTEN_MOD ) ;
2011-07-02 02:31:37 +04:00
}
2012-12-10 17:42:48 +04:00
static int pn533_start_poll_complete ( struct pn533 * dev , struct sk_buff * resp )
2011-07-02 02:31:37 +04:00
{
2012-12-10 17:42:48 +04:00
u8 nbtg , tg , * tgdata ;
int rc , tgdata_len ;
2011-07-02 02:31:37 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:42:48 +04:00
nbtg = resp - > data [ 0 ] ;
tg = resp - > data [ 1 ] ;
tgdata = & resp - > data [ 2 ] ;
tgdata_len = resp - > len - 2 ; /* nbtg + tg */
if ( nbtg ) {
rc = pn533_target_found ( dev , tg , tgdata , tgdata_len ) ;
2011-07-02 02:31:37 +04:00
/* We must stop the poll after a valid target found */
2012-05-30 19:20:25 +04:00
if ( rc = = 0 ) {
pn533_poll_reset_mod_list ( dev ) ;
return 0 ;
}
2011-07-02 02:31:37 +04:00
}
2012-05-30 19:20:25 +04:00
return - EAGAIN ;
2011-07-02 02:31:37 +04:00
}
2012-12-10 17:43:01 +04:00
static struct sk_buff * pn533_alloc_poll_tg_frame ( struct pn533 * dev )
2012-05-31 01:54:55 +04:00
{
2012-12-10 17:42:48 +04:00
struct sk_buff * skb ;
u8 * felica , * nfcid3 , * gb ;
2012-12-10 17:43:01 +04:00
u8 * gbytes = dev - > gb ;
size_t gbytes_len = dev - > gb_len ;
2012-05-30 03:48:46 +04:00
u8 felica_params [ 18 ] = { 0x1 , 0xfe , /* DEP */
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , /* random */
0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
0xff , 0xff } ; /* System code */
2012-12-10 17:42:48 +04:00
2012-05-30 03:48:46 +04:00
u8 mifare_params [ 6 ] = { 0x1 , 0x1 , /* SENS_RES */
0x0 , 0x0 , 0x0 ,
0x40 } ; /* SEL_RES for DEP */
2012-05-31 01:54:55 +04:00
2012-12-10 17:42:48 +04:00
unsigned int skb_len = 36 + /* mode (1), mifare (6),
felica ( 18 ) , nfcid3 ( 10 ) , gb_len ( 1 ) */
gbytes_len +
1 ; /* len Tk*/
2012-05-31 01:54:55 +04:00
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , skb_len ) ;
2012-12-10 17:42:48 +04:00
if ( ! skb )
return NULL ;
2012-05-31 01:54:55 +04:00
/* DEP support only */
2013-02-05 13:08:35 +04:00
* skb_put ( skb , 1 ) = PN533_INIT_TARGET_DEP ;
2012-12-10 17:42:48 +04:00
/* MIFARE params */
memcpy ( skb_put ( skb , 6 ) , mifare_params , 6 ) ;
2012-05-30 03:48:46 +04:00
/* Felica params */
2012-12-10 17:42:48 +04:00
felica = skb_put ( skb , 18 ) ;
memcpy ( felica , felica_params , 18 ) ;
get_random_bytes ( felica + 2 , 6 ) ;
2012-05-30 03:48:46 +04:00
/* NFCID3 */
2012-12-10 17:42:48 +04:00
nfcid3 = skb_put ( skb , 10 ) ;
memset ( nfcid3 , 0 , 10 ) ;
memcpy ( nfcid3 , felica , 8 ) ;
2012-05-30 03:48:46 +04:00
/* General bytes */
2012-12-10 17:42:48 +04:00
* skb_put ( skb , 1 ) = gbytes_len ;
2012-05-30 03:48:46 +04:00
2012-12-10 17:42:48 +04:00
gb = skb_put ( skb , gbytes_len ) ;
memcpy ( gb , gbytes , gbytes_len ) ;
2012-05-31 01:54:55 +04:00
2012-12-10 17:42:48 +04:00
/* Len Tk */
* skb_put ( skb , 1 ) = 0 ;
2012-05-30 03:48:46 +04:00
2012-12-10 17:42:48 +04:00
return skb ;
2012-05-31 01:54:55 +04:00
}
2012-11-26 17:18:32 +04:00
# define PN533_CMD_DATAEXCH_HEAD_LEN 1
2012-05-31 02:07:51 +04:00
# define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
static int pn533_tm_get_data_complete ( struct pn533 * dev , void * arg ,
2012-12-10 17:42:44 +04:00
struct sk_buff * resp )
2012-05-31 02:07:51 +04:00
{
2012-12-10 17:42:44 +04:00
u8 status ;
2012-05-31 02:07:51 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:42:44 +04:00
if ( IS_ERR ( resp ) )
return PTR_ERR ( resp ) ;
2012-05-31 02:07:51 +04:00
2012-12-10 17:42:44 +04:00
status = resp - > data [ 0 ] ;
skb_pull ( resp , sizeof ( status ) ) ;
2012-05-31 02:07:51 +04:00
2012-12-10 17:42:44 +04:00
if ( status ! = 0 ) {
2012-05-31 02:07:51 +04:00
nfc_tm_deactivated ( dev - > nfc_dev ) ;
2012-05-31 22:01:32 +04:00
dev - > tgt_mode = 0 ;
2012-12-10 17:42:44 +04:00
dev_kfree_skb ( resp ) ;
2012-05-31 02:07:51 +04:00
return 0 ;
}
2012-12-10 17:42:44 +04:00
return nfc_tm_data_received ( dev - > nfc_dev , resp ) ;
2012-05-31 02:07:51 +04:00
}
static void pn533_wq_tg_get_data ( struct work_struct * work )
{
struct pn533 * dev = container_of ( work , struct pn533 , tg_work ) ;
2012-12-10 17:42:44 +04:00
struct sk_buff * skb ;
int rc ;
2012-05-31 02:07:51 +04:00
2012-12-10 17:42:44 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-05-31 02:07:51 +04:00
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , 0 ) ;
2012-12-10 17:42:44 +04:00
if ( ! skb )
2012-05-31 02:07:51 +04:00
return ;
2012-12-10 17:42:44 +04:00
rc = pn533_send_data_async ( dev , PN533_CMD_TG_GET_DATA , skb ,
pn533_tm_get_data_complete , NULL ) ;
2012-05-31 02:07:51 +04:00
2012-12-10 17:42:44 +04:00
if ( rc < 0 )
dev_kfree_skb ( skb ) ;
2012-05-31 02:07:51 +04:00
return ;
}
2012-06-01 15:21:13 +04:00
# define ATR_REQ_GB_OFFSET 17
2012-12-10 17:42:48 +04:00
static int pn533_init_target_complete ( struct pn533 * dev , struct sk_buff * resp )
2012-05-15 17:57:06 +04:00
{
2012-12-10 17:42:48 +04:00
u8 mode , * cmd , comm_mode = NFC_COMM_PASSIVE , * gb ;
2012-06-01 15:21:13 +04:00
size_t gb_len ;
2012-05-31 02:07:51 +04:00
int rc ;
2012-05-31 01:54:55 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:42:48 +04:00
if ( resp - > len < ATR_REQ_GB_OFFSET + 1 )
2012-06-01 15:21:13 +04:00
return - EINVAL ;
2012-12-10 17:42:48 +04:00
mode = resp - > data [ 0 ] ;
cmd = & resp - > data [ 1 ] ;
2012-05-31 01:54:55 +04:00
2012-12-10 17:42:48 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " Target mode 0x%x len %d \n " ,
mode , resp - > len ) ;
2012-05-31 01:54:55 +04:00
2012-12-10 17:42:48 +04:00
if ( ( mode & PN533_INIT_TARGET_RESP_FRAME_MASK ) = =
PN533_INIT_TARGET_RESP_ACTIVE )
2012-06-01 15:21:13 +04:00
comm_mode = NFC_COMM_ACTIVE ;
2012-12-10 17:42:48 +04:00
if ( ( mode & PN533_INIT_TARGET_RESP_DEP ) = = 0 ) /* Only DEP supported */
2012-06-01 15:21:13 +04:00
return - EOPNOTSUPP ;
2012-12-10 17:42:48 +04:00
gb = cmd + ATR_REQ_GB_OFFSET ;
gb_len = resp - > len - ( ATR_REQ_GB_OFFSET + 1 ) ;
2012-06-01 15:21:13 +04:00
2012-05-31 02:07:51 +04:00
rc = nfc_tm_activated ( dev - > nfc_dev , NFC_PROTO_NFC_DEP_MASK ,
comm_mode , gb , gb_len ) ;
if ( rc < 0 ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Error when signaling target activation " ) ;
return rc ;
}
2012-05-31 22:01:32 +04:00
dev - > tgt_mode = 1 ;
2012-05-31 02:07:51 +04:00
queue_work ( dev - > wq , & dev - > tg_work ) ;
return 0 ;
2012-05-15 17:57:06 +04:00
}
2012-05-30 19:20:25 +04:00
static void pn533_listen_mode_timer ( unsigned long data )
2012-05-31 01:54:55 +04:00
{
2012-12-10 17:42:50 +04:00
struct pn533 * dev = ( struct pn533 * ) data ;
2012-05-30 19:20:25 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " Listen mode timeout " ) ;
dev - > cancel_listen = 1 ;
pn533_poll_next_mod ( dev ) ;
queue_work ( dev - > wq , & dev - > poll_work ) ;
}
2013-06-26 20:16:21 +04:00
static int pn533_rf_complete ( struct pn533 * dev , void * arg ,
struct sk_buff * resp )
{
int rc = 0 ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
if ( IS_ERR ( resp ) ) {
rc = PTR_ERR ( resp ) ;
nfc_dev_err ( & dev - > interface - > dev , " %s RF setting error %d " ,
__func__ , rc ) ;
return rc ;
}
queue_work ( dev - > wq , & dev - > poll_work ) ;
dev_kfree_skb ( resp ) ;
return rc ;
}
static void pn533_wq_rf ( struct work_struct * work )
{
struct pn533 * dev = container_of ( work , struct pn533 , rf_work ) ;
struct sk_buff * skb ;
int rc ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
skb = pn533_alloc_skb ( dev , 2 ) ;
if ( ! skb )
return ;
* skb_put ( skb , 1 ) = PN533_CFGITEM_RF_FIELD ;
2013-07-01 19:26:58 +04:00
* skb_put ( skb , 1 ) = PN533_CFGITEM_RF_FIELD_AUTO_RFCA ;
2013-06-26 20:16:21 +04:00
rc = pn533_send_cmd_async ( dev , PN533_CMD_RF_CONFIGURATION , skb ,
pn533_rf_complete , NULL ) ;
if ( rc < 0 ) {
dev_kfree_skb ( skb ) ;
nfc_dev_err ( & dev - > interface - > dev , " RF setting error %d " , rc ) ;
}
return ;
}
2012-05-30 19:20:25 +04:00
static int pn533_poll_complete ( struct pn533 * dev , void * arg ,
2012-12-10 17:42:48 +04:00
struct sk_buff * resp )
2012-05-30 19:20:25 +04:00
{
struct pn533_poll_modulations * cur_mod ;
2012-05-31 01:54:55 +04:00
int rc ;
2012-05-30 19:20:25 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-05-31 01:54:55 +04:00
2012-12-10 17:42:48 +04:00
if ( IS_ERR ( resp ) ) {
rc = PTR_ERR ( resp ) ;
nfc_dev_err ( & dev - > interface - > dev , " %s Poll complete error %d " ,
__func__ , rc ) ;
if ( rc = = - ENOENT ) {
if ( dev - > poll_mod_count ! = 0 )
return rc ;
else
goto stop_poll ;
} else if ( rc < 0 ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Error %d when running poll " , rc ) ;
goto stop_poll ;
}
2012-05-30 19:20:25 +04:00
}
2012-05-31 01:54:55 +04:00
2012-05-30 19:20:25 +04:00
cur_mod = dev - > poll_mod_active [ dev - > poll_mod_curr ] ;
2012-12-10 17:42:48 +04:00
if ( cur_mod - > len = = 0 ) { /* Target mode */
2012-05-30 19:20:25 +04:00
del_timer ( & dev - > listen_timer ) ;
2012-12-10 17:42:48 +04:00
rc = pn533_init_target_complete ( dev , resp ) ;
goto done ;
2012-05-30 19:20:25 +04:00
}
2012-12-10 17:42:48 +04:00
/* Initiator mode */
rc = pn533_start_poll_complete ( dev , resp ) ;
if ( ! rc )
goto done ;
2012-05-30 19:20:25 +04:00
2013-04-03 10:02:00 +04:00
if ( ! dev - > poll_mod_count ) {
2013-05-21 18:13:12 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " Polling has been stopped. " ) ;
2013-04-03 10:02:00 +04:00
goto done ;
}
2012-12-10 17:42:48 +04:00
pn533_poll_next_mod ( dev ) ;
2013-06-26 20:16:21 +04:00
/* Not target found, turn radio off */
queue_work ( dev - > wq , & dev - > rf_work ) ;
2012-05-30 19:20:25 +04:00
2012-12-10 17:42:48 +04:00
done :
dev_kfree_skb ( resp ) ;
return rc ;
2012-05-30 19:20:25 +04:00
stop_poll :
2012-12-10 17:42:48 +04:00
nfc_dev_err ( & dev - > interface - > dev , " Polling operation has been stopped " ) ;
2012-05-30 19:20:25 +04:00
pn533_poll_reset_mod_list ( dev ) ;
dev - > poll_protocols = 0 ;
2012-12-10 17:42:48 +04:00
return rc ;
2012-05-31 01:54:55 +04:00
}
2012-12-10 17:43:01 +04:00
static struct sk_buff * pn533_alloc_poll_in_frame ( struct pn533 * dev ,
struct pn533_poll_modulations * mod )
2011-07-02 02:31:37 +04:00
{
2012-12-10 17:42:48 +04:00
struct sk_buff * skb ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , mod - > len ) ;
2012-12-10 17:42:48 +04:00
if ( ! skb )
return NULL ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:48 +04:00
memcpy ( skb_put ( skb , mod - > len ) , & mod - > data , mod - > len ) ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:48 +04:00
return skb ;
2012-05-30 19:20:25 +04:00
}
2011-07-02 02:31:37 +04:00
2012-05-30 19:20:25 +04:00
static int pn533_send_poll_frame ( struct pn533 * dev )
{
2012-12-10 17:42:48 +04:00
struct pn533_poll_modulations * mod ;
struct sk_buff * skb ;
2012-05-30 19:20:25 +04:00
int rc ;
2012-12-10 17:42:48 +04:00
u8 cmd_code ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:48 +04:00
mod = dev - > poll_mod_active [ dev - > poll_mod_curr ] ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:48 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s mod len %d \n " ,
__func__ , mod - > len ) ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:48 +04:00
if ( mod - > len = = 0 ) { /* Listen mode */
cmd_code = PN533_CMD_TG_INIT_AS_TARGET ;
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_poll_tg_frame ( dev ) ;
2012-12-10 17:42:48 +04:00
} else { /* Polling mode */
cmd_code = PN533_CMD_IN_LIST_PASSIVE_TARGET ;
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_poll_in_frame ( dev , mod ) ;
2012-12-10 17:42:48 +04:00
}
if ( ! skb ) {
nfc_dev_err ( & dev - > interface - > dev , " Failed to allocate skb. " ) ;
return - ENOMEM ;
}
rc = pn533_send_cmd_async ( dev , cmd_code , skb , pn533_poll_complete ,
NULL ) ;
if ( rc < 0 ) {
dev_kfree_skb ( skb ) ;
2012-05-30 19:20:25 +04:00
nfc_dev_err ( & dev - > interface - > dev , " Polling loop error %d " , rc ) ;
2012-12-10 17:42:48 +04:00
}
2011-07-02 02:31:37 +04:00
2012-05-30 19:20:25 +04:00
return rc ;
}
static void pn533_wq_poll ( struct work_struct * work )
{
struct pn533 * dev = container_of ( work , struct pn533 , poll_work ) ;
struct pn533_poll_modulations * cur_mod ;
int rc ;
cur_mod = dev - > poll_mod_active [ dev - > poll_mod_curr ] ;
nfc_dev_dbg ( & dev - > interface - > dev ,
" %s cancel_listen %d modulation len %d " ,
__func__ , dev - > cancel_listen , cur_mod - > len ) ;
if ( dev - > cancel_listen = = 1 ) {
dev - > cancel_listen = 0 ;
2013-04-03 10:02:14 +04:00
pn533_abort_cmd ( dev , GFP_ATOMIC ) ;
2011-07-02 02:31:37 +04:00
}
2012-05-30 19:20:25 +04:00
rc = pn533_send_poll_frame ( dev ) ;
if ( rc )
return ;
2011-07-02 02:31:37 +04:00
2012-05-30 19:20:25 +04:00
if ( cur_mod - > len = = 0 & & dev - > poll_mod_count > 1 )
mod_timer ( & dev - > listen_timer , jiffies + PN533_LISTEN_TIME * HZ ) ;
2011-07-02 02:31:37 +04:00
2012-05-30 19:20:25 +04:00
return ;
2011-07-02 02:31:37 +04:00
}
2012-05-15 17:57:06 +04:00
static int pn533_start_poll ( struct nfc_dev * nfc_dev ,
u32 im_protocols , u32 tm_protocols )
{
struct pn533 * dev = nfc_get_drvdata ( nfc_dev ) ;
nfc_dev_dbg ( & dev - > interface - > dev ,
" %s: im protocols 0x%x tm protocols 0x%x " ,
__func__ , im_protocols , tm_protocols ) ;
if ( dev - > tgt_active_prot ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Cannot poll with a target already activated " ) ;
return - EBUSY ;
}
2012-05-31 22:01:32 +04:00
if ( dev - > tgt_mode ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Cannot poll while already being activated " ) ;
return - EBUSY ;
}
2012-05-30 19:20:25 +04:00
if ( tm_protocols ) {
dev - > gb = nfc_get_local_general_bytes ( nfc_dev , & dev - > gb_len ) ;
if ( dev - > gb = = NULL )
tm_protocols = 0 ;
}
2012-05-31 01:54:55 +04:00
2012-05-30 19:20:25 +04:00
dev - > poll_mod_curr = 0 ;
pn533_poll_create_mod_list ( dev , im_protocols , tm_protocols ) ;
dev - > poll_protocols = im_protocols ;
dev - > listen_protocols = tm_protocols ;
2012-05-31 01:54:55 +04:00
2012-05-30 19:20:25 +04:00
return pn533_send_poll_frame ( dev ) ;
2012-05-15 17:57:06 +04:00
}
2011-07-02 02:31:37 +04:00
static void pn533_stop_poll ( struct nfc_dev * nfc_dev )
{
struct pn533 * dev = nfc_get_drvdata ( nfc_dev ) ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-05-30 19:20:25 +04:00
del_timer ( & dev - > listen_timer ) ;
2011-07-02 02:31:37 +04:00
if ( ! dev - > poll_mod_count ) {
2012-12-10 17:42:49 +04:00
nfc_dev_dbg ( & dev - > interface - > dev ,
" Polling operation was not running " ) ;
2011-07-02 02:31:37 +04:00
return ;
}
2013-04-03 10:02:14 +04:00
pn533_abort_cmd ( dev , GFP_KERNEL ) ;
2012-05-21 18:20:01 +04:00
pn533_poll_reset_mod_list ( dev ) ;
2011-07-02 02:31:37 +04:00
}
static int pn533_activate_target_nfcdep ( struct pn533 * dev )
{
2012-11-26 17:18:38 +04:00
struct pn533_cmd_activate_response * rsp ;
2011-12-14 19:43:10 +04:00
u16 gt_len ;
2011-07-02 02:31:37 +04:00
int rc ;
2012-11-26 17:18:38 +04:00
struct sk_buff * skb ;
struct sk_buff * resp ;
2011-07-02 02:31:37 +04:00
2012-11-26 17:18:38 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , sizeof ( u8 ) * 2 ) ; /*TG + Next*/
2012-11-26 17:18:38 +04:00
if ( ! skb )
return - ENOMEM ;
2011-07-02 02:31:37 +04:00
2012-11-26 17:18:38 +04:00
* skb_put ( skb , sizeof ( u8 ) ) = 1 ; /* TG */
* skb_put ( skb , sizeof ( u8 ) ) = 0 ; /* Next */
2011-07-02 02:31:37 +04:00
2012-11-26 17:18:38 +04:00
resp = pn533_send_cmd_sync ( dev , PN533_CMD_IN_ATR , skb ) ;
if ( IS_ERR ( resp ) )
return PTR_ERR ( resp ) ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:50 +04:00
rsp = ( struct pn533_cmd_activate_response * ) resp - > data ;
2012-11-26 17:18:38 +04:00
rc = rsp - > status & PN533_CMD_RET_MASK ;
2012-12-21 13:39:01 +04:00
if ( rc ! = PN533_CMD_RET_SUCCESS ) {
2013-04-03 10:01:59 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" Target activation failed (error 0x%x) " , rc ) ;
2012-11-26 17:18:38 +04:00
dev_kfree_skb ( resp ) ;
2011-07-02 02:31:37 +04:00
return - EIO ;
2012-12-21 13:39:01 +04:00
}
2011-07-02 02:31:37 +04:00
2011-12-14 19:43:10 +04:00
/* ATR_RES general bytes are located at offset 16 */
2012-11-26 17:18:38 +04:00
gt_len = resp - > len - 16 ;
rc = nfc_set_remote_general_bytes ( dev - > nfc_dev , rsp - > gt , gt_len ) ;
2011-12-14 19:43:10 +04:00
2012-11-26 17:18:38 +04:00
dev_kfree_skb ( resp ) ;
2011-12-14 19:43:10 +04:00
return rc ;
2011-07-02 02:31:37 +04:00
}
2012-05-07 14:31:13 +04:00
static int pn533_activate_target ( struct nfc_dev * nfc_dev ,
struct nfc_target * target , u32 protocol )
2011-07-02 02:31:37 +04:00
{
struct pn533 * dev = nfc_get_drvdata ( nfc_dev ) ;
int rc ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s - protocol=%u " , __func__ ,
2012-12-10 17:42:51 +04:00
protocol ) ;
2011-07-02 02:31:37 +04:00
if ( dev - > poll_mod_count ) {
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" Cannot activate while polling " ) ;
2011-07-02 02:31:37 +04:00
return - EBUSY ;
}
if ( dev - > tgt_active_prot ) {
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" There is already an active target " ) ;
2011-07-02 02:31:37 +04:00
return - EBUSY ;
}
if ( ! dev - > tgt_available_prots ) {
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" There is no available target to activate " ) ;
2011-07-02 02:31:37 +04:00
return - EINVAL ;
}
if ( ! ( dev - > tgt_available_prots & ( 1 < < protocol ) ) ) {
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" Target doesn't support requested proto %u " ,
protocol ) ;
2011-07-02 02:31:37 +04:00
return - EINVAL ;
}
if ( protocol = = NFC_PROTO_NFC_DEP ) {
rc = pn533_activate_target_nfcdep ( dev ) ;
if ( rc ) {
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" Activating target with DEP failed %d " , rc ) ;
2011-07-02 02:31:37 +04:00
return rc ;
}
}
dev - > tgt_active_prot = protocol ;
dev - > tgt_available_prots = 0 ;
return 0 ;
}
2012-05-07 14:31:13 +04:00
static void pn533_deactivate_target ( struct nfc_dev * nfc_dev ,
struct nfc_target * target )
2011-07-02 02:31:37 +04:00
{
struct pn533 * dev = nfc_get_drvdata ( nfc_dev ) ;
2012-11-26 17:18:38 +04:00
struct sk_buff * skb ;
struct sk_buff * resp ;
2011-07-02 02:31:37 +04:00
int rc ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
if ( ! dev - > tgt_active_prot ) {
nfc_dev_err ( & dev - > interface - > dev , " There is no active target " ) ;
return ;
}
dev - > tgt_active_prot = 0 ;
2012-04-10 21:43:18 +04:00
skb_queue_purge ( & dev - > resp_q ) ;
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , sizeof ( u8 ) ) ;
2012-11-26 17:18:38 +04:00
if ( ! skb )
return ;
2011-07-02 02:31:37 +04:00
2012-11-26 17:18:38 +04:00
* skb_put ( skb , 1 ) = 1 ; /* TG*/
2011-07-02 02:31:37 +04:00
2012-11-26 17:18:38 +04:00
resp = pn533_send_cmd_sync ( dev , PN533_CMD_IN_RELEASE , skb ) ;
if ( IS_ERR ( resp ) )
2011-07-02 02:31:37 +04:00
return ;
2012-11-26 17:18:38 +04:00
rc = resp - > data [ 0 ] & PN533_CMD_RET_MASK ;
2011-07-02 02:31:37 +04:00
if ( rc ! = PN533_CMD_RET_SUCCESS )
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" Error 0x%x when releasing the target " , rc ) ;
2011-07-02 02:31:37 +04:00
2012-11-26 17:18:38 +04:00
dev_kfree_skb ( resp ) ;
2011-07-02 02:31:37 +04:00
return ;
}
2011-12-14 19:43:11 +04:00
static int pn533_in_dep_link_up_complete ( struct pn533 * dev , void * arg ,
2012-12-10 17:42:45 +04:00
struct sk_buff * resp )
2011-12-14 19:43:11 +04:00
{
2012-12-10 17:42:45 +04:00
struct pn533_cmd_jump_dep_response * rsp ;
2011-12-14 19:43:11 +04:00
u8 target_gt_len ;
int rc ;
2012-12-10 17:42:45 +04:00
u8 active = * ( u8 * ) arg ;
2012-10-11 16:04:00 +04:00
kfree ( arg ) ;
2011-12-14 19:43:11 +04:00
2012-12-10 17:42:45 +04:00
if ( IS_ERR ( resp ) )
return PTR_ERR ( resp ) ;
2011-12-14 19:43:11 +04:00
if ( dev - > tgt_available_prots & &
! ( dev - > tgt_available_prots & ( 1 < < NFC_PROTO_NFC_DEP ) ) ) {
nfc_dev_err ( & dev - > interface - > dev ,
2012-12-10 17:42:51 +04:00
" The target does not support DEP " ) ;
2012-12-10 17:42:45 +04:00
rc = - EINVAL ;
goto error ;
2011-12-14 19:43:11 +04:00
}
2012-12-10 17:42:45 +04:00
rsp = ( struct pn533_cmd_jump_dep_response * ) resp - > data ;
rc = rsp - > status & PN533_CMD_RET_MASK ;
2011-12-14 19:43:11 +04:00
if ( rc ! = PN533_CMD_RET_SUCCESS ) {
nfc_dev_err ( & dev - > interface - > dev ,
2013-04-03 10:01:59 +04:00
" Bringing DEP link up failed (error 0x%x) " , rc ) ;
2012-12-10 17:42:45 +04:00
goto error ;
2011-12-14 19:43:11 +04:00
}
if ( ! dev - > tgt_available_prots ) {
2012-12-10 17:42:45 +04:00
struct nfc_target nfc_target ;
2011-12-14 19:43:11 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " Creating new target " ) ;
nfc_target . supported_protocols = NFC_PROTO_NFC_DEP_MASK ;
2012-03-05 04:03:47 +04:00
nfc_target . nfcid1_len = 10 ;
2012-12-10 17:42:45 +04:00
memcpy ( nfc_target . nfcid1 , rsp - > nfcid3t , nfc_target . nfcid1_len ) ;
2011-12-14 19:43:11 +04:00
rc = nfc_targets_found ( dev - > nfc_dev , & nfc_target , 1 ) ;
if ( rc )
2012-12-10 17:42:45 +04:00
goto error ;
2011-12-14 19:43:11 +04:00
dev - > tgt_available_prots = 0 ;
}
dev - > tgt_active_prot = NFC_PROTO_NFC_DEP ;
/* ATR_RES general bytes are located at offset 17 */
2012-12-10 17:42:45 +04:00
target_gt_len = resp - > len - 17 ;
2011-12-14 19:43:11 +04:00
rc = nfc_set_remote_general_bytes ( dev - > nfc_dev ,
2012-12-10 17:42:45 +04:00
rsp - > gt , target_gt_len ) ;
2011-12-14 19:43:11 +04:00
if ( rc = = 0 )
rc = nfc_dep_link_is_up ( dev - > nfc_dev ,
2012-12-10 17:42:45 +04:00
dev - > nfc_dev - > targets [ 0 ] . idx ,
! active , NFC_RF_INITIATOR ) ;
2011-12-14 19:43:11 +04:00
2012-12-10 17:42:45 +04:00
error :
dev_kfree_skb ( resp ) ;
return rc ;
2011-12-14 19:43:11 +04:00
}
2013-06-26 20:16:21 +04:00
static int pn533_rf_field ( struct nfc_dev * nfc_dev , u8 rf ) ;
2012-05-29 23:45:21 +04:00
# define PASSIVE_DATA_LEN 5
2012-05-07 14:31:13 +04:00
static int pn533_dep_link_up ( struct nfc_dev * nfc_dev , struct nfc_target * target ,
2012-12-10 17:42:50 +04:00
u8 comm_mode , u8 * gb , size_t gb_len )
2011-12-14 19:43:11 +04:00
{
struct pn533 * dev = nfc_get_drvdata ( nfc_dev ) ;
2012-12-10 17:42:45 +04:00
struct sk_buff * skb ;
2013-07-01 12:58:12 +04:00
int rc , skb_len ;
u8 * next , * arg , nfcid3 [ NFC_NFCID3_MAXSIZE ] ;
2012-12-10 17:42:45 +04:00
2012-05-29 23:45:21 +04:00
u8 passive_data [ PASSIVE_DATA_LEN ] = { 0x00 , 0xff , 0xff , 0x00 , 0x3 } ;
2011-12-14 19:43:11 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
if ( dev - > poll_mod_count ) {
nfc_dev_err ( & dev - > interface - > dev ,
2012-12-10 17:42:51 +04:00
" Cannot bring the DEP link up while polling " ) ;
2011-12-14 19:43:11 +04:00
return - EBUSY ;
}
if ( dev - > tgt_active_prot ) {
nfc_dev_err ( & dev - > interface - > dev ,
2012-12-10 17:42:51 +04:00
" There is already an active target " ) ;
2011-12-14 19:43:11 +04:00
return - EBUSY ;
}
2012-12-10 17:42:45 +04:00
skb_len = 3 + gb_len ; /* ActPass + BR + Next */
2013-07-01 12:58:12 +04:00
skb_len + = PASSIVE_DATA_LEN ;
2012-05-29 23:45:21 +04:00
2013-07-01 12:58:12 +04:00
/* NFCID3 */
skb_len + = NFC_NFCID3_MAXSIZE ;
if ( target & & ! target - > nfcid2_len ) {
nfcid3 [ 0 ] = 0x1 ;
nfcid3 [ 1 ] = 0xfe ;
get_random_bytes ( nfcid3 + 2 , 6 ) ;
}
2013-05-27 17:29:11 +04:00
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , skb_len ) ;
2012-12-10 17:42:45 +04:00
if ( ! skb )
2011-12-14 19:43:11 +04:00
return - ENOMEM ;
2012-12-10 17:42:45 +04:00
* skb_put ( skb , 1 ) = ! comm_mode ; /* ActPass */
2013-07-01 12:58:12 +04:00
* skb_put ( skb , 1 ) = 0x02 ; /* 424 kbps */
2012-12-10 17:42:45 +04:00
next = skb_put ( skb , 1 ) ; /* Next */
* next = 0 ;
2011-12-14 19:43:11 +04:00
2013-07-01 12:58:12 +04:00
/* Copy passive data */
memcpy ( skb_put ( skb , PASSIVE_DATA_LEN ) , passive_data , PASSIVE_DATA_LEN ) ;
* next | = 1 ;
2012-05-29 23:45:21 +04:00
2013-07-01 12:58:12 +04:00
/* Copy NFCID3 (which is NFCID2 from SENSF_RES) */
if ( target & & target - > nfcid2_len )
2013-05-27 17:29:11 +04:00
memcpy ( skb_put ( skb , NFC_NFCID3_MAXSIZE ) , target - > nfcid2 ,
target - > nfcid2_len ) ;
2013-07-01 12:58:12 +04:00
else
memcpy ( skb_put ( skb , NFC_NFCID3_MAXSIZE ) , nfcid3 ,
NFC_NFCID3_MAXSIZE ) ;
* next | = 2 ;
2013-05-27 17:29:11 +04:00
2012-03-05 04:03:50 +04:00
if ( gb ! = NULL & & gb_len > 0 ) {
2012-12-10 17:42:45 +04:00
memcpy ( skb_put ( skb , gb_len ) , gb , gb_len ) ;
* next | = 4 ; /* We have some Gi */
2011-12-14 19:43:11 +04:00
} else {
2012-12-10 17:42:45 +04:00
* next = 0 ;
2011-12-14 19:43:11 +04:00
}
2012-12-10 17:42:45 +04:00
arg = kmalloc ( sizeof ( * arg ) , GFP_KERNEL ) ;
if ( ! arg ) {
dev_kfree_skb ( skb ) ;
return - ENOMEM ;
}
2011-12-14 19:43:11 +04:00
2012-12-10 17:42:45 +04:00
* arg = ! comm_mode ;
2011-12-14 19:43:11 +04:00
2013-06-26 20:16:21 +04:00
pn533_rf_field ( dev - > nfc_dev , 0 ) ;
2012-12-10 17:42:45 +04:00
rc = pn533_send_cmd_async ( dev , PN533_CMD_IN_JUMP_FOR_DEP , skb ,
pn533_in_dep_link_up_complete , arg ) ;
if ( rc < 0 ) {
dev_kfree_skb ( skb ) ;
kfree ( arg ) ;
}
2011-12-14 19:43:11 +04:00
return rc ;
}
static int pn533_dep_link_down ( struct nfc_dev * nfc_dev )
{
2012-05-30 19:20:25 +04:00
struct pn533 * dev = nfc_get_drvdata ( nfc_dev ) ;
2012-12-10 17:42:55 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-05-30 19:20:25 +04:00
pn533_poll_reset_mod_list ( dev ) ;
2013-04-03 10:02:14 +04:00
if ( dev - > tgt_mode | | dev - > tgt_active_prot )
pn533_abort_cmd ( dev , GFP_KERNEL ) ;
2012-05-31 22:01:32 +04:00
dev - > tgt_active_prot = 0 ;
dev - > tgt_mode = 0 ;
skb_queue_purge ( & dev - > resp_q ) ;
2011-12-14 19:43:11 +04:00
return 0 ;
}
2011-07-02 02:31:37 +04:00
struct pn533_data_exchange_arg {
data_exchange_cb_t cb ;
void * cb_context ;
} ;
2012-04-10 21:43:18 +04:00
static struct sk_buff * pn533_build_response ( struct pn533 * dev )
{
struct sk_buff * skb , * tmp , * t ;
unsigned int skb_len = 0 , tmp_len = 0 ;
2012-12-10 17:42:55 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-04-10 21:43:18 +04:00
if ( skb_queue_empty ( & dev - > resp_q ) )
return NULL ;
if ( skb_queue_len ( & dev - > resp_q ) = = 1 ) {
skb = skb_dequeue ( & dev - > resp_q ) ;
goto out ;
}
skb_queue_walk_safe ( & dev - > resp_q , tmp , t )
skb_len + = tmp - > len ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s total length %d \n " ,
__func__ , skb_len ) ;
skb = alloc_skb ( skb_len , GFP_KERNEL ) ;
if ( skb = = NULL )
goto out ;
skb_put ( skb , skb_len ) ;
skb_queue_walk_safe ( & dev - > resp_q , tmp , t ) {
memcpy ( skb - > data + tmp_len , tmp - > data , tmp - > len ) ;
tmp_len + = tmp - > len ;
}
out :
skb_queue_purge ( & dev - > resp_q ) ;
return skb ;
}
2011-07-02 02:31:37 +04:00
static int pn533_data_exchange_complete ( struct pn533 * dev , void * _arg ,
2012-12-10 17:42:46 +04:00
struct sk_buff * resp )
2011-07-02 02:31:37 +04:00
{
struct pn533_data_exchange_arg * arg = _arg ;
2012-12-10 17:42:46 +04:00
struct sk_buff * skb ;
int rc = 0 ;
u8 status , ret , mi ;
2011-07-02 02:31:37 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:42:46 +04:00
if ( IS_ERR ( resp ) ) {
rc = PTR_ERR ( resp ) ;
goto _error ;
2011-07-02 02:31:37 +04:00
}
2012-12-10 17:42:46 +04:00
status = resp - > data [ 0 ] ;
ret = status & PN533_CMD_RET_MASK ;
mi = status & PN533_CMD_MI_MASK ;
skb_pull ( resp , sizeof ( status ) ) ;
2011-07-02 02:31:37 +04:00
2012-12-10 17:42:46 +04:00
if ( ret ! = PN533_CMD_RET_SUCCESS ) {
nfc_dev_err ( & dev - > interface - > dev ,
2013-04-03 10:01:59 +04:00
" Exchanging data failed (error 0x%x) " , ret ) ;
2012-12-10 17:42:46 +04:00
rc = - EIO ;
2011-07-02 02:31:37 +04:00
goto error ;
}
2012-12-10 17:42:46 +04:00
skb_queue_tail ( & dev - > resp_q , resp ) ;
2012-04-10 21:43:18 +04:00
2012-12-10 17:42:46 +04:00
if ( mi ) {
dev - > cmd_complete_mi_arg = arg ;
2012-04-10 21:43:18 +04:00
queue_work ( dev - > wq , & dev - > mi_work ) ;
return - EINPROGRESS ;
2011-07-02 02:31:37 +04:00
}
2012-04-10 21:43:18 +04:00
skb = pn533_build_response ( dev ) ;
2012-12-10 17:42:46 +04:00
if ( ! skb )
2012-04-10 21:43:18 +04:00
goto error ;
2011-07-02 02:31:37 +04:00
2012-04-10 21:43:18 +04:00
arg - > cb ( arg - > cb_context , skb , 0 ) ;
2011-07-02 02:31:37 +04:00
kfree ( arg ) ;
return 0 ;
error :
2012-12-10 17:42:46 +04:00
dev_kfree_skb ( resp ) ;
_error :
2012-04-10 21:43:18 +04:00
skb_queue_purge ( & dev - > resp_q ) ;
2012-12-10 17:42:46 +04:00
arg - > cb ( arg - > cb_context , NULL , rc ) ;
2011-07-02 02:31:37 +04:00
kfree ( arg ) ;
2012-12-10 17:42:46 +04:00
return rc ;
2011-07-02 02:31:37 +04:00
}
2012-05-16 17:55:48 +04:00
static int pn533_transceive ( struct nfc_dev * nfc_dev ,
struct nfc_target * target , struct sk_buff * skb ,
data_exchange_cb_t cb , void * cb_context )
2011-07-02 02:31:37 +04:00
{
struct pn533 * dev = nfc_get_drvdata ( nfc_dev ) ;
2012-12-10 17:42:46 +04:00
struct pn533_data_exchange_arg * arg = NULL ;
2011-07-02 02:31:37 +04:00
int rc ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:42:46 +04:00
if ( skb - > len > PN533_CMD_DATAEXCH_DATA_MAXLEN ) {
/* TODO: Implement support to multi-part data exchange */
nfc_dev_err ( & dev - > interface - > dev ,
" Data length greater than the max allowed: %d " ,
PN533_CMD_DATAEXCH_DATA_MAXLEN ) ;
rc = - ENOSYS ;
goto error ;
}
2011-07-02 02:31:37 +04:00
if ( ! dev - > tgt_active_prot ) {
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" Can't exchange data if there is no active target " ) ;
2011-07-02 02:31:37 +04:00
rc = - EINVAL ;
goto error ;
}
2012-12-10 17:42:46 +04:00
arg = kmalloc ( sizeof ( * arg ) , GFP_KERNEL ) ;
2011-07-02 02:31:37 +04:00
if ( ! arg ) {
rc = - ENOMEM ;
2012-12-10 17:42:46 +04:00
goto error ;
2011-07-02 02:31:37 +04:00
}
arg - > cb = cb ;
arg - > cb_context = cb_context ;
2012-12-10 17:42:46 +04:00
switch ( dev - > device_type ) {
case PN533_DEVICE_PASORI :
if ( dev - > tgt_active_prot = = NFC_PROTO_FELICA ) {
rc = pn533_send_data_async ( dev , PN533_CMD_IN_COMM_THRU ,
skb ,
pn533_data_exchange_complete ,
arg ) ;
break ;
}
default :
* skb_push ( skb , sizeof ( u8 ) ) = 1 ; /*TG*/
rc = pn533_send_data_async ( dev , PN533_CMD_IN_DATA_EXCHANGE ,
skb , pn533_data_exchange_complete ,
arg ) ;
break ;
2011-07-02 02:31:37 +04:00
}
2012-12-10 17:42:46 +04:00
if ( rc < 0 ) /* rc from send_async */
goto error ;
2011-07-02 02:31:37 +04:00
return 0 ;
error :
2012-12-10 17:42:46 +04:00
kfree ( arg ) ;
dev_kfree_skb ( skb ) ;
2011-07-02 02:31:37 +04:00
return rc ;
}
2012-05-31 02:09:11 +04:00
static int pn533_tm_send_complete ( struct pn533 * dev , void * arg ,
2012-12-10 17:42:44 +04:00
struct sk_buff * resp )
2012-05-31 02:09:11 +04:00
{
2012-12-10 17:42:44 +04:00
u8 status ;
2012-11-15 21:24:28 +04:00
2012-05-31 02:09:11 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:42:44 +04:00
if ( IS_ERR ( resp ) )
return PTR_ERR ( resp ) ;
2012-11-15 21:24:28 +04:00
2012-12-10 17:42:44 +04:00
status = resp - > data [ 0 ] ;
2012-05-31 02:09:11 +04:00
2012-12-10 17:42:44 +04:00
dev_kfree_skb ( resp ) ;
2012-05-31 02:09:11 +04:00
2012-12-10 17:42:44 +04:00
if ( status ! = 0 ) {
2012-05-31 02:09:11 +04:00
nfc_tm_deactivated ( dev - > nfc_dev ) ;
2012-05-31 22:01:32 +04:00
dev - > tgt_mode = 0 ;
2012-05-31 02:09:11 +04:00
return 0 ;
}
queue_work ( dev - > wq , & dev - > tg_work ) ;
return 0 ;
}
static int pn533_tm_send ( struct nfc_dev * nfc_dev , struct sk_buff * skb )
{
struct pn533 * dev = nfc_get_drvdata ( nfc_dev ) ;
int rc ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:42:44 +04:00
if ( skb - > len > PN533_CMD_DATAEXCH_DATA_MAXLEN ) {
2012-05-31 02:09:11 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
2012-12-10 17:42:44 +04:00
" Data length greater than the max allowed: %d " ,
PN533_CMD_DATAEXCH_DATA_MAXLEN ) ;
return - ENOSYS ;
2012-05-31 02:09:11 +04:00
}
2012-12-10 17:42:44 +04:00
rc = pn533_send_data_async ( dev , PN533_CMD_TG_SET_DATA , skb ,
pn533_tm_send_complete , NULL ) ;
if ( rc < 0 )
dev_kfree_skb ( skb ) ;
2012-05-31 02:09:11 +04:00
return rc ;
}
2012-04-10 21:43:18 +04:00
static void pn533_wq_mi_recv ( struct work_struct * work )
{
struct pn533 * dev = container_of ( work , struct pn533 , mi_work ) ;
2012-12-10 17:42:46 +04:00
struct sk_buff * skb ;
2012-04-10 21:43:18 +04:00
int rc ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , PN533_CMD_DATAEXCH_HEAD_LEN ) ;
2012-12-10 17:42:46 +04:00
if ( ! skb )
goto error ;
2012-04-10 21:43:18 +04:00
2012-12-10 17:42:46 +04:00
switch ( dev - > device_type ) {
case PN533_DEVICE_PASORI :
if ( dev - > tgt_active_prot = = NFC_PROTO_FELICA ) {
rc = pn533_send_cmd_direct_async ( dev ,
PN533_CMD_IN_COMM_THRU ,
skb ,
pn533_data_exchange_complete ,
dev - > cmd_complete_mi_arg ) ;
2012-04-10 21:43:18 +04:00
2012-12-10 17:42:46 +04:00
break ;
}
default :
* skb_put ( skb , sizeof ( u8 ) ) = 1 ; /*TG*/
2012-04-10 21:43:18 +04:00
2012-12-10 17:42:46 +04:00
rc = pn533_send_cmd_direct_async ( dev ,
PN533_CMD_IN_DATA_EXCHANGE ,
skb ,
pn533_data_exchange_complete ,
dev - > cmd_complete_mi_arg ) ;
2012-11-26 17:18:32 +04:00
2012-12-10 17:42:46 +04:00
break ;
2012-04-10 21:43:18 +04:00
}
2012-12-10 17:42:46 +04:00
if ( rc = = 0 ) /* success */
2012-04-10 21:43:18 +04:00
return ;
2012-12-10 17:42:46 +04:00
nfc_dev_err ( & dev - > interface - > dev ,
" Error %d when trying to perform data_exchange " , rc ) ;
2012-04-10 21:43:18 +04:00
2012-12-10 17:42:46 +04:00
dev_kfree_skb ( skb ) ;
2013-04-03 10:02:07 +04:00
kfree ( dev - > cmd_complete_mi_arg ) ;
2012-04-10 21:43:18 +04:00
2012-12-10 17:42:46 +04:00
error :
2012-04-10 21:43:18 +04:00
pn533_send_ack ( dev , GFP_KERNEL ) ;
2012-08-18 01:47:54 +04:00
queue_work ( dev - > wq , & dev - > cmd_work ) ;
2012-04-10 21:43:18 +04:00
}
2011-07-02 02:31:37 +04:00
static int pn533_set_configuration ( struct pn533 * dev , u8 cfgitem , u8 * cfgdata ,
u8 cfgdata_len )
{
2012-11-26 17:18:38 +04:00
struct sk_buff * skb ;
struct sk_buff * resp ;
int skb_len ;
2011-07-02 02:31:37 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-11-26 17:18:38 +04:00
skb_len = sizeof ( cfgitem ) + cfgdata_len ; /* cfgitem + cfgdata */
2011-07-02 02:31:37 +04:00
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , skb_len ) ;
2012-11-26 17:18:38 +04:00
if ( ! skb )
return - ENOMEM ;
2011-07-02 02:31:37 +04:00
2012-11-26 17:18:38 +04:00
* skb_put ( skb , sizeof ( cfgitem ) ) = cfgitem ;
memcpy ( skb_put ( skb , cfgdata_len ) , cfgdata , cfgdata_len ) ;
2011-07-02 02:31:37 +04:00
2012-11-26 17:18:38 +04:00
resp = pn533_send_cmd_sync ( dev , PN533_CMD_RF_CONFIGURATION , skb ) ;
if ( IS_ERR ( resp ) )
return PTR_ERR ( resp ) ;
2011-07-02 02:31:37 +04:00
2012-11-26 17:18:38 +04:00
dev_kfree_skb ( resp ) ;
return 0 ;
}
static int pn533_get_firmware_version ( struct pn533 * dev ,
struct pn533_fw_version * fv )
{
struct sk_buff * skb ;
struct sk_buff * resp ;
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , 0 ) ;
2012-11-26 17:18:38 +04:00
if ( ! skb )
return - ENOMEM ;
resp = pn533_send_cmd_sync ( dev , PN533_CMD_GET_FIRMWARE_VERSION , skb ) ;
if ( IS_ERR ( resp ) )
return PTR_ERR ( resp ) ;
fv - > ic = resp - > data [ 0 ] ;
fv - > ver = resp - > data [ 1 ] ;
fv - > rev = resp - > data [ 2 ] ;
fv - > support = resp - > data [ 3 ] ;
dev_kfree_skb ( resp ) ;
return 0 ;
2011-07-02 02:31:37 +04:00
}
2013-04-03 10:02:02 +04:00
static int pn533_pasori_fw_reset ( struct pn533 * dev )
2012-07-02 22:04:01 +04:00
{
2012-11-26 17:18:38 +04:00
struct sk_buff * skb ;
struct sk_buff * resp ;
2012-07-02 22:04:01 +04:00
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __func__ ) ;
2012-12-10 17:43:01 +04:00
skb = pn533_alloc_skb ( dev , sizeof ( u8 ) ) ;
2012-11-26 17:18:38 +04:00
if ( ! skb )
return - ENOMEM ;
2012-07-02 22:04:01 +04:00
2012-11-26 17:18:38 +04:00
* skb_put ( skb , sizeof ( u8 ) ) = 0x1 ;
2012-07-02 22:04:01 +04:00
2012-11-26 17:18:38 +04:00
resp = pn533_send_cmd_sync ( dev , 0x18 , skb ) ;
if ( IS_ERR ( resp ) )
return PTR_ERR ( resp ) ;
2012-07-02 22:04:01 +04:00
2012-11-26 17:18:38 +04:00
dev_kfree_skb ( resp ) ;
2012-07-02 22:04:01 +04:00
2012-11-26 17:18:36 +04:00
return 0 ;
2012-07-02 22:04:01 +04:00
}
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
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 ;
nfc_dev_dbg ( & urb - > dev - > dev , " %s " , __func__ ) ;
2013-06-03 14:02:29 +04:00
print_hex_dump_debug ( " ACR122 RX: " , DUMP_PREFIX_NONE , 16 , 1 ,
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
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 ;
nfc_dev_dbg ( & dev - > interface - > dev , " %s " , __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 ) ;
2013-06-03 14:02:29 +04:00
print_hex_dump_debug ( " ACR122 TX: " , DUMP_PREFIX_NONE , 16 , 1 ,
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
cmd , sizeof ( cmd ) , false ) ;
rc = usb_submit_urb ( dev - > out_urb , GFP_KERNEL ) ;
if ( rc ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Reader power on cmd error %d " , rc ) ;
return rc ;
}
rc = usb_submit_urb ( dev - > in_urb , GFP_KERNEL ) ;
if ( rc ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Can't submit for reader power on cmd response %d " ,
rc ) ;
return rc ;
}
wait_for_completion ( & arg . done ) ;
dev - > in_urb - > context = cntx ; /* restore context */
return arg . rc ;
}
2013-04-11 13:45:41 +04:00
static int pn533_rf_field ( struct nfc_dev * nfc_dev , u8 rf )
{
struct pn533 * dev = nfc_get_drvdata ( nfc_dev ) ;
u8 rf_field = ! ! rf ;
int rc ;
2013-07-01 19:26:58 +04:00
rf_field | = PN533_CFGITEM_RF_FIELD_AUTO_RFCA ;
2013-04-11 13:45:41 +04:00
rc = pn533_set_configuration ( dev , PN533_CFGITEM_RF_FIELD ,
( u8 * ) & rf_field , 1 ) ;
if ( rc ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Error on setting RF field " ) ;
return rc ;
}
return rc ;
}
int pn533_dev_up ( struct nfc_dev * nfc_dev )
{
return pn533_rf_field ( nfc_dev , 1 ) ;
}
int pn533_dev_down ( struct nfc_dev * nfc_dev )
{
return pn533_rf_field ( nfc_dev , 0 ) ;
}
2012-07-02 22:04:01 +04:00
static struct nfc_ops pn533_nfc_ops = {
2013-04-11 13:45:41 +04:00
. dev_up = pn533_dev_up ,
. dev_down = pn533_dev_down ,
2011-12-14 19:43:11 +04:00
. dep_link_up = pn533_dep_link_up ,
. dep_link_down = pn533_dep_link_down ,
2011-07-02 02:31:37 +04:00
. start_poll = pn533_start_poll ,
. stop_poll = pn533_stop_poll ,
. activate_target = pn533_activate_target ,
. deactivate_target = pn533_deactivate_target ,
2012-05-16 17:55:48 +04:00
. im_transceive = pn533_transceive ,
2012-05-31 02:09:11 +04:00
. tm_send = pn533_tm_send ,
2011-07-02 02:31:37 +04:00
} ;
2012-07-02 22:04:01 +04:00
static int pn533_setup ( struct pn533 * dev )
{
struct pn533_config_max_retries max_retries ;
struct pn533_config_timing timing ;
u8 pasori_cfg [ 3 ] = { 0x08 , 0x01 , 0x08 } ;
int rc ;
switch ( dev - > device_type ) {
case PN533_DEVICE_STD :
case PN533_DEVICE_PASORI :
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
case PN533_DEVICE_ACR122U :
2012-07-02 22:04:01 +04:00
max_retries . mx_rty_atr = 0x2 ;
max_retries . mx_rty_psl = 0x1 ;
max_retries . mx_rty_passive_act =
PN533_CONFIG_MAX_RETRIES_NO_RETRY ;
timing . rfu = PN533_CONFIG_TIMING_102 ;
timing . atr_res_timeout = PN533_CONFIG_TIMING_102 ;
timing . dep_timeout = PN533_CONFIG_TIMING_204 ;
break ;
default :
nfc_dev_err ( & dev - > interface - > dev , " Unknown device type %d \n " ,
dev - > device_type ) ;
return - EINVAL ;
}
rc = pn533_set_configuration ( dev , PN533_CFGITEM_MAX_RETRIES ,
( u8 * ) & max_retries , sizeof ( max_retries ) ) ;
if ( rc ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Error on setting MAX_RETRIES config " ) ;
return rc ;
}
rc = pn533_set_configuration ( dev , PN533_CFGITEM_TIMING ,
( u8 * ) & timing , sizeof ( timing ) ) ;
if ( rc ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Error on setting RF timings " ) ;
return rc ;
}
switch ( dev - > device_type ) {
case PN533_DEVICE_STD :
break ;
case PN533_DEVICE_PASORI :
2013-04-03 10:02:02 +04:00
pn533_pasori_fw_reset ( dev ) ;
2012-07-02 22:04:01 +04:00
rc = pn533_set_configuration ( dev , PN533_CFGITEM_PASORI ,
pasori_cfg , 3 ) ;
if ( rc ) {
nfc_dev_err ( & dev - > interface - > dev ,
" Error while settings PASORI config " ) ;
return rc ;
}
2013-04-03 10:02:02 +04:00
pn533_pasori_fw_reset ( dev ) ;
2012-07-02 22:04:01 +04:00
break ;
}
return 0 ;
}
2011-07-02 02:31:37 +04:00
static int pn533_probe ( struct usb_interface * interface ,
const struct usb_device_id * id )
{
2012-11-26 17:18:38 +04:00
struct pn533_fw_version fw_ver ;
2011-07-02 02:31:37 +04:00
struct pn533 * dev ;
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 ;
dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
if ( ! dev )
return - ENOMEM ;
dev - > udev = usb_get_dev ( interface_to_usbdev ( interface ) ) ;
dev - > interface = interface ;
2012-05-31 19:56:46 +04:00
mutex_init ( & dev - > cmd_lock ) ;
2011-07-02 02:31:37 +04:00
iface_desc = interface - > cur_altsetting ;
for ( i = 0 ; i < iface_desc - > desc . bNumEndpoints ; + + i ) {
endpoint = & iface_desc - > endpoint [ i ] . desc ;
2012-11-26 17:18:30 +04:00
if ( ! in_endpoint & & usb_endpoint_is_bulk_in ( endpoint ) )
2011-07-02 02:31:37 +04:00
in_endpoint = endpoint - > bEndpointAddress ;
2012-11-26 17:18:30 +04:00
if ( ! out_endpoint & & usb_endpoint_is_bulk_out ( endpoint ) )
2011-07-02 02:31:37 +04:00
out_endpoint = endpoint - > bEndpointAddress ;
}
if ( ! in_endpoint | | ! out_endpoint ) {
2012-12-10 17:42:49 +04:00
nfc_dev_err ( & interface - > dev ,
" Could not find bulk-in or bulk-out endpoint " ) ;
2011-07-02 02:31:37 +04:00
rc = - ENODEV ;
goto error ;
}
dev - > in_urb = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
dev - > out_urb = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
2012-12-10 17:42:58 +04:00
if ( ! dev - > in_urb | | ! dev - > out_urb )
2011-07-02 02:31:37 +04:00
goto error ;
usb_fill_bulk_urb ( dev - > in_urb , dev - > udev ,
2012-12-10 17:42:51 +04:00
usb_rcvbulkpipe ( dev - > udev , in_endpoint ) ,
NULL , 0 , NULL , dev ) ;
2011-07-02 02:31:37 +04:00
usb_fill_bulk_urb ( dev - > out_urb , dev - > udev ,
2012-12-10 17:42:51 +04:00
usb_sndbulkpipe ( dev - > udev , out_endpoint ) ,
NULL , 0 , pn533_send_complete , dev ) ;
2011-07-02 02:31:37 +04:00
2012-08-18 01:47:54 +04:00
INIT_WORK ( & dev - > cmd_work , pn533_wq_cmd ) ;
INIT_WORK ( & dev - > cmd_complete_work , pn533_wq_cmd_complete ) ;
2012-04-10 21:43:18 +04:00
INIT_WORK ( & dev - > mi_work , pn533_wq_mi_recv ) ;
2012-05-31 02:07:51 +04:00
INIT_WORK ( & dev - > tg_work , pn533_wq_tg_get_data ) ;
2012-05-30 19:20:25 +04:00
INIT_WORK ( & dev - > poll_work , pn533_wq_poll ) ;
2013-06-26 20:16:21 +04:00
INIT_WORK ( & dev - > rf_work , pn533_wq_rf ) ;
2012-08-23 03:28:46 +04:00
dev - > wq = alloc_ordered_workqueue ( " pn533 " , 0 ) ;
2012-04-10 21:43:17 +04:00
if ( dev - > wq = = NULL )
goto error ;
2011-07-02 02:31:37 +04:00
2012-05-30 19:20:25 +04:00
init_timer ( & dev - > listen_timer ) ;
dev - > listen_timer . data = ( unsigned long ) dev ;
dev - > listen_timer . function = pn533_listen_mode_timer ;
2012-04-10 21:43:18 +04:00
skb_queue_head_init ( & dev - > resp_q ) ;
2012-08-18 01:47:54 +04:00
INIT_LIST_HEAD ( & dev - > cmd_queue ) ;
2011-07-02 02:31:37 +04:00
usb_set_intfdata ( interface , dev ) ;
2012-12-10 17:43:01 +04:00
dev - > ops = & pn533_std_frame_ops ;
2011-07-02 02:31:37 +04:00
2013-04-03 10:02:12 +04:00
dev - > protocol_type = PN533_PROTO_REQ_ACK_RESP ;
2012-07-02 22:04:01 +04:00
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 ;
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
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_dev_err ( & dev - > interface - > dev ,
" Couldn't poweron the reader (error %d) " ,
rc ) ;
goto destroy_wq ;
}
break ;
2012-07-02 22:04:01 +04:00
default :
nfc_dev_err ( & dev - > interface - > dev , " Unknown device type %d \n " ,
dev - > device_type ) ;
rc = - EINVAL ;
goto destroy_wq ;
}
2011-07-02 02:31:37 +04:00
2012-12-10 17:43:01 +04:00
memset ( & fw_ver , 0 , sizeof ( fw_ver ) ) ;
rc = pn533_get_firmware_version ( dev , & fw_ver ) ;
if ( rc < 0 )
goto destroy_wq ;
nfc_dev_info ( & dev - > interface - > dev ,
2013-06-03 14:02:29 +04:00
" NXP PN5%02X firmware ver %d.%d now attached " ,
fw_ver . ic , fw_ver . ver , fw_ver . rev ) ;
2012-12-10 17:43:01 +04:00
2011-08-19 17:47:11 +04:00
dev - > nfc_dev = nfc_allocate_device ( & pn533_nfc_ops , protocols ,
2012-12-10 17:43:01 +04:00
dev - > ops - > tx_header_len +
2011-08-19 17:47:11 +04:00
PN533_CMD_DATAEXCH_HEAD_LEN ,
2012-12-10 17:43:01 +04:00
dev - > ops - > tx_tail_len ) ;
2013-05-07 16:07:52 +04:00
if ( ! dev - > nfc_dev ) {
rc = - ENOMEM ;
2012-04-10 21:43:17 +04:00
goto destroy_wq ;
2013-05-07 16:07:52 +04:00
}
2011-07-02 02:31:37 +04:00
nfc_set_parent_dev ( dev - > nfc_dev , & interface - > dev ) ;
nfc_set_drvdata ( dev - > nfc_dev , dev ) ;
rc = nfc_register_device ( dev - > nfc_dev ) ;
if ( rc )
goto free_nfc_dev ;
2012-07-02 22:04:01 +04:00
rc = pn533_setup ( dev ) ;
if ( rc )
2012-05-29 23:34:08 +04:00
goto unregister_nfc_dev ;
2011-07-02 02:31:37 +04:00
return 0 ;
2012-05-29 23:28:58 +04:00
unregister_nfc_dev :
nfc_unregister_device ( dev - > nfc_dev ) ;
2011-07-02 02:31:37 +04:00
free_nfc_dev :
nfc_free_device ( dev - > nfc_dev ) ;
2012-05-29 23:28:58 +04:00
2012-04-10 21:43:17 +04:00
destroy_wq :
destroy_workqueue ( dev - > wq ) ;
2011-07-02 02:31:37 +04:00
error :
usb_free_urb ( dev - > in_urb ) ;
usb_free_urb ( dev - > out_urb ) ;
2013-02-26 11:41:18 +04:00
usb_put_dev ( dev - > udev ) ;
2011-07-02 02:31:37 +04:00
kfree ( dev ) ;
return rc ;
}
static void pn533_disconnect ( struct usb_interface * interface )
{
struct pn533 * dev ;
2012-08-18 01:47:54 +04:00
struct pn533_cmd * cmd , * n ;
2011-07-02 02:31:37 +04:00
dev = usb_get_intfdata ( interface ) ;
usb_set_intfdata ( interface , NULL ) ;
nfc_unregister_device ( dev - > nfc_dev ) ;
nfc_free_device ( dev - > nfc_dev ) ;
usb_kill_urb ( dev - > in_urb ) ;
usb_kill_urb ( dev - > out_urb ) ;
2012-04-10 21:43:17 +04:00
destroy_workqueue ( dev - > wq ) ;
2011-07-02 02:31:37 +04:00
2012-04-10 21:43:18 +04:00
skb_queue_purge ( & dev - > resp_q ) ;
2012-05-30 19:20:25 +04:00
del_timer ( & dev - > listen_timer ) ;
2012-08-18 01:47:54 +04:00
list_for_each_entry_safe ( cmd , n , & dev - > cmd_queue , queue ) {
list_del ( & cmd - > queue ) ;
kfree ( cmd ) ;
}
2011-07-02 02:31:37 +04:00
usb_free_urb ( dev - > in_urb ) ;
usb_free_urb ( dev - > out_urb ) ;
kfree ( dev ) ;
2011-07-08 11:21:15 +04:00
nfc_dev_info ( & interface - > dev , " NXP PN533 NFC device disconnected " ) ;
2011-07-02 02:31:37 +04:00
}
static struct usb_driver pn533_driver = {
. name = " pn533 " ,
. probe = pn533_probe ,
. disconnect = pn533_disconnect ,
. id_table = pn533_table ,
} ;
2011-11-18 21:52:10 +04:00
module_usb_driver ( pn533_driver ) ;
2011-07-02 02:31:37 +04:00
2013-04-03 10:02:01 +04:00
MODULE_AUTHOR ( " Lauro Ramos Venancio <lauro.venancio@openbossa.org> " ) ;
MODULE_AUTHOR ( " Aloisio Almeida Jr <aloisio.almeida@openbossa.org> " ) ;
MODULE_AUTHOR ( " Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> " ) ;
2011-07-02 02:31:37 +04:00
MODULE_DESCRIPTION ( " PN533 usb driver ver " VERSION ) ;
MODULE_VERSION ( VERSION ) ;
MODULE_LICENSE ( " GPL " ) ;