11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29815c7cfSMichael Thalmeier /*
39815c7cfSMichael Thalmeier * Driver for NXP PN533 NFC Chip - core functions
49815c7cfSMichael Thalmeier *
59815c7cfSMichael Thalmeier * Copyright (C) 2011 Instituto Nokia de Tecnologia
69815c7cfSMichael Thalmeier * Copyright (C) 2012-2013 Tieto Poland
79815c7cfSMichael Thalmeier */
89815c7cfSMichael Thalmeier
99815c7cfSMichael Thalmeier #include <linux/device.h>
109815c7cfSMichael Thalmeier #include <linux/kernel.h>
119815c7cfSMichael Thalmeier #include <linux/module.h>
129815c7cfSMichael Thalmeier #include <linux/slab.h>
139815c7cfSMichael Thalmeier #include <linux/nfc.h>
149815c7cfSMichael Thalmeier #include <linux/netdevice.h>
159815c7cfSMichael Thalmeier #include <net/nfc/nfc.h>
169815c7cfSMichael Thalmeier #include "pn533.h"
179815c7cfSMichael Thalmeier
189815c7cfSMichael Thalmeier #define VERSION "0.3"
199815c7cfSMichael Thalmeier
209815c7cfSMichael Thalmeier /* How much time we spend listening for initiators */
219815c7cfSMichael Thalmeier #define PN533_LISTEN_TIME 2
229815c7cfSMichael Thalmeier /* Delay between each poll frame (ms) */
239815c7cfSMichael Thalmeier #define PN533_POLL_INTERVAL 10
249815c7cfSMichael Thalmeier
259815c7cfSMichael Thalmeier /* structs for pn533 commands */
269815c7cfSMichael Thalmeier
279815c7cfSMichael Thalmeier /* PN533_CMD_GET_FIRMWARE_VERSION */
289815c7cfSMichael Thalmeier struct pn533_fw_version {
299815c7cfSMichael Thalmeier u8 ic;
309815c7cfSMichael Thalmeier u8 ver;
319815c7cfSMichael Thalmeier u8 rev;
329815c7cfSMichael Thalmeier u8 support;
339815c7cfSMichael Thalmeier };
349815c7cfSMichael Thalmeier
359815c7cfSMichael Thalmeier /* PN533_CMD_RF_CONFIGURATION */
369815c7cfSMichael Thalmeier #define PN533_CFGITEM_RF_FIELD 0x01
379815c7cfSMichael Thalmeier #define PN533_CFGITEM_TIMING 0x02
389815c7cfSMichael Thalmeier #define PN533_CFGITEM_MAX_RETRIES 0x05
399815c7cfSMichael Thalmeier #define PN533_CFGITEM_PASORI 0x82
409815c7cfSMichael Thalmeier
419815c7cfSMichael Thalmeier #define PN533_CFGITEM_RF_FIELD_AUTO_RFCA 0x2
429815c7cfSMichael Thalmeier #define PN533_CFGITEM_RF_FIELD_ON 0x1
439815c7cfSMichael Thalmeier #define PN533_CFGITEM_RF_FIELD_OFF 0x0
449815c7cfSMichael Thalmeier
459815c7cfSMichael Thalmeier #define PN533_CONFIG_TIMING_102 0xb
469815c7cfSMichael Thalmeier #define PN533_CONFIG_TIMING_204 0xc
479815c7cfSMichael Thalmeier #define PN533_CONFIG_TIMING_409 0xd
489815c7cfSMichael Thalmeier #define PN533_CONFIG_TIMING_819 0xe
499815c7cfSMichael Thalmeier
509815c7cfSMichael Thalmeier #define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00
519815c7cfSMichael Thalmeier #define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF
529815c7cfSMichael Thalmeier
539815c7cfSMichael Thalmeier struct pn533_config_max_retries {
549815c7cfSMichael Thalmeier u8 mx_rty_atr;
559815c7cfSMichael Thalmeier u8 mx_rty_psl;
569815c7cfSMichael Thalmeier u8 mx_rty_passive_act;
579815c7cfSMichael Thalmeier } __packed;
589815c7cfSMichael Thalmeier
599815c7cfSMichael Thalmeier struct pn533_config_timing {
609815c7cfSMichael Thalmeier u8 rfu;
619815c7cfSMichael Thalmeier u8 atr_res_timeout;
629815c7cfSMichael Thalmeier u8 dep_timeout;
639815c7cfSMichael Thalmeier } __packed;
649815c7cfSMichael Thalmeier
659815c7cfSMichael Thalmeier /* PN533_CMD_IN_LIST_PASSIVE_TARGET */
669815c7cfSMichael Thalmeier
679815c7cfSMichael Thalmeier /* felica commands opcode */
689815c7cfSMichael Thalmeier #define PN533_FELICA_OPC_SENSF_REQ 0
699815c7cfSMichael Thalmeier #define PN533_FELICA_OPC_SENSF_RES 1
709815c7cfSMichael Thalmeier /* felica SENSF_REQ parameters */
719815c7cfSMichael Thalmeier #define PN533_FELICA_SENSF_SC_ALL 0xFFFF
729815c7cfSMichael Thalmeier #define PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE 0
739815c7cfSMichael Thalmeier #define PN533_FELICA_SENSF_RC_SYSTEM_CODE 1
749815c7cfSMichael Thalmeier #define PN533_FELICA_SENSF_RC_ADVANCED_PROTOCOL 2
759815c7cfSMichael Thalmeier
769815c7cfSMichael Thalmeier /* type B initiator_data values */
779815c7cfSMichael Thalmeier #define PN533_TYPE_B_AFI_ALL_FAMILIES 0
789815c7cfSMichael Thalmeier #define PN533_TYPE_B_POLL_METHOD_TIMESLOT 0
799815c7cfSMichael Thalmeier #define PN533_TYPE_B_POLL_METHOD_PROBABILISTIC 1
809815c7cfSMichael Thalmeier
819815c7cfSMichael Thalmeier union pn533_cmd_poll_initdata {
829815c7cfSMichael Thalmeier struct {
839815c7cfSMichael Thalmeier u8 afi;
849815c7cfSMichael Thalmeier u8 polling_method;
859815c7cfSMichael Thalmeier } __packed type_b;
869815c7cfSMichael Thalmeier struct {
879815c7cfSMichael Thalmeier u8 opcode;
889815c7cfSMichael Thalmeier __be16 sc;
899815c7cfSMichael Thalmeier u8 rc;
909815c7cfSMichael Thalmeier u8 tsn;
919815c7cfSMichael Thalmeier } __packed felica;
929815c7cfSMichael Thalmeier };
939815c7cfSMichael Thalmeier
949815c7cfSMichael Thalmeier struct pn533_poll_modulations {
959815c7cfSMichael Thalmeier struct {
969815c7cfSMichael Thalmeier u8 maxtg;
979815c7cfSMichael Thalmeier u8 brty;
989815c7cfSMichael Thalmeier union pn533_cmd_poll_initdata initiator_data;
999815c7cfSMichael Thalmeier } __packed data;
1009815c7cfSMichael Thalmeier u8 len;
1019815c7cfSMichael Thalmeier };
1029815c7cfSMichael Thalmeier
1039815c7cfSMichael Thalmeier static const struct pn533_poll_modulations poll_mod[] = {
1049815c7cfSMichael Thalmeier [PN533_POLL_MOD_106KBPS_A] = {
1059815c7cfSMichael Thalmeier .data = {
1069815c7cfSMichael Thalmeier .maxtg = 1,
1079815c7cfSMichael Thalmeier .brty = 0,
1089815c7cfSMichael Thalmeier },
1099815c7cfSMichael Thalmeier .len = 2,
1109815c7cfSMichael Thalmeier },
1119815c7cfSMichael Thalmeier [PN533_POLL_MOD_212KBPS_FELICA] = {
1129815c7cfSMichael Thalmeier .data = {
1139815c7cfSMichael Thalmeier .maxtg = 1,
1149815c7cfSMichael Thalmeier .brty = 1,
1159815c7cfSMichael Thalmeier .initiator_data.felica = {
1169815c7cfSMichael Thalmeier .opcode = PN533_FELICA_OPC_SENSF_REQ,
1179815c7cfSMichael Thalmeier .sc = PN533_FELICA_SENSF_SC_ALL,
1189815c7cfSMichael Thalmeier .rc = PN533_FELICA_SENSF_RC_SYSTEM_CODE,
1199815c7cfSMichael Thalmeier .tsn = 0x03,
1209815c7cfSMichael Thalmeier },
1219815c7cfSMichael Thalmeier },
1229815c7cfSMichael Thalmeier .len = 7,
1239815c7cfSMichael Thalmeier },
1249815c7cfSMichael Thalmeier [PN533_POLL_MOD_424KBPS_FELICA] = {
1259815c7cfSMichael Thalmeier .data = {
1269815c7cfSMichael Thalmeier .maxtg = 1,
1279815c7cfSMichael Thalmeier .brty = 2,
1289815c7cfSMichael Thalmeier .initiator_data.felica = {
1299815c7cfSMichael Thalmeier .opcode = PN533_FELICA_OPC_SENSF_REQ,
1309815c7cfSMichael Thalmeier .sc = PN533_FELICA_SENSF_SC_ALL,
1319815c7cfSMichael Thalmeier .rc = PN533_FELICA_SENSF_RC_SYSTEM_CODE,
1329815c7cfSMichael Thalmeier .tsn = 0x03,
1339815c7cfSMichael Thalmeier },
1349815c7cfSMichael Thalmeier },
1359815c7cfSMichael Thalmeier .len = 7,
1369815c7cfSMichael Thalmeier },
1379815c7cfSMichael Thalmeier [PN533_POLL_MOD_106KBPS_JEWEL] = {
1389815c7cfSMichael Thalmeier .data = {
1399815c7cfSMichael Thalmeier .maxtg = 1,
1409815c7cfSMichael Thalmeier .brty = 4,
1419815c7cfSMichael Thalmeier },
1429815c7cfSMichael Thalmeier .len = 2,
1439815c7cfSMichael Thalmeier },
1449815c7cfSMichael Thalmeier [PN533_POLL_MOD_847KBPS_B] = {
1459815c7cfSMichael Thalmeier .data = {
1469815c7cfSMichael Thalmeier .maxtg = 1,
1479815c7cfSMichael Thalmeier .brty = 8,
1489815c7cfSMichael Thalmeier .initiator_data.type_b = {
1499815c7cfSMichael Thalmeier .afi = PN533_TYPE_B_AFI_ALL_FAMILIES,
1509815c7cfSMichael Thalmeier .polling_method =
1519815c7cfSMichael Thalmeier PN533_TYPE_B_POLL_METHOD_TIMESLOT,
1529815c7cfSMichael Thalmeier },
1539815c7cfSMichael Thalmeier },
1549815c7cfSMichael Thalmeier .len = 3,
1559815c7cfSMichael Thalmeier },
1569815c7cfSMichael Thalmeier [PN533_LISTEN_MOD] = {
1579815c7cfSMichael Thalmeier .len = 0,
1589815c7cfSMichael Thalmeier },
1599815c7cfSMichael Thalmeier };
1609815c7cfSMichael Thalmeier
1619815c7cfSMichael Thalmeier /* PN533_CMD_IN_ATR */
1629815c7cfSMichael Thalmeier
1639815c7cfSMichael Thalmeier struct pn533_cmd_activate_response {
1649815c7cfSMichael Thalmeier u8 status;
1659815c7cfSMichael Thalmeier u8 nfcid3t[10];
1669815c7cfSMichael Thalmeier u8 didt;
1679815c7cfSMichael Thalmeier u8 bst;
1689815c7cfSMichael Thalmeier u8 brt;
1699815c7cfSMichael Thalmeier u8 to;
1709815c7cfSMichael Thalmeier u8 ppt;
1719815c7cfSMichael Thalmeier /* optional */
1729815c7cfSMichael Thalmeier u8 gt[];
1739815c7cfSMichael Thalmeier } __packed;
1749815c7cfSMichael Thalmeier
1759815c7cfSMichael Thalmeier struct pn533_cmd_jump_dep_response {
1769815c7cfSMichael Thalmeier u8 status;
1779815c7cfSMichael Thalmeier u8 tg;
1789815c7cfSMichael Thalmeier u8 nfcid3t[10];
1799815c7cfSMichael Thalmeier u8 didt;
1809815c7cfSMichael Thalmeier u8 bst;
1819815c7cfSMichael Thalmeier u8 brt;
1829815c7cfSMichael Thalmeier u8 to;
1839815c7cfSMichael Thalmeier u8 ppt;
1849815c7cfSMichael Thalmeier /* optional */
1859815c7cfSMichael Thalmeier u8 gt[];
1869815c7cfSMichael Thalmeier } __packed;
1879815c7cfSMichael Thalmeier
188c64b875fSLars Poeschel struct pn532_autopoll_resp {
189c64b875fSLars Poeschel u8 type;
190c64b875fSLars Poeschel u8 ln;
191c64b875fSLars Poeschel u8 tg;
192c64b875fSLars Poeschel u8 tgdata[];
193c64b875fSLars Poeschel };
194c64b875fSLars Poeschel
195c64b875fSLars Poeschel /* PN532_CMD_IN_AUTOPOLL */
196c64b875fSLars Poeschel #define PN532_AUTOPOLL_POLLNR_INFINITE 0xff
197c64b875fSLars Poeschel #define PN532_AUTOPOLL_PERIOD 0x03 /* in units of 150 ms */
198c64b875fSLars Poeschel
199c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_GENERIC_106 0x00
200c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_GENERIC_212 0x01
201c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_GENERIC_424 0x02
202c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_JEWEL 0x04
203c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_MIFARE 0x10
204c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_FELICA212 0x11
205c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_FELICA424 0x12
206c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_ISOA 0x20
207c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_ISOB 0x23
208c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106 0x40
209c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212 0x41
210c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424 0x42
211c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106 0x80
212c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_212 0x81
213c64b875fSLars Poeschel #define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_424 0x82
2149815c7cfSMichael Thalmeier
2159815c7cfSMichael Thalmeier /* PN533_TG_INIT_AS_TARGET */
2169815c7cfSMichael Thalmeier #define PN533_INIT_TARGET_PASSIVE 0x1
2179815c7cfSMichael Thalmeier #define PN533_INIT_TARGET_DEP 0x2
2189815c7cfSMichael Thalmeier
2199815c7cfSMichael Thalmeier #define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3
2209815c7cfSMichael Thalmeier #define PN533_INIT_TARGET_RESP_ACTIVE 0x1
2219815c7cfSMichael Thalmeier #define PN533_INIT_TARGET_RESP_DEP 0x4
2229815c7cfSMichael Thalmeier
2239815c7cfSMichael Thalmeier /* The rule: value(high byte) + value(low byte) + checksum = 0 */
pn533_ext_checksum(u16 value)2249815c7cfSMichael Thalmeier static inline u8 pn533_ext_checksum(u16 value)
2259815c7cfSMichael Thalmeier {
2269815c7cfSMichael Thalmeier return ~(u8)(((value & 0xFF00) >> 8) + (u8)(value & 0xFF)) + 1;
2279815c7cfSMichael Thalmeier }
2289815c7cfSMichael Thalmeier
2299815c7cfSMichael Thalmeier /* The rule: value + checksum = 0 */
pn533_std_checksum(u8 value)2309815c7cfSMichael Thalmeier static inline u8 pn533_std_checksum(u8 value)
2319815c7cfSMichael Thalmeier {
2329815c7cfSMichael Thalmeier return ~value + 1;
2339815c7cfSMichael Thalmeier }
2349815c7cfSMichael Thalmeier
2359815c7cfSMichael Thalmeier /* The rule: sum(data elements) + checksum = 0 */
pn533_std_data_checksum(u8 * data,int datalen)2369815c7cfSMichael Thalmeier static u8 pn533_std_data_checksum(u8 *data, int datalen)
2379815c7cfSMichael Thalmeier {
2389815c7cfSMichael Thalmeier u8 sum = 0;
2399815c7cfSMichael Thalmeier int i;
2409815c7cfSMichael Thalmeier
2419815c7cfSMichael Thalmeier for (i = 0; i < datalen; i++)
2429815c7cfSMichael Thalmeier sum += data[i];
2439815c7cfSMichael Thalmeier
2449815c7cfSMichael Thalmeier return pn533_std_checksum(sum);
2459815c7cfSMichael Thalmeier }
2469815c7cfSMichael Thalmeier
pn533_std_tx_frame_init(void * _frame,u8 cmd_code)2479815c7cfSMichael Thalmeier static void pn533_std_tx_frame_init(void *_frame, u8 cmd_code)
2489815c7cfSMichael Thalmeier {
2499815c7cfSMichael Thalmeier struct pn533_std_frame *frame = _frame;
2509815c7cfSMichael Thalmeier
2519815c7cfSMichael Thalmeier frame->preamble = 0;
2529815c7cfSMichael Thalmeier frame->start_frame = cpu_to_be16(PN533_STD_FRAME_SOF);
2539815c7cfSMichael Thalmeier PN533_STD_FRAME_IDENTIFIER(frame) = PN533_STD_FRAME_DIR_OUT;
2549815c7cfSMichael Thalmeier PN533_FRAME_CMD(frame) = cmd_code;
2559815c7cfSMichael Thalmeier frame->datalen = 2;
2569815c7cfSMichael Thalmeier }
2579815c7cfSMichael Thalmeier
pn533_std_tx_frame_finish(void * _frame)2589815c7cfSMichael Thalmeier static void pn533_std_tx_frame_finish(void *_frame)
2599815c7cfSMichael Thalmeier {
2609815c7cfSMichael Thalmeier struct pn533_std_frame *frame = _frame;
2619815c7cfSMichael Thalmeier
2629815c7cfSMichael Thalmeier frame->datalen_checksum = pn533_std_checksum(frame->datalen);
2639815c7cfSMichael Thalmeier
2649815c7cfSMichael Thalmeier PN533_STD_FRAME_CHECKSUM(frame) =
2659815c7cfSMichael Thalmeier pn533_std_data_checksum(frame->data, frame->datalen);
2669815c7cfSMichael Thalmeier
2679815c7cfSMichael Thalmeier PN533_STD_FRAME_POSTAMBLE(frame) = 0;
2689815c7cfSMichael Thalmeier }
2699815c7cfSMichael Thalmeier
pn533_std_tx_update_payload_len(void * _frame,int len)2709815c7cfSMichael Thalmeier static void pn533_std_tx_update_payload_len(void *_frame, int len)
2719815c7cfSMichael Thalmeier {
2729815c7cfSMichael Thalmeier struct pn533_std_frame *frame = _frame;
2739815c7cfSMichael Thalmeier
2749815c7cfSMichael Thalmeier frame->datalen += len;
2759815c7cfSMichael Thalmeier }
2769815c7cfSMichael Thalmeier
pn533_std_rx_frame_is_valid(void * _frame,struct pn533 * dev)2779815c7cfSMichael Thalmeier static bool pn533_std_rx_frame_is_valid(void *_frame, struct pn533 *dev)
2789815c7cfSMichael Thalmeier {
2799815c7cfSMichael Thalmeier u8 checksum;
2809815c7cfSMichael Thalmeier struct pn533_std_frame *stdf = _frame;
2819815c7cfSMichael Thalmeier
2829815c7cfSMichael Thalmeier if (stdf->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
2839815c7cfSMichael Thalmeier return false;
2849815c7cfSMichael Thalmeier
2859815c7cfSMichael Thalmeier if (likely(!PN533_STD_IS_EXTENDED(stdf))) {
2869815c7cfSMichael Thalmeier /* Standard frame code */
2879815c7cfSMichael Thalmeier dev->ops->rx_header_len = PN533_STD_FRAME_HEADER_LEN;
2889815c7cfSMichael Thalmeier
2899815c7cfSMichael Thalmeier checksum = pn533_std_checksum(stdf->datalen);
2909815c7cfSMichael Thalmeier if (checksum != stdf->datalen_checksum)
2919815c7cfSMichael Thalmeier return false;
2929815c7cfSMichael Thalmeier
2939815c7cfSMichael Thalmeier checksum = pn533_std_data_checksum(stdf->data, stdf->datalen);
2949815c7cfSMichael Thalmeier if (checksum != PN533_STD_FRAME_CHECKSUM(stdf))
2959815c7cfSMichael Thalmeier return false;
2969815c7cfSMichael Thalmeier } else {
2979815c7cfSMichael Thalmeier /* Extended */
2989815c7cfSMichael Thalmeier struct pn533_ext_frame *eif = _frame;
2999815c7cfSMichael Thalmeier
3009815c7cfSMichael Thalmeier dev->ops->rx_header_len = PN533_EXT_FRAME_HEADER_LEN;
3019815c7cfSMichael Thalmeier
3029815c7cfSMichael Thalmeier checksum = pn533_ext_checksum(be16_to_cpu(eif->datalen));
3039815c7cfSMichael Thalmeier if (checksum != eif->datalen_checksum)
3049815c7cfSMichael Thalmeier return false;
3059815c7cfSMichael Thalmeier
3069815c7cfSMichael Thalmeier /* check data checksum */
3079815c7cfSMichael Thalmeier checksum = pn533_std_data_checksum(eif->data,
3089815c7cfSMichael Thalmeier be16_to_cpu(eif->datalen));
3099815c7cfSMichael Thalmeier if (checksum != PN533_EXT_FRAME_CHECKSUM(eif))
3109815c7cfSMichael Thalmeier return false;
3119815c7cfSMichael Thalmeier }
3129815c7cfSMichael Thalmeier
3139815c7cfSMichael Thalmeier return true;
3149815c7cfSMichael Thalmeier }
3159815c7cfSMichael Thalmeier
pn533_rx_frame_is_ack(void * _frame)3169815c7cfSMichael Thalmeier bool pn533_rx_frame_is_ack(void *_frame)
3179815c7cfSMichael Thalmeier {
3189815c7cfSMichael Thalmeier struct pn533_std_frame *frame = _frame;
3199815c7cfSMichael Thalmeier
3209815c7cfSMichael Thalmeier if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
3219815c7cfSMichael Thalmeier return false;
3229815c7cfSMichael Thalmeier
3239815c7cfSMichael Thalmeier if (frame->datalen != 0 || frame->datalen_checksum != 0xFF)
3249815c7cfSMichael Thalmeier return false;
3259815c7cfSMichael Thalmeier
3269815c7cfSMichael Thalmeier return true;
3279815c7cfSMichael Thalmeier }
3289815c7cfSMichael Thalmeier EXPORT_SYMBOL_GPL(pn533_rx_frame_is_ack);
3299815c7cfSMichael Thalmeier
pn533_std_rx_frame_size(void * frame)3309815c7cfSMichael Thalmeier static inline int pn533_std_rx_frame_size(void *frame)
3319815c7cfSMichael Thalmeier {
3329815c7cfSMichael Thalmeier struct pn533_std_frame *f = frame;
3339815c7cfSMichael Thalmeier
3349815c7cfSMichael Thalmeier /* check for Extended Information frame */
3359815c7cfSMichael Thalmeier if (PN533_STD_IS_EXTENDED(f)) {
3369815c7cfSMichael Thalmeier struct pn533_ext_frame *eif = frame;
3379815c7cfSMichael Thalmeier
3389815c7cfSMichael Thalmeier return sizeof(struct pn533_ext_frame)
3399815c7cfSMichael Thalmeier + be16_to_cpu(eif->datalen) + PN533_STD_FRAME_TAIL_LEN;
3409815c7cfSMichael Thalmeier }
3419815c7cfSMichael Thalmeier
3429815c7cfSMichael Thalmeier return sizeof(struct pn533_std_frame) + f->datalen +
3439815c7cfSMichael Thalmeier PN533_STD_FRAME_TAIL_LEN;
3449815c7cfSMichael Thalmeier }
3459815c7cfSMichael Thalmeier
pn533_std_get_cmd_code(void * frame)3469815c7cfSMichael Thalmeier static u8 pn533_std_get_cmd_code(void *frame)
3479815c7cfSMichael Thalmeier {
3489815c7cfSMichael Thalmeier struct pn533_std_frame *f = frame;
3499815c7cfSMichael Thalmeier struct pn533_ext_frame *eif = frame;
3509815c7cfSMichael Thalmeier
3519815c7cfSMichael Thalmeier if (PN533_STD_IS_EXTENDED(f))
3529815c7cfSMichael Thalmeier return PN533_FRAME_CMD(eif);
3539815c7cfSMichael Thalmeier else
3549815c7cfSMichael Thalmeier return PN533_FRAME_CMD(f);
3559815c7cfSMichael Thalmeier }
3569815c7cfSMichael Thalmeier
pn533_rx_frame_is_cmd_response(struct pn533 * dev,void * frame)3579815c7cfSMichael Thalmeier bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame)
3589815c7cfSMichael Thalmeier {
3599815c7cfSMichael Thalmeier return (dev->ops->get_cmd_code(frame) ==
3609815c7cfSMichael Thalmeier PN533_CMD_RESPONSE(dev->cmd->code));
3619815c7cfSMichael Thalmeier }
3629815c7cfSMichael Thalmeier EXPORT_SYMBOL_GPL(pn533_rx_frame_is_cmd_response);
3639815c7cfSMichael Thalmeier
3649815c7cfSMichael Thalmeier
3659815c7cfSMichael Thalmeier static struct pn533_frame_ops pn533_std_frame_ops = {
3669815c7cfSMichael Thalmeier .tx_frame_init = pn533_std_tx_frame_init,
3679815c7cfSMichael Thalmeier .tx_frame_finish = pn533_std_tx_frame_finish,
3689815c7cfSMichael Thalmeier .tx_update_payload_len = pn533_std_tx_update_payload_len,
3699815c7cfSMichael Thalmeier .tx_header_len = PN533_STD_FRAME_HEADER_LEN,
3709815c7cfSMichael Thalmeier .tx_tail_len = PN533_STD_FRAME_TAIL_LEN,
3719815c7cfSMichael Thalmeier
3729815c7cfSMichael Thalmeier .rx_is_frame_valid = pn533_std_rx_frame_is_valid,
3739815c7cfSMichael Thalmeier .rx_frame_size = pn533_std_rx_frame_size,
3749815c7cfSMichael Thalmeier .rx_header_len = PN533_STD_FRAME_HEADER_LEN,
3759815c7cfSMichael Thalmeier .rx_tail_len = PN533_STD_FRAME_TAIL_LEN,
3769815c7cfSMichael Thalmeier
3779815c7cfSMichael Thalmeier .max_payload_len = PN533_STD_FRAME_MAX_PAYLOAD_LEN,
3789815c7cfSMichael Thalmeier .get_cmd_code = pn533_std_get_cmd_code,
3799815c7cfSMichael Thalmeier };
3809815c7cfSMichael Thalmeier
pn533_build_cmd_frame(struct pn533 * dev,u8 cmd_code,struct sk_buff * skb)3819815c7cfSMichael Thalmeier static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code,
3829815c7cfSMichael Thalmeier struct sk_buff *skb)
3839815c7cfSMichael Thalmeier {
3849815c7cfSMichael Thalmeier /* payload is already there, just update datalen */
3859815c7cfSMichael Thalmeier int payload_len = skb->len;
3869815c7cfSMichael Thalmeier struct pn533_frame_ops *ops = dev->ops;
3879815c7cfSMichael Thalmeier
3889815c7cfSMichael Thalmeier
3899815c7cfSMichael Thalmeier skb_push(skb, ops->tx_header_len);
3909815c7cfSMichael Thalmeier skb_put(skb, ops->tx_tail_len);
3919815c7cfSMichael Thalmeier
3929815c7cfSMichael Thalmeier ops->tx_frame_init(skb->data, cmd_code);
3939815c7cfSMichael Thalmeier ops->tx_update_payload_len(skb->data, payload_len);
3949815c7cfSMichael Thalmeier ops->tx_frame_finish(skb->data);
3959815c7cfSMichael Thalmeier }
3969815c7cfSMichael Thalmeier
pn533_send_async_complete(struct pn533 * dev)3979815c7cfSMichael Thalmeier static int pn533_send_async_complete(struct pn533 *dev)
3989815c7cfSMichael Thalmeier {
3999815c7cfSMichael Thalmeier struct pn533_cmd *cmd = dev->cmd;
4005dd9c1bdSAndrey Rusalin struct sk_buff *resp;
4015dd9c1bdSAndrey Rusalin int status, rc = 0;
4029815c7cfSMichael Thalmeier
4035dd9c1bdSAndrey Rusalin if (!cmd) {
4045dd9c1bdSAndrey Rusalin dev_dbg(dev->dev, "%s: cmd not set\n", __func__);
4055dd9c1bdSAndrey Rusalin goto done;
4065dd9c1bdSAndrey Rusalin }
4079815c7cfSMichael Thalmeier
4085dd9c1bdSAndrey Rusalin dev_kfree_skb(cmd->req);
4099815c7cfSMichael Thalmeier
4105dd9c1bdSAndrey Rusalin status = cmd->status;
4115dd9c1bdSAndrey Rusalin resp = cmd->resp;
4129815c7cfSMichael Thalmeier
4139815c7cfSMichael Thalmeier if (status < 0) {
4149815c7cfSMichael Thalmeier rc = cmd->complete_cb(dev, cmd->complete_cb_context,
4159815c7cfSMichael Thalmeier ERR_PTR(status));
4169815c7cfSMichael Thalmeier dev_kfree_skb(resp);
4179815c7cfSMichael Thalmeier goto done;
4189815c7cfSMichael Thalmeier }
4199815c7cfSMichael Thalmeier
4205dd9c1bdSAndrey Rusalin /* when no response is set we got interrupted */
4215dd9c1bdSAndrey Rusalin if (!resp)
4225dd9c1bdSAndrey Rusalin resp = ERR_PTR(-EINTR);
4235dd9c1bdSAndrey Rusalin
4245dd9c1bdSAndrey Rusalin if (!IS_ERR(resp)) {
4259815c7cfSMichael Thalmeier skb_pull(resp, dev->ops->rx_header_len);
4269815c7cfSMichael Thalmeier skb_trim(resp, resp->len - dev->ops->rx_tail_len);
4275dd9c1bdSAndrey Rusalin }
4289815c7cfSMichael Thalmeier
4299815c7cfSMichael Thalmeier rc = cmd->complete_cb(dev, cmd->complete_cb_context, resp);
4309815c7cfSMichael Thalmeier
4319815c7cfSMichael Thalmeier done:
4329815c7cfSMichael Thalmeier kfree(cmd);
4339815c7cfSMichael Thalmeier dev->cmd = NULL;
4349815c7cfSMichael Thalmeier return rc;
4359815c7cfSMichael Thalmeier }
4369815c7cfSMichael Thalmeier
__pn533_send_async(struct pn533 * dev,u8 cmd_code,struct sk_buff * req,pn533_send_async_complete_t complete_cb,void * complete_cb_context)4379815c7cfSMichael Thalmeier static int __pn533_send_async(struct pn533 *dev, u8 cmd_code,
4389815c7cfSMichael Thalmeier struct sk_buff *req,
4399815c7cfSMichael Thalmeier pn533_send_async_complete_t complete_cb,
4409815c7cfSMichael Thalmeier void *complete_cb_context)
4419815c7cfSMichael Thalmeier {
4429815c7cfSMichael Thalmeier struct pn533_cmd *cmd;
4439815c7cfSMichael Thalmeier int rc = 0;
4449815c7cfSMichael Thalmeier
4459815c7cfSMichael Thalmeier dev_dbg(dev->dev, "Sending command 0x%x\n", cmd_code);
4469815c7cfSMichael Thalmeier
4479815c7cfSMichael Thalmeier cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
4489815c7cfSMichael Thalmeier if (!cmd)
4499815c7cfSMichael Thalmeier return -ENOMEM;
4509815c7cfSMichael Thalmeier
4519815c7cfSMichael Thalmeier cmd->code = cmd_code;
4529815c7cfSMichael Thalmeier cmd->req = req;
4539815c7cfSMichael Thalmeier cmd->complete_cb = complete_cb;
4549815c7cfSMichael Thalmeier cmd->complete_cb_context = complete_cb_context;
4559815c7cfSMichael Thalmeier
4569815c7cfSMichael Thalmeier pn533_build_cmd_frame(dev, cmd_code, req);
4579815c7cfSMichael Thalmeier
4589815c7cfSMichael Thalmeier mutex_lock(&dev->cmd_lock);
4599815c7cfSMichael Thalmeier
4609815c7cfSMichael Thalmeier if (!dev->cmd_pending) {
4615dd9c1bdSAndrey Rusalin dev->cmd = cmd;
4629815c7cfSMichael Thalmeier rc = dev->phy_ops->send_frame(dev, req);
4635dd9c1bdSAndrey Rusalin if (rc) {
4645dd9c1bdSAndrey Rusalin dev->cmd = NULL;
4659815c7cfSMichael Thalmeier goto error;
4665dd9c1bdSAndrey Rusalin }
4679815c7cfSMichael Thalmeier
4689815c7cfSMichael Thalmeier dev->cmd_pending = 1;
4699815c7cfSMichael Thalmeier goto unlock;
4709815c7cfSMichael Thalmeier }
4719815c7cfSMichael Thalmeier
4729815c7cfSMichael Thalmeier dev_dbg(dev->dev, "%s Queueing command 0x%x\n",
4739815c7cfSMichael Thalmeier __func__, cmd_code);
4749815c7cfSMichael Thalmeier
4759815c7cfSMichael Thalmeier INIT_LIST_HEAD(&cmd->queue);
4769815c7cfSMichael Thalmeier list_add_tail(&cmd->queue, &dev->cmd_queue);
4779815c7cfSMichael Thalmeier
4789815c7cfSMichael Thalmeier goto unlock;
4799815c7cfSMichael Thalmeier
4809815c7cfSMichael Thalmeier error:
4819815c7cfSMichael Thalmeier kfree(cmd);
4829815c7cfSMichael Thalmeier unlock:
4839815c7cfSMichael Thalmeier mutex_unlock(&dev->cmd_lock);
4849815c7cfSMichael Thalmeier return rc;
4859815c7cfSMichael Thalmeier }
4869815c7cfSMichael Thalmeier
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)4879815c7cfSMichael Thalmeier static int pn533_send_data_async(struct pn533 *dev, u8 cmd_code,
4889815c7cfSMichael Thalmeier struct sk_buff *req,
4899815c7cfSMichael Thalmeier pn533_send_async_complete_t complete_cb,
4909815c7cfSMichael Thalmeier void *complete_cb_context)
4919815c7cfSMichael Thalmeier {
492a115d24aSwengjianfeng return __pn533_send_async(dev, cmd_code, req, complete_cb,
4939815c7cfSMichael Thalmeier complete_cb_context);
4949815c7cfSMichael Thalmeier }
4959815c7cfSMichael Thalmeier
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)4969815c7cfSMichael Thalmeier static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code,
4979815c7cfSMichael Thalmeier struct sk_buff *req,
4989815c7cfSMichael Thalmeier pn533_send_async_complete_t complete_cb,
4999815c7cfSMichael Thalmeier void *complete_cb_context)
5009815c7cfSMichael Thalmeier {
501a115d24aSwengjianfeng return __pn533_send_async(dev, cmd_code, req, complete_cb,
5029815c7cfSMichael Thalmeier complete_cb_context);
5039815c7cfSMichael Thalmeier }
5049815c7cfSMichael Thalmeier
5059815c7cfSMichael Thalmeier /*
5069815c7cfSMichael Thalmeier * pn533_send_cmd_direct_async
5079815c7cfSMichael Thalmeier *
508d6adfd37Swengjianfeng * The function sends a priority cmd directly to the chip omitting the cmd
5099815c7cfSMichael Thalmeier * queue. It's intended to be used by chaining mechanism of received responses
5109815c7cfSMichael Thalmeier * where the host has to request every single chunk of data before scheduling
5119815c7cfSMichael Thalmeier * next cmd from the queue.
5129815c7cfSMichael Thalmeier */
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)5139815c7cfSMichael Thalmeier static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code,
5149815c7cfSMichael Thalmeier struct sk_buff *req,
5159815c7cfSMichael Thalmeier pn533_send_async_complete_t complete_cb,
5169815c7cfSMichael Thalmeier void *complete_cb_context)
5179815c7cfSMichael Thalmeier {
5189815c7cfSMichael Thalmeier struct pn533_cmd *cmd;
5199815c7cfSMichael Thalmeier int rc;
5209815c7cfSMichael Thalmeier
5219815c7cfSMichael Thalmeier cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
5229815c7cfSMichael Thalmeier if (!cmd)
5239815c7cfSMichael Thalmeier return -ENOMEM;
5249815c7cfSMichael Thalmeier
5259815c7cfSMichael Thalmeier cmd->code = cmd_code;
5269815c7cfSMichael Thalmeier cmd->req = req;
5279815c7cfSMichael Thalmeier cmd->complete_cb = complete_cb;
5289815c7cfSMichael Thalmeier cmd->complete_cb_context = complete_cb_context;
5299815c7cfSMichael Thalmeier
5309815c7cfSMichael Thalmeier pn533_build_cmd_frame(dev, cmd_code, req);
5319815c7cfSMichael Thalmeier
5329815c7cfSMichael Thalmeier dev->cmd = cmd;
5335dd9c1bdSAndrey Rusalin rc = dev->phy_ops->send_frame(dev, req);
5345dd9c1bdSAndrey Rusalin if (rc < 0) {
5355dd9c1bdSAndrey Rusalin dev->cmd = NULL;
5365dd9c1bdSAndrey Rusalin kfree(cmd);
5375dd9c1bdSAndrey Rusalin }
5389815c7cfSMichael Thalmeier
5399815c7cfSMichael Thalmeier return rc;
5409815c7cfSMichael Thalmeier }
5419815c7cfSMichael Thalmeier
pn533_wq_cmd_complete(struct work_struct * work)5429815c7cfSMichael Thalmeier static void pn533_wq_cmd_complete(struct work_struct *work)
5439815c7cfSMichael Thalmeier {
5449815c7cfSMichael Thalmeier struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work);
5459815c7cfSMichael Thalmeier int rc;
5469815c7cfSMichael Thalmeier
5479815c7cfSMichael Thalmeier rc = pn533_send_async_complete(dev);
5489815c7cfSMichael Thalmeier if (rc != -EINPROGRESS)
5499815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->cmd_work);
5509815c7cfSMichael Thalmeier }
5519815c7cfSMichael Thalmeier
pn533_wq_cmd(struct work_struct * work)5529815c7cfSMichael Thalmeier static void pn533_wq_cmd(struct work_struct *work)
5539815c7cfSMichael Thalmeier {
5549815c7cfSMichael Thalmeier struct pn533 *dev = container_of(work, struct pn533, cmd_work);
5559815c7cfSMichael Thalmeier struct pn533_cmd *cmd;
5569815c7cfSMichael Thalmeier int rc;
5579815c7cfSMichael Thalmeier
5589815c7cfSMichael Thalmeier mutex_lock(&dev->cmd_lock);
5599815c7cfSMichael Thalmeier
5609815c7cfSMichael Thalmeier if (list_empty(&dev->cmd_queue)) {
5619815c7cfSMichael Thalmeier dev->cmd_pending = 0;
5629815c7cfSMichael Thalmeier mutex_unlock(&dev->cmd_lock);
5639815c7cfSMichael Thalmeier return;
5649815c7cfSMichael Thalmeier }
5659815c7cfSMichael Thalmeier
5669815c7cfSMichael Thalmeier cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue);
5679815c7cfSMichael Thalmeier
5689815c7cfSMichael Thalmeier list_del(&cmd->queue);
5699815c7cfSMichael Thalmeier
5709815c7cfSMichael Thalmeier mutex_unlock(&dev->cmd_lock);
5719815c7cfSMichael Thalmeier
5725dd9c1bdSAndrey Rusalin dev->cmd = cmd;
5739815c7cfSMichael Thalmeier rc = dev->phy_ops->send_frame(dev, cmd->req);
5749815c7cfSMichael Thalmeier if (rc < 0) {
5755dd9c1bdSAndrey Rusalin dev->cmd = NULL;
5769815c7cfSMichael Thalmeier dev_kfree_skb(cmd->req);
5779815c7cfSMichael Thalmeier kfree(cmd);
5789815c7cfSMichael Thalmeier return;
5799815c7cfSMichael Thalmeier }
5809815c7cfSMichael Thalmeier
5819815c7cfSMichael Thalmeier }
5829815c7cfSMichael Thalmeier
5839815c7cfSMichael Thalmeier struct pn533_sync_cmd_response {
5849815c7cfSMichael Thalmeier struct sk_buff *resp;
5859815c7cfSMichael Thalmeier struct completion done;
5869815c7cfSMichael Thalmeier };
5879815c7cfSMichael Thalmeier
pn533_send_sync_complete(struct pn533 * dev,void * _arg,struct sk_buff * resp)5889815c7cfSMichael Thalmeier static int pn533_send_sync_complete(struct pn533 *dev, void *_arg,
5899815c7cfSMichael Thalmeier struct sk_buff *resp)
5909815c7cfSMichael Thalmeier {
5919815c7cfSMichael Thalmeier struct pn533_sync_cmd_response *arg = _arg;
5929815c7cfSMichael Thalmeier
5939815c7cfSMichael Thalmeier arg->resp = resp;
5949815c7cfSMichael Thalmeier complete(&arg->done);
5959815c7cfSMichael Thalmeier
5969815c7cfSMichael Thalmeier return 0;
5979815c7cfSMichael Thalmeier }
5989815c7cfSMichael Thalmeier
5999815c7cfSMichael Thalmeier /* pn533_send_cmd_sync
6009815c7cfSMichael Thalmeier *
6019815c7cfSMichael Thalmeier * Please note the req parameter is freed inside the function to
6029815c7cfSMichael Thalmeier * limit a number of return value interpretations by the caller.
6039815c7cfSMichael Thalmeier *
6049815c7cfSMichael Thalmeier * 1. negative in case of error during TX path -> req should be freed
6059815c7cfSMichael Thalmeier *
6069815c7cfSMichael Thalmeier * 2. negative in case of error during RX path -> req should not be freed
6079815c7cfSMichael Thalmeier * as it's been already freed at the beginning of RX path by
6089815c7cfSMichael Thalmeier * async_complete_cb.
6099815c7cfSMichael Thalmeier *
610d6adfd37Swengjianfeng * 3. valid pointer in case of successful RX path
6119815c7cfSMichael Thalmeier *
6129815c7cfSMichael Thalmeier * A caller has to check a return value with IS_ERR macro. If the test pass,
6139815c7cfSMichael Thalmeier * the returned pointer is valid.
6149815c7cfSMichael Thalmeier *
6159815c7cfSMichael Thalmeier */
pn533_send_cmd_sync(struct pn533 * dev,u8 cmd_code,struct sk_buff * req)6169815c7cfSMichael Thalmeier static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code,
6179815c7cfSMichael Thalmeier struct sk_buff *req)
6189815c7cfSMichael Thalmeier {
6199815c7cfSMichael Thalmeier int rc;
6209815c7cfSMichael Thalmeier struct pn533_sync_cmd_response arg;
6219815c7cfSMichael Thalmeier
6229815c7cfSMichael Thalmeier init_completion(&arg.done);
6239815c7cfSMichael Thalmeier
6249815c7cfSMichael Thalmeier rc = pn533_send_cmd_async(dev, cmd_code, req,
6259815c7cfSMichael Thalmeier pn533_send_sync_complete, &arg);
6269815c7cfSMichael Thalmeier if (rc) {
6279815c7cfSMichael Thalmeier dev_kfree_skb(req);
6289815c7cfSMichael Thalmeier return ERR_PTR(rc);
6299815c7cfSMichael Thalmeier }
6309815c7cfSMichael Thalmeier
6319815c7cfSMichael Thalmeier wait_for_completion(&arg.done);
6329815c7cfSMichael Thalmeier
6339815c7cfSMichael Thalmeier return arg.resp;
6349815c7cfSMichael Thalmeier }
6359815c7cfSMichael Thalmeier
pn533_alloc_skb(struct pn533 * dev,unsigned int size)6369815c7cfSMichael Thalmeier static struct sk_buff *pn533_alloc_skb(struct pn533 *dev, unsigned int size)
6379815c7cfSMichael Thalmeier {
6389815c7cfSMichael Thalmeier struct sk_buff *skb;
6399815c7cfSMichael Thalmeier
6409815c7cfSMichael Thalmeier skb = alloc_skb(dev->ops->tx_header_len +
6419815c7cfSMichael Thalmeier size +
6429815c7cfSMichael Thalmeier dev->ops->tx_tail_len, GFP_KERNEL);
6439815c7cfSMichael Thalmeier
6449815c7cfSMichael Thalmeier if (skb)
6459815c7cfSMichael Thalmeier skb_reserve(skb, dev->ops->tx_header_len);
6469815c7cfSMichael Thalmeier
6479815c7cfSMichael Thalmeier return skb;
6489815c7cfSMichael Thalmeier }
6499815c7cfSMichael Thalmeier
6509815c7cfSMichael Thalmeier struct pn533_target_type_a {
6519815c7cfSMichael Thalmeier __be16 sens_res;
6529815c7cfSMichael Thalmeier u8 sel_res;
6539815c7cfSMichael Thalmeier u8 nfcid_len;
6549815c7cfSMichael Thalmeier u8 nfcid_data[];
6559815c7cfSMichael Thalmeier } __packed;
6569815c7cfSMichael Thalmeier
6579815c7cfSMichael Thalmeier
6589815c7cfSMichael Thalmeier #define PN533_TYPE_A_SENS_RES_NFCID1(x) ((u8)((be16_to_cpu(x) & 0x00C0) >> 6))
6599815c7cfSMichael Thalmeier #define PN533_TYPE_A_SENS_RES_SSD(x) ((u8)((be16_to_cpu(x) & 0x001F) >> 0))
6609815c7cfSMichael Thalmeier #define PN533_TYPE_A_SENS_RES_PLATCONF(x) ((u8)((be16_to_cpu(x) & 0x0F00) >> 8))
6619815c7cfSMichael Thalmeier
6629815c7cfSMichael Thalmeier #define PN533_TYPE_A_SENS_RES_SSD_JEWEL 0x00
6639815c7cfSMichael Thalmeier #define PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL 0x0C
6649815c7cfSMichael Thalmeier
6659815c7cfSMichael Thalmeier #define PN533_TYPE_A_SEL_PROT(x) (((x) & 0x60) >> 5)
6669815c7cfSMichael Thalmeier #define PN533_TYPE_A_SEL_CASCADE(x) (((x) & 0x04) >> 2)
6679815c7cfSMichael Thalmeier
6689815c7cfSMichael Thalmeier #define PN533_TYPE_A_SEL_PROT_MIFARE 0
6699815c7cfSMichael Thalmeier #define PN533_TYPE_A_SEL_PROT_ISO14443 1
6709815c7cfSMichael Thalmeier #define PN533_TYPE_A_SEL_PROT_DEP 2
6719815c7cfSMichael Thalmeier #define PN533_TYPE_A_SEL_PROT_ISO14443_DEP 3
6729815c7cfSMichael Thalmeier
pn533_target_type_a_is_valid(struct pn533_target_type_a * type_a,int target_data_len)6739815c7cfSMichael Thalmeier static bool pn533_target_type_a_is_valid(struct pn533_target_type_a *type_a,
6749815c7cfSMichael Thalmeier int target_data_len)
6759815c7cfSMichael Thalmeier {
6769815c7cfSMichael Thalmeier u8 ssd;
6779815c7cfSMichael Thalmeier u8 platconf;
6789815c7cfSMichael Thalmeier
6799815c7cfSMichael Thalmeier if (target_data_len < sizeof(struct pn533_target_type_a))
6809815c7cfSMichael Thalmeier return false;
6819815c7cfSMichael Thalmeier
6829815c7cfSMichael Thalmeier /*
6839815c7cfSMichael Thalmeier * The length check of nfcid[] and ats[] are not being performed because
6849815c7cfSMichael Thalmeier * the values are not being used
6859815c7cfSMichael Thalmeier */
6869815c7cfSMichael Thalmeier
6879815c7cfSMichael Thalmeier /* Requirement 4.6.3.3 from NFC Forum Digital Spec */
6889815c7cfSMichael Thalmeier ssd = PN533_TYPE_A_SENS_RES_SSD(type_a->sens_res);
6899815c7cfSMichael Thalmeier platconf = PN533_TYPE_A_SENS_RES_PLATCONF(type_a->sens_res);
6909815c7cfSMichael Thalmeier
6919815c7cfSMichael Thalmeier if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
6929815c7cfSMichael Thalmeier platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) ||
6939815c7cfSMichael Thalmeier (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
6949815c7cfSMichael Thalmeier platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL))
6959815c7cfSMichael Thalmeier return false;
6969815c7cfSMichael Thalmeier
6979815c7cfSMichael Thalmeier /* Requirements 4.8.2.1, 4.8.2.3, 4.8.2.5 and 4.8.2.7 from NFC Forum */
6989815c7cfSMichael Thalmeier if (PN533_TYPE_A_SEL_CASCADE(type_a->sel_res) != 0)
6999815c7cfSMichael Thalmeier return false;
7009815c7cfSMichael Thalmeier
701ca4d4c34SDan Carpenter if (type_a->nfcid_len > NFC_NFCID1_MAXSIZE)
702ca4d4c34SDan Carpenter return false;
703ca4d4c34SDan Carpenter
7049815c7cfSMichael Thalmeier return true;
7059815c7cfSMichael Thalmeier }
7069815c7cfSMichael Thalmeier
pn533_target_found_type_a(struct nfc_target * nfc_tgt,u8 * tgt_data,int tgt_data_len)7079815c7cfSMichael Thalmeier static int pn533_target_found_type_a(struct nfc_target *nfc_tgt, u8 *tgt_data,
7089815c7cfSMichael Thalmeier int tgt_data_len)
7099815c7cfSMichael Thalmeier {
7109815c7cfSMichael Thalmeier struct pn533_target_type_a *tgt_type_a;
7119815c7cfSMichael Thalmeier
7129815c7cfSMichael Thalmeier tgt_type_a = (struct pn533_target_type_a *)tgt_data;
7139815c7cfSMichael Thalmeier
7149815c7cfSMichael Thalmeier if (!pn533_target_type_a_is_valid(tgt_type_a, tgt_data_len))
7159815c7cfSMichael Thalmeier return -EPROTO;
7169815c7cfSMichael Thalmeier
7179815c7cfSMichael Thalmeier switch (PN533_TYPE_A_SEL_PROT(tgt_type_a->sel_res)) {
7189815c7cfSMichael Thalmeier case PN533_TYPE_A_SEL_PROT_MIFARE:
7199815c7cfSMichael Thalmeier nfc_tgt->supported_protocols = NFC_PROTO_MIFARE_MASK;
7209815c7cfSMichael Thalmeier break;
7219815c7cfSMichael Thalmeier case PN533_TYPE_A_SEL_PROT_ISO14443:
7229815c7cfSMichael Thalmeier nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK;
7239815c7cfSMichael Thalmeier break;
7249815c7cfSMichael Thalmeier case PN533_TYPE_A_SEL_PROT_DEP:
7259815c7cfSMichael Thalmeier nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
7269815c7cfSMichael Thalmeier break;
7279815c7cfSMichael Thalmeier case PN533_TYPE_A_SEL_PROT_ISO14443_DEP:
7289815c7cfSMichael Thalmeier nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK |
7299815c7cfSMichael Thalmeier NFC_PROTO_NFC_DEP_MASK;
7309815c7cfSMichael Thalmeier break;
7319815c7cfSMichael Thalmeier }
7329815c7cfSMichael Thalmeier
7339815c7cfSMichael Thalmeier nfc_tgt->sens_res = be16_to_cpu(tgt_type_a->sens_res);
7349815c7cfSMichael Thalmeier nfc_tgt->sel_res = tgt_type_a->sel_res;
7359815c7cfSMichael Thalmeier nfc_tgt->nfcid1_len = tgt_type_a->nfcid_len;
7369815c7cfSMichael Thalmeier memcpy(nfc_tgt->nfcid1, tgt_type_a->nfcid_data, nfc_tgt->nfcid1_len);
7379815c7cfSMichael Thalmeier
7389815c7cfSMichael Thalmeier return 0;
7399815c7cfSMichael Thalmeier }
7409815c7cfSMichael Thalmeier
7419815c7cfSMichael Thalmeier struct pn533_target_felica {
7429815c7cfSMichael Thalmeier u8 pol_res;
7439815c7cfSMichael Thalmeier u8 opcode;
7449815c7cfSMichael Thalmeier u8 nfcid2[NFC_NFCID2_MAXSIZE];
7459815c7cfSMichael Thalmeier u8 pad[8];
7469815c7cfSMichael Thalmeier /* optional */
7479815c7cfSMichael Thalmeier u8 syst_code[];
7489815c7cfSMichael Thalmeier } __packed;
7499815c7cfSMichael Thalmeier
7509815c7cfSMichael Thalmeier #define PN533_FELICA_SENSF_NFCID2_DEP_B1 0x01
7519815c7cfSMichael Thalmeier #define PN533_FELICA_SENSF_NFCID2_DEP_B2 0xFE
7529815c7cfSMichael Thalmeier
pn533_target_felica_is_valid(struct pn533_target_felica * felica,int target_data_len)7539815c7cfSMichael Thalmeier static bool pn533_target_felica_is_valid(struct pn533_target_felica *felica,
7549815c7cfSMichael Thalmeier int target_data_len)
7559815c7cfSMichael Thalmeier {
7569815c7cfSMichael Thalmeier if (target_data_len < sizeof(struct pn533_target_felica))
7579815c7cfSMichael Thalmeier return false;
7589815c7cfSMichael Thalmeier
7599815c7cfSMichael Thalmeier if (felica->opcode != PN533_FELICA_OPC_SENSF_RES)
7609815c7cfSMichael Thalmeier return false;
7619815c7cfSMichael Thalmeier
7629815c7cfSMichael Thalmeier return true;
7639815c7cfSMichael Thalmeier }
7649815c7cfSMichael Thalmeier
pn533_target_found_felica(struct nfc_target * nfc_tgt,u8 * tgt_data,int tgt_data_len)7659815c7cfSMichael Thalmeier static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data,
7669815c7cfSMichael Thalmeier int tgt_data_len)
7679815c7cfSMichael Thalmeier {
7689815c7cfSMichael Thalmeier struct pn533_target_felica *tgt_felica;
7699815c7cfSMichael Thalmeier
7709815c7cfSMichael Thalmeier tgt_felica = (struct pn533_target_felica *)tgt_data;
7719815c7cfSMichael Thalmeier
7729815c7cfSMichael Thalmeier if (!pn533_target_felica_is_valid(tgt_felica, tgt_data_len))
7739815c7cfSMichael Thalmeier return -EPROTO;
7749815c7cfSMichael Thalmeier
7759815c7cfSMichael Thalmeier if ((tgt_felica->nfcid2[0] == PN533_FELICA_SENSF_NFCID2_DEP_B1) &&
7769815c7cfSMichael Thalmeier (tgt_felica->nfcid2[1] == PN533_FELICA_SENSF_NFCID2_DEP_B2))
7779815c7cfSMichael Thalmeier nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
7789815c7cfSMichael Thalmeier else
7799815c7cfSMichael Thalmeier nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK;
7809815c7cfSMichael Thalmeier
7819815c7cfSMichael Thalmeier memcpy(nfc_tgt->sensf_res, &tgt_felica->opcode, 9);
7829815c7cfSMichael Thalmeier nfc_tgt->sensf_res_len = 9;
7839815c7cfSMichael Thalmeier
7849815c7cfSMichael Thalmeier memcpy(nfc_tgt->nfcid2, tgt_felica->nfcid2, NFC_NFCID2_MAXSIZE);
7859815c7cfSMichael Thalmeier nfc_tgt->nfcid2_len = NFC_NFCID2_MAXSIZE;
7869815c7cfSMichael Thalmeier
7879815c7cfSMichael Thalmeier return 0;
7889815c7cfSMichael Thalmeier }
7899815c7cfSMichael Thalmeier
7909815c7cfSMichael Thalmeier struct pn533_target_jewel {
7919815c7cfSMichael Thalmeier __be16 sens_res;
7929815c7cfSMichael Thalmeier u8 jewelid[4];
7939815c7cfSMichael Thalmeier } __packed;
7949815c7cfSMichael Thalmeier
pn533_target_jewel_is_valid(struct pn533_target_jewel * jewel,int target_data_len)7959815c7cfSMichael Thalmeier static bool pn533_target_jewel_is_valid(struct pn533_target_jewel *jewel,
7969815c7cfSMichael Thalmeier int target_data_len)
7979815c7cfSMichael Thalmeier {
7989815c7cfSMichael Thalmeier u8 ssd;
7999815c7cfSMichael Thalmeier u8 platconf;
8009815c7cfSMichael Thalmeier
8019815c7cfSMichael Thalmeier if (target_data_len < sizeof(struct pn533_target_jewel))
8029815c7cfSMichael Thalmeier return false;
8039815c7cfSMichael Thalmeier
8049815c7cfSMichael Thalmeier /* Requirement 4.6.3.3 from NFC Forum Digital Spec */
8059815c7cfSMichael Thalmeier ssd = PN533_TYPE_A_SENS_RES_SSD(jewel->sens_res);
8069815c7cfSMichael Thalmeier platconf = PN533_TYPE_A_SENS_RES_PLATCONF(jewel->sens_res);
8079815c7cfSMichael Thalmeier
8089815c7cfSMichael Thalmeier if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
8099815c7cfSMichael Thalmeier platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) ||
8109815c7cfSMichael Thalmeier (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
8119815c7cfSMichael Thalmeier platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL))
8129815c7cfSMichael Thalmeier return false;
8139815c7cfSMichael Thalmeier
8149815c7cfSMichael Thalmeier return true;
8159815c7cfSMichael Thalmeier }
8169815c7cfSMichael Thalmeier
pn533_target_found_jewel(struct nfc_target * nfc_tgt,u8 * tgt_data,int tgt_data_len)8179815c7cfSMichael Thalmeier static int pn533_target_found_jewel(struct nfc_target *nfc_tgt, u8 *tgt_data,
8189815c7cfSMichael Thalmeier int tgt_data_len)
8199815c7cfSMichael Thalmeier {
8209815c7cfSMichael Thalmeier struct pn533_target_jewel *tgt_jewel;
8219815c7cfSMichael Thalmeier
8229815c7cfSMichael Thalmeier tgt_jewel = (struct pn533_target_jewel *)tgt_data;
8239815c7cfSMichael Thalmeier
8249815c7cfSMichael Thalmeier if (!pn533_target_jewel_is_valid(tgt_jewel, tgt_data_len))
8259815c7cfSMichael Thalmeier return -EPROTO;
8269815c7cfSMichael Thalmeier
8279815c7cfSMichael Thalmeier nfc_tgt->supported_protocols = NFC_PROTO_JEWEL_MASK;
8289815c7cfSMichael Thalmeier nfc_tgt->sens_res = be16_to_cpu(tgt_jewel->sens_res);
8299815c7cfSMichael Thalmeier nfc_tgt->nfcid1_len = 4;
8309815c7cfSMichael Thalmeier memcpy(nfc_tgt->nfcid1, tgt_jewel->jewelid, nfc_tgt->nfcid1_len);
8319815c7cfSMichael Thalmeier
8329815c7cfSMichael Thalmeier return 0;
8339815c7cfSMichael Thalmeier }
8349815c7cfSMichael Thalmeier
8359815c7cfSMichael Thalmeier struct pn533_type_b_prot_info {
8369815c7cfSMichael Thalmeier u8 bitrate;
8379815c7cfSMichael Thalmeier u8 fsci_type;
8389815c7cfSMichael Thalmeier u8 fwi_adc_fo;
8399815c7cfSMichael Thalmeier } __packed;
8409815c7cfSMichael Thalmeier
8419815c7cfSMichael Thalmeier #define PN533_TYPE_B_PROT_FCSI(x) (((x) & 0xF0) >> 4)
8429815c7cfSMichael Thalmeier #define PN533_TYPE_B_PROT_TYPE(x) (((x) & 0x0F) >> 0)
8439815c7cfSMichael Thalmeier #define PN533_TYPE_B_PROT_TYPE_RFU_MASK 0x8
8449815c7cfSMichael Thalmeier
8459815c7cfSMichael Thalmeier struct pn533_type_b_sens_res {
8469815c7cfSMichael Thalmeier u8 opcode;
8479815c7cfSMichael Thalmeier u8 nfcid[4];
8489815c7cfSMichael Thalmeier u8 appdata[4];
8499815c7cfSMichael Thalmeier struct pn533_type_b_prot_info prot_info;
8509815c7cfSMichael Thalmeier } __packed;
8519815c7cfSMichael Thalmeier
8529815c7cfSMichael Thalmeier #define PN533_TYPE_B_OPC_SENSB_RES 0x50
8539815c7cfSMichael Thalmeier
8549815c7cfSMichael Thalmeier struct pn533_target_type_b {
8559815c7cfSMichael Thalmeier struct pn533_type_b_sens_res sensb_res;
8569815c7cfSMichael Thalmeier u8 attrib_res_len;
8579815c7cfSMichael Thalmeier u8 attrib_res[];
8589815c7cfSMichael Thalmeier } __packed;
8599815c7cfSMichael Thalmeier
pn533_target_type_b_is_valid(struct pn533_target_type_b * type_b,int target_data_len)8609815c7cfSMichael Thalmeier static bool pn533_target_type_b_is_valid(struct pn533_target_type_b *type_b,
8619815c7cfSMichael Thalmeier int target_data_len)
8629815c7cfSMichael Thalmeier {
8639815c7cfSMichael Thalmeier if (target_data_len < sizeof(struct pn533_target_type_b))
8649815c7cfSMichael Thalmeier return false;
8659815c7cfSMichael Thalmeier
8669815c7cfSMichael Thalmeier if (type_b->sensb_res.opcode != PN533_TYPE_B_OPC_SENSB_RES)
8679815c7cfSMichael Thalmeier return false;
8689815c7cfSMichael Thalmeier
8699815c7cfSMichael Thalmeier if (PN533_TYPE_B_PROT_TYPE(type_b->sensb_res.prot_info.fsci_type) &
8709815c7cfSMichael Thalmeier PN533_TYPE_B_PROT_TYPE_RFU_MASK)
8719815c7cfSMichael Thalmeier return false;
8729815c7cfSMichael Thalmeier
8739815c7cfSMichael Thalmeier return true;
8749815c7cfSMichael Thalmeier }
8759815c7cfSMichael Thalmeier
pn533_target_found_type_b(struct nfc_target * nfc_tgt,u8 * tgt_data,int tgt_data_len)8769815c7cfSMichael Thalmeier static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data,
8779815c7cfSMichael Thalmeier int tgt_data_len)
8789815c7cfSMichael Thalmeier {
8799815c7cfSMichael Thalmeier struct pn533_target_type_b *tgt_type_b;
8809815c7cfSMichael Thalmeier
8819815c7cfSMichael Thalmeier tgt_type_b = (struct pn533_target_type_b *)tgt_data;
8829815c7cfSMichael Thalmeier
8839815c7cfSMichael Thalmeier if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len))
8849815c7cfSMichael Thalmeier return -EPROTO;
8859815c7cfSMichael Thalmeier
8869815c7cfSMichael Thalmeier nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
8879815c7cfSMichael Thalmeier
8889815c7cfSMichael Thalmeier return 0;
8899815c7cfSMichael Thalmeier }
8909815c7cfSMichael Thalmeier
891c952f915SMichael Thalmeier static void pn533_poll_reset_mod_list(struct pn533 *dev);
pn533_target_found(struct pn533 * dev,u8 tg,u8 * tgdata,int tgdata_len)8929815c7cfSMichael Thalmeier static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata,
8939815c7cfSMichael Thalmeier int tgdata_len)
8949815c7cfSMichael Thalmeier {
8959815c7cfSMichael Thalmeier struct nfc_target nfc_tgt;
8969815c7cfSMichael Thalmeier int rc;
8979815c7cfSMichael Thalmeier
8989815c7cfSMichael Thalmeier dev_dbg(dev->dev, "%s: modulation=%d\n",
8999815c7cfSMichael Thalmeier __func__, dev->poll_mod_curr);
9009815c7cfSMichael Thalmeier
9019815c7cfSMichael Thalmeier if (tg != 1)
9029815c7cfSMichael Thalmeier return -EPROTO;
9039815c7cfSMichael Thalmeier
9049815c7cfSMichael Thalmeier memset(&nfc_tgt, 0, sizeof(struct nfc_target));
9059815c7cfSMichael Thalmeier
9069815c7cfSMichael Thalmeier switch (dev->poll_mod_curr) {
9079815c7cfSMichael Thalmeier case PN533_POLL_MOD_106KBPS_A:
9089815c7cfSMichael Thalmeier rc = pn533_target_found_type_a(&nfc_tgt, tgdata, tgdata_len);
9099815c7cfSMichael Thalmeier break;
9109815c7cfSMichael Thalmeier case PN533_POLL_MOD_212KBPS_FELICA:
9119815c7cfSMichael Thalmeier case PN533_POLL_MOD_424KBPS_FELICA:
9129815c7cfSMichael Thalmeier rc = pn533_target_found_felica(&nfc_tgt, tgdata, tgdata_len);
9139815c7cfSMichael Thalmeier break;
9149815c7cfSMichael Thalmeier case PN533_POLL_MOD_106KBPS_JEWEL:
9159815c7cfSMichael Thalmeier rc = pn533_target_found_jewel(&nfc_tgt, tgdata, tgdata_len);
9169815c7cfSMichael Thalmeier break;
9179815c7cfSMichael Thalmeier case PN533_POLL_MOD_847KBPS_B:
9189815c7cfSMichael Thalmeier rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len);
9199815c7cfSMichael Thalmeier break;
9209815c7cfSMichael Thalmeier default:
9219815c7cfSMichael Thalmeier nfc_err(dev->dev,
9229815c7cfSMichael Thalmeier "Unknown current poll modulation\n");
9239815c7cfSMichael Thalmeier return -EPROTO;
9249815c7cfSMichael Thalmeier }
9259815c7cfSMichael Thalmeier
9269815c7cfSMichael Thalmeier if (rc)
9279815c7cfSMichael Thalmeier return rc;
9289815c7cfSMichael Thalmeier
9299815c7cfSMichael Thalmeier if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) {
9309815c7cfSMichael Thalmeier dev_dbg(dev->dev,
9319815c7cfSMichael Thalmeier "The Tg found doesn't have the desired protocol\n");
9329815c7cfSMichael Thalmeier return -EAGAIN;
9339815c7cfSMichael Thalmeier }
9349815c7cfSMichael Thalmeier
9359815c7cfSMichael Thalmeier dev_dbg(dev->dev,
9369815c7cfSMichael Thalmeier "Target found - supported protocols: 0x%x\n",
9379815c7cfSMichael Thalmeier nfc_tgt.supported_protocols);
9389815c7cfSMichael Thalmeier
9399815c7cfSMichael Thalmeier dev->tgt_available_prots = nfc_tgt.supported_protocols;
9409815c7cfSMichael Thalmeier
941c952f915SMichael Thalmeier pn533_poll_reset_mod_list(dev);
9429815c7cfSMichael Thalmeier nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);
9439815c7cfSMichael Thalmeier
9449815c7cfSMichael Thalmeier return 0;
9459815c7cfSMichael Thalmeier }
9469815c7cfSMichael Thalmeier
pn533_poll_next_mod(struct pn533 * dev)9479815c7cfSMichael Thalmeier static inline void pn533_poll_next_mod(struct pn533 *dev)
9489815c7cfSMichael Thalmeier {
9499815c7cfSMichael Thalmeier dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
9509815c7cfSMichael Thalmeier }
9519815c7cfSMichael Thalmeier
pn533_poll_reset_mod_list(struct pn533 * dev)9529815c7cfSMichael Thalmeier static void pn533_poll_reset_mod_list(struct pn533 *dev)
9539815c7cfSMichael Thalmeier {
9549815c7cfSMichael Thalmeier dev->poll_mod_count = 0;
9559815c7cfSMichael Thalmeier }
9569815c7cfSMichael Thalmeier
pn533_poll_add_mod(struct pn533 * dev,u8 mod_index)9579815c7cfSMichael Thalmeier static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index)
9589815c7cfSMichael Thalmeier {
9599815c7cfSMichael Thalmeier dev->poll_mod_active[dev->poll_mod_count] =
9609815c7cfSMichael Thalmeier (struct pn533_poll_modulations *)&poll_mod[mod_index];
9619815c7cfSMichael Thalmeier dev->poll_mod_count++;
9629815c7cfSMichael Thalmeier }
9639815c7cfSMichael Thalmeier
pn533_poll_create_mod_list(struct pn533 * dev,u32 im_protocols,u32 tm_protocols)9649815c7cfSMichael Thalmeier static void pn533_poll_create_mod_list(struct pn533 *dev,
9659815c7cfSMichael Thalmeier u32 im_protocols, u32 tm_protocols)
9669815c7cfSMichael Thalmeier {
9679815c7cfSMichael Thalmeier pn533_poll_reset_mod_list(dev);
9689815c7cfSMichael Thalmeier
9699815c7cfSMichael Thalmeier if ((im_protocols & NFC_PROTO_MIFARE_MASK) ||
9709815c7cfSMichael Thalmeier (im_protocols & NFC_PROTO_ISO14443_MASK) ||
9719815c7cfSMichael Thalmeier (im_protocols & NFC_PROTO_NFC_DEP_MASK))
9729815c7cfSMichael Thalmeier pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A);
9739815c7cfSMichael Thalmeier
9749815c7cfSMichael Thalmeier if (im_protocols & NFC_PROTO_FELICA_MASK ||
9759815c7cfSMichael Thalmeier im_protocols & NFC_PROTO_NFC_DEP_MASK) {
9769815c7cfSMichael Thalmeier pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA);
9779815c7cfSMichael Thalmeier pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA);
9789815c7cfSMichael Thalmeier }
9799815c7cfSMichael Thalmeier
9809815c7cfSMichael Thalmeier if (im_protocols & NFC_PROTO_JEWEL_MASK)
9819815c7cfSMichael Thalmeier pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);
9829815c7cfSMichael Thalmeier
9839815c7cfSMichael Thalmeier if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
9849815c7cfSMichael Thalmeier pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
9859815c7cfSMichael Thalmeier
9869815c7cfSMichael Thalmeier if (tm_protocols)
9879815c7cfSMichael Thalmeier pn533_poll_add_mod(dev, PN533_LISTEN_MOD);
9889815c7cfSMichael Thalmeier }
9899815c7cfSMichael Thalmeier
pn533_start_poll_complete(struct pn533 * dev,struct sk_buff * resp)9909815c7cfSMichael Thalmeier static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp)
9919815c7cfSMichael Thalmeier {
9929815c7cfSMichael Thalmeier u8 nbtg, tg, *tgdata;
9939815c7cfSMichael Thalmeier int rc, tgdata_len;
9949815c7cfSMichael Thalmeier
9959815c7cfSMichael Thalmeier /* Toggle the DEP polling */
9969815c7cfSMichael Thalmeier if (dev->poll_protocols & NFC_PROTO_NFC_DEP_MASK)
9979815c7cfSMichael Thalmeier dev->poll_dep = 1;
9989815c7cfSMichael Thalmeier
9999815c7cfSMichael Thalmeier nbtg = resp->data[0];
10009815c7cfSMichael Thalmeier tg = resp->data[1];
10019815c7cfSMichael Thalmeier tgdata = &resp->data[2];
10029815c7cfSMichael Thalmeier tgdata_len = resp->len - 2; /* nbtg + tg */
10039815c7cfSMichael Thalmeier
10049815c7cfSMichael Thalmeier if (nbtg) {
10059815c7cfSMichael Thalmeier rc = pn533_target_found(dev, tg, tgdata, tgdata_len);
10069815c7cfSMichael Thalmeier
10079815c7cfSMichael Thalmeier /* We must stop the poll after a valid target found */
1008c952f915SMichael Thalmeier if (rc == 0)
10099815c7cfSMichael Thalmeier return 0;
10109815c7cfSMichael Thalmeier }
10119815c7cfSMichael Thalmeier
10129815c7cfSMichael Thalmeier return -EAGAIN;
10139815c7cfSMichael Thalmeier }
10149815c7cfSMichael Thalmeier
pn533_alloc_poll_tg_frame(struct pn533 * dev)10159815c7cfSMichael Thalmeier static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev)
10169815c7cfSMichael Thalmeier {
10179815c7cfSMichael Thalmeier struct sk_buff *skb;
1018b952f4dfSyuan linyu u8 *felica, *nfcid3;
10199815c7cfSMichael Thalmeier
10209815c7cfSMichael Thalmeier u8 *gbytes = dev->gb;
10219815c7cfSMichael Thalmeier size_t gbytes_len = dev->gb_len;
10229815c7cfSMichael Thalmeier
10239815c7cfSMichael Thalmeier u8 felica_params[18] = {0x1, 0xfe, /* DEP */
10249815c7cfSMichael Thalmeier 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */
10259815c7cfSMichael Thalmeier 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
10269815c7cfSMichael Thalmeier 0xff, 0xff}; /* System code */
10279815c7cfSMichael Thalmeier
10289815c7cfSMichael Thalmeier u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */
10299815c7cfSMichael Thalmeier 0x0, 0x0, 0x0,
10309815c7cfSMichael Thalmeier 0x40}; /* SEL_RES for DEP */
10319815c7cfSMichael Thalmeier
10329815c7cfSMichael Thalmeier unsigned int skb_len = 36 + /*
10339815c7cfSMichael Thalmeier * mode (1), mifare (6),
10349815c7cfSMichael Thalmeier * felica (18), nfcid3 (10), gb_len (1)
10359815c7cfSMichael Thalmeier */
10369815c7cfSMichael Thalmeier gbytes_len +
10379815c7cfSMichael Thalmeier 1; /* len Tk*/
10389815c7cfSMichael Thalmeier
10399815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, skb_len);
10409815c7cfSMichael Thalmeier if (!skb)
10419815c7cfSMichael Thalmeier return NULL;
10429815c7cfSMichael Thalmeier
10439815c7cfSMichael Thalmeier /* DEP support only */
1044634fef61SJohannes Berg skb_put_u8(skb, PN533_INIT_TARGET_DEP);
10459815c7cfSMichael Thalmeier
10469815c7cfSMichael Thalmeier /* MIFARE params */
104759ae1d12SJohannes Berg skb_put_data(skb, mifare_params, 6);
10489815c7cfSMichael Thalmeier
10499815c7cfSMichael Thalmeier /* Felica params */
105059ae1d12SJohannes Berg felica = skb_put_data(skb, felica_params, 18);
10519815c7cfSMichael Thalmeier get_random_bytes(felica + 2, 6);
10529815c7cfSMichael Thalmeier
10539815c7cfSMichael Thalmeier /* NFCID3 */
1054aa9f979cSJohannes Berg nfcid3 = skb_put_zero(skb, 10);
10559815c7cfSMichael Thalmeier memcpy(nfcid3, felica, 8);
10569815c7cfSMichael Thalmeier
10579815c7cfSMichael Thalmeier /* General bytes */
1058634fef61SJohannes Berg skb_put_u8(skb, gbytes_len);
10599815c7cfSMichael Thalmeier
1060b952f4dfSyuan linyu skb_put_data(skb, gbytes, gbytes_len);
10619815c7cfSMichael Thalmeier
10629815c7cfSMichael Thalmeier /* Len Tk */
1063634fef61SJohannes Berg skb_put_u8(skb, 0);
10649815c7cfSMichael Thalmeier
10659815c7cfSMichael Thalmeier return skb;
10669815c7cfSMichael Thalmeier }
10679815c7cfSMichael Thalmeier
10689815c7cfSMichael Thalmeier static void pn533_wq_tm_mi_recv(struct work_struct *work);
10699815c7cfSMichael Thalmeier static struct sk_buff *pn533_build_response(struct pn533 *dev);
10709815c7cfSMichael Thalmeier
pn533_tm_get_data_complete(struct pn533 * dev,void * arg,struct sk_buff * resp)10719815c7cfSMichael Thalmeier static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg,
10729815c7cfSMichael Thalmeier struct sk_buff *resp)
10739815c7cfSMichael Thalmeier {
10749815c7cfSMichael Thalmeier struct sk_buff *skb;
10759815c7cfSMichael Thalmeier u8 status, ret, mi;
10769815c7cfSMichael Thalmeier int rc;
10779815c7cfSMichael Thalmeier
10789815c7cfSMichael Thalmeier if (IS_ERR(resp)) {
10799815c7cfSMichael Thalmeier skb_queue_purge(&dev->resp_q);
10809815c7cfSMichael Thalmeier return PTR_ERR(resp);
10819815c7cfSMichael Thalmeier }
10829815c7cfSMichael Thalmeier
10839815c7cfSMichael Thalmeier status = resp->data[0];
10849815c7cfSMichael Thalmeier
10859815c7cfSMichael Thalmeier ret = status & PN533_CMD_RET_MASK;
10869815c7cfSMichael Thalmeier mi = status & PN533_CMD_MI_MASK;
10879815c7cfSMichael Thalmeier
10889815c7cfSMichael Thalmeier skb_pull(resp, sizeof(status));
10899815c7cfSMichael Thalmeier
10909815c7cfSMichael Thalmeier if (ret != PN533_CMD_RET_SUCCESS) {
10919815c7cfSMichael Thalmeier rc = -EIO;
10929815c7cfSMichael Thalmeier goto error;
10939815c7cfSMichael Thalmeier }
10949815c7cfSMichael Thalmeier
10959815c7cfSMichael Thalmeier skb_queue_tail(&dev->resp_q, resp);
10969815c7cfSMichael Thalmeier
10979815c7cfSMichael Thalmeier if (mi) {
10989815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->mi_tm_rx_work);
10999815c7cfSMichael Thalmeier return -EINPROGRESS;
11009815c7cfSMichael Thalmeier }
11019815c7cfSMichael Thalmeier
11029815c7cfSMichael Thalmeier skb = pn533_build_response(dev);
11039815c7cfSMichael Thalmeier if (!skb) {
11049815c7cfSMichael Thalmeier rc = -EIO;
11059815c7cfSMichael Thalmeier goto error;
11069815c7cfSMichael Thalmeier }
11079815c7cfSMichael Thalmeier
11089815c7cfSMichael Thalmeier return nfc_tm_data_received(dev->nfc_dev, skb);
11099815c7cfSMichael Thalmeier
11109815c7cfSMichael Thalmeier error:
11119815c7cfSMichael Thalmeier nfc_tm_deactivated(dev->nfc_dev);
11129815c7cfSMichael Thalmeier dev->tgt_mode = 0;
11139815c7cfSMichael Thalmeier skb_queue_purge(&dev->resp_q);
11149815c7cfSMichael Thalmeier dev_kfree_skb(resp);
11159815c7cfSMichael Thalmeier
11169815c7cfSMichael Thalmeier return rc;
11179815c7cfSMichael Thalmeier }
11189815c7cfSMichael Thalmeier
pn533_wq_tm_mi_recv(struct work_struct * work)11199815c7cfSMichael Thalmeier static void pn533_wq_tm_mi_recv(struct work_struct *work)
11209815c7cfSMichael Thalmeier {
11219815c7cfSMichael Thalmeier struct pn533 *dev = container_of(work, struct pn533, mi_tm_rx_work);
11229815c7cfSMichael Thalmeier struct sk_buff *skb;
11239815c7cfSMichael Thalmeier int rc;
11249815c7cfSMichael Thalmeier
11259815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, 0);
11269815c7cfSMichael Thalmeier if (!skb)
11279815c7cfSMichael Thalmeier return;
11289815c7cfSMichael Thalmeier
11299815c7cfSMichael Thalmeier rc = pn533_send_cmd_direct_async(dev,
11309815c7cfSMichael Thalmeier PN533_CMD_TG_GET_DATA,
11319815c7cfSMichael Thalmeier skb,
11329815c7cfSMichael Thalmeier pn533_tm_get_data_complete,
11339815c7cfSMichael Thalmeier NULL);
11349815c7cfSMichael Thalmeier
11359815c7cfSMichael Thalmeier if (rc < 0)
11369815c7cfSMichael Thalmeier dev_kfree_skb(skb);
11379815c7cfSMichael Thalmeier }
11389815c7cfSMichael Thalmeier
11399815c7cfSMichael Thalmeier static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
11409815c7cfSMichael Thalmeier struct sk_buff *resp);
pn533_wq_tm_mi_send(struct work_struct * work)11419815c7cfSMichael Thalmeier static void pn533_wq_tm_mi_send(struct work_struct *work)
11429815c7cfSMichael Thalmeier {
11439815c7cfSMichael Thalmeier struct pn533 *dev = container_of(work, struct pn533, mi_tm_tx_work);
11449815c7cfSMichael Thalmeier struct sk_buff *skb;
11459815c7cfSMichael Thalmeier int rc;
11469815c7cfSMichael Thalmeier
11479815c7cfSMichael Thalmeier /* Grab the first skb in the queue */
11489815c7cfSMichael Thalmeier skb = skb_dequeue(&dev->fragment_skb);
11499815c7cfSMichael Thalmeier if (skb == NULL) { /* No more data */
11509815c7cfSMichael Thalmeier /* Reset the queue for future use */
11519815c7cfSMichael Thalmeier skb_queue_head_init(&dev->fragment_skb);
11529815c7cfSMichael Thalmeier goto error;
11539815c7cfSMichael Thalmeier }
11549815c7cfSMichael Thalmeier
11559815c7cfSMichael Thalmeier /* last entry - remove MI bit */
11569815c7cfSMichael Thalmeier if (skb_queue_len(&dev->fragment_skb) == 0) {
11579815c7cfSMichael Thalmeier rc = pn533_send_cmd_direct_async(dev, PN533_CMD_TG_SET_DATA,
11589815c7cfSMichael Thalmeier skb, pn533_tm_send_complete, NULL);
11599815c7cfSMichael Thalmeier } else
11609815c7cfSMichael Thalmeier rc = pn533_send_cmd_direct_async(dev,
11619815c7cfSMichael Thalmeier PN533_CMD_TG_SET_META_DATA,
11629815c7cfSMichael Thalmeier skb, pn533_tm_send_complete, NULL);
11639815c7cfSMichael Thalmeier
11649815c7cfSMichael Thalmeier if (rc == 0) /* success */
11659815c7cfSMichael Thalmeier return;
11669815c7cfSMichael Thalmeier
11679815c7cfSMichael Thalmeier dev_err(dev->dev,
11689815c7cfSMichael Thalmeier "Error %d when trying to perform set meta data_exchange", rc);
11699815c7cfSMichael Thalmeier
11709815c7cfSMichael Thalmeier dev_kfree_skb(skb);
11719815c7cfSMichael Thalmeier
11729815c7cfSMichael Thalmeier error:
11739815c7cfSMichael Thalmeier dev->phy_ops->send_ack(dev, GFP_KERNEL);
11749815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->cmd_work);
11759815c7cfSMichael Thalmeier }
11769815c7cfSMichael Thalmeier
pn533_wq_tg_get_data(struct work_struct * work)11779815c7cfSMichael Thalmeier static void pn533_wq_tg_get_data(struct work_struct *work)
11789815c7cfSMichael Thalmeier {
11799815c7cfSMichael Thalmeier struct pn533 *dev = container_of(work, struct pn533, tg_work);
11809815c7cfSMichael Thalmeier struct sk_buff *skb;
11819815c7cfSMichael Thalmeier int rc;
11829815c7cfSMichael Thalmeier
11839815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, 0);
11849815c7cfSMichael Thalmeier if (!skb)
11859815c7cfSMichael Thalmeier return;
11869815c7cfSMichael Thalmeier
11879815c7cfSMichael Thalmeier rc = pn533_send_data_async(dev, PN533_CMD_TG_GET_DATA, skb,
11889815c7cfSMichael Thalmeier pn533_tm_get_data_complete, NULL);
11899815c7cfSMichael Thalmeier
11909815c7cfSMichael Thalmeier if (rc < 0)
11919815c7cfSMichael Thalmeier dev_kfree_skb(skb);
11929815c7cfSMichael Thalmeier }
11939815c7cfSMichael Thalmeier
11949815c7cfSMichael Thalmeier #define ATR_REQ_GB_OFFSET 17
pn533_init_target_complete(struct pn533 * dev,struct sk_buff * resp)11959815c7cfSMichael Thalmeier static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp)
11969815c7cfSMichael Thalmeier {
11979815c7cfSMichael Thalmeier u8 mode, *cmd, comm_mode = NFC_COMM_PASSIVE, *gb;
11989815c7cfSMichael Thalmeier size_t gb_len;
11999815c7cfSMichael Thalmeier int rc;
12009815c7cfSMichael Thalmeier
12019815c7cfSMichael Thalmeier if (resp->len < ATR_REQ_GB_OFFSET + 1)
12029815c7cfSMichael Thalmeier return -EINVAL;
12039815c7cfSMichael Thalmeier
12049815c7cfSMichael Thalmeier mode = resp->data[0];
12059815c7cfSMichael Thalmeier cmd = &resp->data[1];
12069815c7cfSMichael Thalmeier
12079815c7cfSMichael Thalmeier dev_dbg(dev->dev, "Target mode 0x%x len %d\n",
12089815c7cfSMichael Thalmeier mode, resp->len);
12099815c7cfSMichael Thalmeier
12109815c7cfSMichael Thalmeier if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) ==
12119815c7cfSMichael Thalmeier PN533_INIT_TARGET_RESP_ACTIVE)
12129815c7cfSMichael Thalmeier comm_mode = NFC_COMM_ACTIVE;
12139815c7cfSMichael Thalmeier
12149815c7cfSMichael Thalmeier if ((mode & PN533_INIT_TARGET_RESP_DEP) == 0) /* Only DEP supported */
12159815c7cfSMichael Thalmeier return -EOPNOTSUPP;
12169815c7cfSMichael Thalmeier
12179815c7cfSMichael Thalmeier gb = cmd + ATR_REQ_GB_OFFSET;
12189815c7cfSMichael Thalmeier gb_len = resp->len - (ATR_REQ_GB_OFFSET + 1);
12199815c7cfSMichael Thalmeier
12209815c7cfSMichael Thalmeier rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
12219815c7cfSMichael Thalmeier comm_mode, gb, gb_len);
12229815c7cfSMichael Thalmeier if (rc < 0) {
12239815c7cfSMichael Thalmeier nfc_err(dev->dev,
12249815c7cfSMichael Thalmeier "Error when signaling target activation\n");
12259815c7cfSMichael Thalmeier return rc;
12269815c7cfSMichael Thalmeier }
12279815c7cfSMichael Thalmeier
12289815c7cfSMichael Thalmeier dev->tgt_mode = 1;
12299815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->tg_work);
12309815c7cfSMichael Thalmeier
12319815c7cfSMichael Thalmeier return 0;
12329815c7cfSMichael Thalmeier }
12339815c7cfSMichael Thalmeier
pn533_listen_mode_timer(struct timer_list * t)1234e99e88a9SKees Cook static void pn533_listen_mode_timer(struct timer_list *t)
12359815c7cfSMichael Thalmeier {
1236e99e88a9SKees Cook struct pn533 *dev = from_timer(dev, t, listen_timer);
12379815c7cfSMichael Thalmeier
12389815c7cfSMichael Thalmeier dev->cancel_listen = 1;
12399815c7cfSMichael Thalmeier
12409815c7cfSMichael Thalmeier pn533_poll_next_mod(dev);
12419815c7cfSMichael Thalmeier
12429815c7cfSMichael Thalmeier queue_delayed_work(dev->wq, &dev->poll_work,
12439815c7cfSMichael Thalmeier msecs_to_jiffies(PN533_POLL_INTERVAL));
12449815c7cfSMichael Thalmeier }
12459815c7cfSMichael Thalmeier
pn533_rf_complete(struct pn533 * dev,void * arg,struct sk_buff * resp)12469815c7cfSMichael Thalmeier static int pn533_rf_complete(struct pn533 *dev, void *arg,
12479815c7cfSMichael Thalmeier struct sk_buff *resp)
12489815c7cfSMichael Thalmeier {
12499815c7cfSMichael Thalmeier int rc = 0;
12509815c7cfSMichael Thalmeier
12519815c7cfSMichael Thalmeier if (IS_ERR(resp)) {
12529815c7cfSMichael Thalmeier rc = PTR_ERR(resp);
12539815c7cfSMichael Thalmeier
12549815c7cfSMichael Thalmeier nfc_err(dev->dev, "RF setting error %d\n", rc);
12559815c7cfSMichael Thalmeier
12569815c7cfSMichael Thalmeier return rc;
12579815c7cfSMichael Thalmeier }
12589815c7cfSMichael Thalmeier
12599815c7cfSMichael Thalmeier queue_delayed_work(dev->wq, &dev->poll_work,
12609815c7cfSMichael Thalmeier msecs_to_jiffies(PN533_POLL_INTERVAL));
12619815c7cfSMichael Thalmeier
12629815c7cfSMichael Thalmeier dev_kfree_skb(resp);
12639815c7cfSMichael Thalmeier return rc;
12649815c7cfSMichael Thalmeier }
12659815c7cfSMichael Thalmeier
pn533_wq_rf(struct work_struct * work)12669815c7cfSMichael Thalmeier static void pn533_wq_rf(struct work_struct *work)
12679815c7cfSMichael Thalmeier {
12689815c7cfSMichael Thalmeier struct pn533 *dev = container_of(work, struct pn533, rf_work);
12699815c7cfSMichael Thalmeier struct sk_buff *skb;
12709815c7cfSMichael Thalmeier int rc;
12719815c7cfSMichael Thalmeier
12729815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, 2);
12739815c7cfSMichael Thalmeier if (!skb)
12749815c7cfSMichael Thalmeier return;
12759815c7cfSMichael Thalmeier
1276634fef61SJohannes Berg skb_put_u8(skb, PN533_CFGITEM_RF_FIELD);
1277634fef61SJohannes Berg skb_put_u8(skb, PN533_CFGITEM_RF_FIELD_AUTO_RFCA);
12789815c7cfSMichael Thalmeier
12799815c7cfSMichael Thalmeier rc = pn533_send_cmd_async(dev, PN533_CMD_RF_CONFIGURATION, skb,
12809815c7cfSMichael Thalmeier pn533_rf_complete, NULL);
12819815c7cfSMichael Thalmeier if (rc < 0) {
12829815c7cfSMichael Thalmeier dev_kfree_skb(skb);
12839815c7cfSMichael Thalmeier nfc_err(dev->dev, "RF setting error %d\n", rc);
12849815c7cfSMichael Thalmeier }
12859815c7cfSMichael Thalmeier }
12869815c7cfSMichael Thalmeier
pn533_poll_dep_complete(struct pn533 * dev,void * arg,struct sk_buff * resp)12879815c7cfSMichael Thalmeier static int pn533_poll_dep_complete(struct pn533 *dev, void *arg,
12889815c7cfSMichael Thalmeier struct sk_buff *resp)
12899815c7cfSMichael Thalmeier {
12909815c7cfSMichael Thalmeier struct pn533_cmd_jump_dep_response *rsp;
12919815c7cfSMichael Thalmeier struct nfc_target nfc_target;
12929815c7cfSMichael Thalmeier u8 target_gt_len;
12939815c7cfSMichael Thalmeier int rc;
12949815c7cfSMichael Thalmeier
12959815c7cfSMichael Thalmeier if (IS_ERR(resp))
12969815c7cfSMichael Thalmeier return PTR_ERR(resp);
12979815c7cfSMichael Thalmeier
12989f281577SMinsuk Kang memset(&nfc_target, 0, sizeof(struct nfc_target));
12999f281577SMinsuk Kang
13009815c7cfSMichael Thalmeier rsp = (struct pn533_cmd_jump_dep_response *)resp->data;
13019815c7cfSMichael Thalmeier
13029815c7cfSMichael Thalmeier rc = rsp->status & PN533_CMD_RET_MASK;
13039815c7cfSMichael Thalmeier if (rc != PN533_CMD_RET_SUCCESS) {
13049815c7cfSMichael Thalmeier /* Not target found, turn radio off */
13059815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->rf_work);
13069815c7cfSMichael Thalmeier
13079815c7cfSMichael Thalmeier dev_kfree_skb(resp);
13089815c7cfSMichael Thalmeier return 0;
13099815c7cfSMichael Thalmeier }
13109815c7cfSMichael Thalmeier
13119815c7cfSMichael Thalmeier dev_dbg(dev->dev, "Creating new target");
13129815c7cfSMichael Thalmeier
13139815c7cfSMichael Thalmeier nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
13149815c7cfSMichael Thalmeier nfc_target.nfcid1_len = 10;
13159815c7cfSMichael Thalmeier memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len);
13169815c7cfSMichael Thalmeier rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1);
13179815c7cfSMichael Thalmeier if (rc)
13189815c7cfSMichael Thalmeier goto error;
13199815c7cfSMichael Thalmeier
13209815c7cfSMichael Thalmeier dev->tgt_available_prots = 0;
13219815c7cfSMichael Thalmeier dev->tgt_active_prot = NFC_PROTO_NFC_DEP;
13229815c7cfSMichael Thalmeier
13239815c7cfSMichael Thalmeier /* ATR_RES general bytes are located at offset 17 */
13249815c7cfSMichael Thalmeier target_gt_len = resp->len - 17;
13259815c7cfSMichael Thalmeier rc = nfc_set_remote_general_bytes(dev->nfc_dev,
13269815c7cfSMichael Thalmeier rsp->gt, target_gt_len);
13279815c7cfSMichael Thalmeier if (!rc) {
13289815c7cfSMichael Thalmeier rc = nfc_dep_link_is_up(dev->nfc_dev,
13299815c7cfSMichael Thalmeier dev->nfc_dev->targets[0].idx,
13309815c7cfSMichael Thalmeier 0, NFC_RF_INITIATOR);
13319815c7cfSMichael Thalmeier
13329815c7cfSMichael Thalmeier if (!rc)
13339815c7cfSMichael Thalmeier pn533_poll_reset_mod_list(dev);
13349815c7cfSMichael Thalmeier }
13359815c7cfSMichael Thalmeier error:
13369815c7cfSMichael Thalmeier dev_kfree_skb(resp);
13379815c7cfSMichael Thalmeier return rc;
13389815c7cfSMichael Thalmeier }
13399815c7cfSMichael Thalmeier
13409815c7cfSMichael Thalmeier #define PASSIVE_DATA_LEN 5
pn533_poll_dep(struct nfc_dev * nfc_dev)13419815c7cfSMichael Thalmeier static int pn533_poll_dep(struct nfc_dev *nfc_dev)
13429815c7cfSMichael Thalmeier {
13439815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
13449815c7cfSMichael Thalmeier struct sk_buff *skb;
13459815c7cfSMichael Thalmeier int rc, skb_len;
13469815c7cfSMichael Thalmeier u8 *next, nfcid3[NFC_NFCID3_MAXSIZE];
13479815c7cfSMichael Thalmeier u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
13489815c7cfSMichael Thalmeier
13499815c7cfSMichael Thalmeier if (!dev->gb) {
13509815c7cfSMichael Thalmeier dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len);
13519815c7cfSMichael Thalmeier
13529815c7cfSMichael Thalmeier if (!dev->gb || !dev->gb_len) {
13539815c7cfSMichael Thalmeier dev->poll_dep = 0;
13549815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->rf_work);
13559815c7cfSMichael Thalmeier }
13569815c7cfSMichael Thalmeier }
13579815c7cfSMichael Thalmeier
13589815c7cfSMichael Thalmeier skb_len = 3 + dev->gb_len; /* ActPass + BR + Next */
13599815c7cfSMichael Thalmeier skb_len += PASSIVE_DATA_LEN;
13609815c7cfSMichael Thalmeier
13619815c7cfSMichael Thalmeier /* NFCID3 */
13629815c7cfSMichael Thalmeier skb_len += NFC_NFCID3_MAXSIZE;
13639815c7cfSMichael Thalmeier nfcid3[0] = 0x1;
13649815c7cfSMichael Thalmeier nfcid3[1] = 0xfe;
13659815c7cfSMichael Thalmeier get_random_bytes(nfcid3 + 2, 6);
13669815c7cfSMichael Thalmeier
13679815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, skb_len);
13689815c7cfSMichael Thalmeier if (!skb)
13699815c7cfSMichael Thalmeier return -ENOMEM;
13709815c7cfSMichael Thalmeier
1371634fef61SJohannes Berg skb_put_u8(skb, 0x01); /* Active */
1372634fef61SJohannes Berg skb_put_u8(skb, 0x02); /* 424 kbps */
13739815c7cfSMichael Thalmeier
13749815c7cfSMichael Thalmeier next = skb_put(skb, 1); /* Next */
13759815c7cfSMichael Thalmeier *next = 0;
13769815c7cfSMichael Thalmeier
13779815c7cfSMichael Thalmeier /* Copy passive data */
137859ae1d12SJohannes Berg skb_put_data(skb, passive_data, PASSIVE_DATA_LEN);
13799815c7cfSMichael Thalmeier *next |= 1;
13809815c7cfSMichael Thalmeier
13819815c7cfSMichael Thalmeier /* Copy NFCID3 (which is NFCID2 from SENSF_RES) */
138259ae1d12SJohannes Berg skb_put_data(skb, nfcid3, NFC_NFCID3_MAXSIZE);
13839815c7cfSMichael Thalmeier *next |= 2;
13849815c7cfSMichael Thalmeier
138559ae1d12SJohannes Berg skb_put_data(skb, dev->gb, dev->gb_len);
13869815c7cfSMichael Thalmeier *next |= 4; /* We have some Gi */
13879815c7cfSMichael Thalmeier
13889815c7cfSMichael Thalmeier rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb,
13899815c7cfSMichael Thalmeier pn533_poll_dep_complete, NULL);
13909815c7cfSMichael Thalmeier
13919815c7cfSMichael Thalmeier if (rc < 0)
13929815c7cfSMichael Thalmeier dev_kfree_skb(skb);
13939815c7cfSMichael Thalmeier
13949815c7cfSMichael Thalmeier return rc;
13959815c7cfSMichael Thalmeier }
13969815c7cfSMichael Thalmeier
pn533_autopoll_complete(struct pn533 * dev,void * arg,struct sk_buff * resp)1397c64b875fSLars Poeschel static int pn533_autopoll_complete(struct pn533 *dev, void *arg,
1398c64b875fSLars Poeschel struct sk_buff *resp)
1399c64b875fSLars Poeschel {
1400c64b875fSLars Poeschel struct pn532_autopoll_resp *apr;
1401c64b875fSLars Poeschel struct nfc_target nfc_tgt;
1402c64b875fSLars Poeschel u8 nbtg;
1403c64b875fSLars Poeschel int rc;
1404c64b875fSLars Poeschel
1405c64b875fSLars Poeschel if (IS_ERR(resp)) {
1406c64b875fSLars Poeschel rc = PTR_ERR(resp);
1407c64b875fSLars Poeschel
1408c64b875fSLars Poeschel nfc_err(dev->dev, "%s autopoll complete error %d\n",
1409c64b875fSLars Poeschel __func__, rc);
1410c64b875fSLars Poeschel
1411c64b875fSLars Poeschel if (rc == -ENOENT) {
1412c64b875fSLars Poeschel if (dev->poll_mod_count != 0)
1413c64b875fSLars Poeschel return rc;
1414c64b875fSLars Poeschel goto stop_poll;
1415c64b875fSLars Poeschel } else if (rc < 0) {
1416c64b875fSLars Poeschel nfc_err(dev->dev,
1417c64b875fSLars Poeschel "Error %d when running autopoll\n", rc);
1418c64b875fSLars Poeschel goto stop_poll;
1419c64b875fSLars Poeschel }
1420c64b875fSLars Poeschel }
1421c64b875fSLars Poeschel
1422c64b875fSLars Poeschel nbtg = resp->data[0];
1423c64b875fSLars Poeschel if ((nbtg > 2) || (nbtg <= 0))
1424c64b875fSLars Poeschel return -EAGAIN;
1425c64b875fSLars Poeschel
1426c64b875fSLars Poeschel apr = (struct pn532_autopoll_resp *)&resp->data[1];
1427c64b875fSLars Poeschel while (nbtg--) {
1428c64b875fSLars Poeschel memset(&nfc_tgt, 0, sizeof(struct nfc_target));
1429c64b875fSLars Poeschel switch (apr->type) {
1430c64b875fSLars Poeschel case PN532_AUTOPOLL_TYPE_ISOA:
1431c64b875fSLars Poeschel dev_dbg(dev->dev, "ISOA\n");
1432c64b875fSLars Poeschel rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
1433c64b875fSLars Poeschel apr->ln - 1);
1434c64b875fSLars Poeschel break;
1435c64b875fSLars Poeschel case PN532_AUTOPOLL_TYPE_FELICA212:
1436c64b875fSLars Poeschel case PN532_AUTOPOLL_TYPE_FELICA424:
1437c64b875fSLars Poeschel dev_dbg(dev->dev, "FELICA\n");
1438c64b875fSLars Poeschel rc = pn533_target_found_felica(&nfc_tgt, apr->tgdata,
1439c64b875fSLars Poeschel apr->ln - 1);
1440c64b875fSLars Poeschel break;
1441c64b875fSLars Poeschel case PN532_AUTOPOLL_TYPE_JEWEL:
1442c64b875fSLars Poeschel dev_dbg(dev->dev, "JEWEL\n");
1443c64b875fSLars Poeschel rc = pn533_target_found_jewel(&nfc_tgt, apr->tgdata,
1444c64b875fSLars Poeschel apr->ln - 1);
1445c64b875fSLars Poeschel break;
1446c64b875fSLars Poeschel case PN532_AUTOPOLL_TYPE_ISOB:
1447c64b875fSLars Poeschel dev_dbg(dev->dev, "ISOB\n");
1448c64b875fSLars Poeschel rc = pn533_target_found_type_b(&nfc_tgt, apr->tgdata,
1449c64b875fSLars Poeschel apr->ln - 1);
1450c64b875fSLars Poeschel break;
1451c64b875fSLars Poeschel case PN532_AUTOPOLL_TYPE_MIFARE:
1452c64b875fSLars Poeschel dev_dbg(dev->dev, "Mifare\n");
1453c64b875fSLars Poeschel rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
1454c64b875fSLars Poeschel apr->ln - 1);
1455c64b875fSLars Poeschel break;
1456c64b875fSLars Poeschel default:
1457c64b875fSLars Poeschel nfc_err(dev->dev,
1458c64b875fSLars Poeschel "Unknown current poll modulation\n");
1459c64b875fSLars Poeschel rc = -EPROTO;
1460c64b875fSLars Poeschel }
1461c64b875fSLars Poeschel
1462c64b875fSLars Poeschel if (rc)
1463c64b875fSLars Poeschel goto done;
1464c64b875fSLars Poeschel
1465c64b875fSLars Poeschel if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) {
1466c64b875fSLars Poeschel nfc_err(dev->dev,
1467c64b875fSLars Poeschel "The Tg found doesn't have the desired protocol\n");
1468c64b875fSLars Poeschel rc = -EAGAIN;
1469c64b875fSLars Poeschel goto done;
1470c64b875fSLars Poeschel }
1471c64b875fSLars Poeschel
1472c64b875fSLars Poeschel dev->tgt_available_prots = nfc_tgt.supported_protocols;
1473c64b875fSLars Poeschel apr = (struct pn532_autopoll_resp *)
1474c64b875fSLars Poeschel (apr->tgdata + (apr->ln - 1));
1475c64b875fSLars Poeschel }
1476c64b875fSLars Poeschel
1477c64b875fSLars Poeschel pn533_poll_reset_mod_list(dev);
1478c64b875fSLars Poeschel nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);
1479c64b875fSLars Poeschel
1480c64b875fSLars Poeschel done:
1481c64b875fSLars Poeschel dev_kfree_skb(resp);
1482c64b875fSLars Poeschel return rc;
1483c64b875fSLars Poeschel
1484c64b875fSLars Poeschel stop_poll:
1485c64b875fSLars Poeschel nfc_err(dev->dev, "autopoll operation has been stopped\n");
1486c64b875fSLars Poeschel
1487c64b875fSLars Poeschel pn533_poll_reset_mod_list(dev);
1488c64b875fSLars Poeschel dev->poll_protocols = 0;
1489c64b875fSLars Poeschel return rc;
1490c64b875fSLars Poeschel }
1491c64b875fSLars Poeschel
pn533_poll_complete(struct pn533 * dev,void * arg,struct sk_buff * resp)14929815c7cfSMichael Thalmeier static int pn533_poll_complete(struct pn533 *dev, void *arg,
14939815c7cfSMichael Thalmeier struct sk_buff *resp)
14949815c7cfSMichael Thalmeier {
14959815c7cfSMichael Thalmeier struct pn533_poll_modulations *cur_mod;
14969815c7cfSMichael Thalmeier int rc;
14979815c7cfSMichael Thalmeier
14989815c7cfSMichael Thalmeier if (IS_ERR(resp)) {
14999815c7cfSMichael Thalmeier rc = PTR_ERR(resp);
15009815c7cfSMichael Thalmeier
15019815c7cfSMichael Thalmeier nfc_err(dev->dev, "%s Poll complete error %d\n",
15029815c7cfSMichael Thalmeier __func__, rc);
15039815c7cfSMichael Thalmeier
15049815c7cfSMichael Thalmeier if (rc == -ENOENT) {
15059815c7cfSMichael Thalmeier if (dev->poll_mod_count != 0)
15069815c7cfSMichael Thalmeier return rc;
15079815c7cfSMichael Thalmeier goto stop_poll;
15089815c7cfSMichael Thalmeier } else if (rc < 0) {
15099815c7cfSMichael Thalmeier nfc_err(dev->dev,
15109815c7cfSMichael Thalmeier "Error %d when running poll\n", rc);
15119815c7cfSMichael Thalmeier goto stop_poll;
15129815c7cfSMichael Thalmeier }
15139815c7cfSMichael Thalmeier }
15149815c7cfSMichael Thalmeier
15159815c7cfSMichael Thalmeier cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
15169815c7cfSMichael Thalmeier
15179815c7cfSMichael Thalmeier if (cur_mod->len == 0) { /* Target mode */
15189815c7cfSMichael Thalmeier del_timer(&dev->listen_timer);
15199815c7cfSMichael Thalmeier rc = pn533_init_target_complete(dev, resp);
15209815c7cfSMichael Thalmeier goto done;
15219815c7cfSMichael Thalmeier }
15229815c7cfSMichael Thalmeier
15239815c7cfSMichael Thalmeier /* Initiator mode */
15249815c7cfSMichael Thalmeier rc = pn533_start_poll_complete(dev, resp);
15259815c7cfSMichael Thalmeier if (!rc)
15269815c7cfSMichael Thalmeier goto done;
15279815c7cfSMichael Thalmeier
15289815c7cfSMichael Thalmeier if (!dev->poll_mod_count) {
15299815c7cfSMichael Thalmeier dev_dbg(dev->dev, "Polling has been stopped\n");
15309815c7cfSMichael Thalmeier goto done;
15319815c7cfSMichael Thalmeier }
15329815c7cfSMichael Thalmeier
15339815c7cfSMichael Thalmeier pn533_poll_next_mod(dev);
15349815c7cfSMichael Thalmeier /* Not target found, turn radio off */
15359815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->rf_work);
15369815c7cfSMichael Thalmeier
15379815c7cfSMichael Thalmeier done:
15389815c7cfSMichael Thalmeier dev_kfree_skb(resp);
15399815c7cfSMichael Thalmeier return rc;
15409815c7cfSMichael Thalmeier
15419815c7cfSMichael Thalmeier stop_poll:
15429815c7cfSMichael Thalmeier nfc_err(dev->dev, "Polling operation has been stopped\n");
15439815c7cfSMichael Thalmeier
15449815c7cfSMichael Thalmeier pn533_poll_reset_mod_list(dev);
15459815c7cfSMichael Thalmeier dev->poll_protocols = 0;
15469815c7cfSMichael Thalmeier return rc;
15479815c7cfSMichael Thalmeier }
15489815c7cfSMichael Thalmeier
pn533_alloc_poll_in_frame(struct pn533 * dev,struct pn533_poll_modulations * mod)15499815c7cfSMichael Thalmeier static struct sk_buff *pn533_alloc_poll_in_frame(struct pn533 *dev,
15509815c7cfSMichael Thalmeier struct pn533_poll_modulations *mod)
15519815c7cfSMichael Thalmeier {
15529815c7cfSMichael Thalmeier struct sk_buff *skb;
15539815c7cfSMichael Thalmeier
15549815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, mod->len);
15559815c7cfSMichael Thalmeier if (!skb)
15569815c7cfSMichael Thalmeier return NULL;
15579815c7cfSMichael Thalmeier
155859ae1d12SJohannes Berg skb_put_data(skb, &mod->data, mod->len);
15599815c7cfSMichael Thalmeier
15609815c7cfSMichael Thalmeier return skb;
15619815c7cfSMichael Thalmeier }
15629815c7cfSMichael Thalmeier
pn533_send_poll_frame(struct pn533 * dev)15639815c7cfSMichael Thalmeier static int pn533_send_poll_frame(struct pn533 *dev)
15649815c7cfSMichael Thalmeier {
15659815c7cfSMichael Thalmeier struct pn533_poll_modulations *mod;
15669815c7cfSMichael Thalmeier struct sk_buff *skb;
15679815c7cfSMichael Thalmeier int rc;
15689815c7cfSMichael Thalmeier u8 cmd_code;
15699815c7cfSMichael Thalmeier
15709815c7cfSMichael Thalmeier mod = dev->poll_mod_active[dev->poll_mod_curr];
15719815c7cfSMichael Thalmeier
15729815c7cfSMichael Thalmeier dev_dbg(dev->dev, "%s mod len %d\n",
15739815c7cfSMichael Thalmeier __func__, mod->len);
15749815c7cfSMichael Thalmeier
15759815c7cfSMichael Thalmeier if ((dev->poll_protocols & NFC_PROTO_NFC_DEP_MASK) && dev->poll_dep) {
15769815c7cfSMichael Thalmeier dev->poll_dep = 0;
15779815c7cfSMichael Thalmeier return pn533_poll_dep(dev->nfc_dev);
15789815c7cfSMichael Thalmeier }
15799815c7cfSMichael Thalmeier
15809815c7cfSMichael Thalmeier if (mod->len == 0) { /* Listen mode */
15819815c7cfSMichael Thalmeier cmd_code = PN533_CMD_TG_INIT_AS_TARGET;
15829815c7cfSMichael Thalmeier skb = pn533_alloc_poll_tg_frame(dev);
15839815c7cfSMichael Thalmeier } else { /* Polling mode */
15849815c7cfSMichael Thalmeier cmd_code = PN533_CMD_IN_LIST_PASSIVE_TARGET;
15859815c7cfSMichael Thalmeier skb = pn533_alloc_poll_in_frame(dev, mod);
15869815c7cfSMichael Thalmeier }
15879815c7cfSMichael Thalmeier
15889815c7cfSMichael Thalmeier if (!skb) {
15899815c7cfSMichael Thalmeier nfc_err(dev->dev, "Failed to allocate skb\n");
15909815c7cfSMichael Thalmeier return -ENOMEM;
15919815c7cfSMichael Thalmeier }
15929815c7cfSMichael Thalmeier
15939815c7cfSMichael Thalmeier rc = pn533_send_cmd_async(dev, cmd_code, skb, pn533_poll_complete,
15949815c7cfSMichael Thalmeier NULL);
15959815c7cfSMichael Thalmeier if (rc < 0) {
15969815c7cfSMichael Thalmeier dev_kfree_skb(skb);
15979815c7cfSMichael Thalmeier nfc_err(dev->dev, "Polling loop error %d\n", rc);
15989815c7cfSMichael Thalmeier }
15999815c7cfSMichael Thalmeier
16009815c7cfSMichael Thalmeier return rc;
16019815c7cfSMichael Thalmeier }
16029815c7cfSMichael Thalmeier
pn533_wq_poll(struct work_struct * work)16039815c7cfSMichael Thalmeier static void pn533_wq_poll(struct work_struct *work)
16049815c7cfSMichael Thalmeier {
16059815c7cfSMichael Thalmeier struct pn533 *dev = container_of(work, struct pn533, poll_work.work);
16069815c7cfSMichael Thalmeier struct pn533_poll_modulations *cur_mod;
16079815c7cfSMichael Thalmeier int rc;
16089815c7cfSMichael Thalmeier
16099815c7cfSMichael Thalmeier cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
16109815c7cfSMichael Thalmeier
16119815c7cfSMichael Thalmeier dev_dbg(dev->dev,
16129815c7cfSMichael Thalmeier "%s cancel_listen %d modulation len %d\n",
16139815c7cfSMichael Thalmeier __func__, dev->cancel_listen, cur_mod->len);
16149815c7cfSMichael Thalmeier
16159815c7cfSMichael Thalmeier if (dev->cancel_listen == 1) {
16169815c7cfSMichael Thalmeier dev->cancel_listen = 0;
16179815c7cfSMichael Thalmeier dev->phy_ops->abort_cmd(dev, GFP_ATOMIC);
16189815c7cfSMichael Thalmeier }
16199815c7cfSMichael Thalmeier
16209815c7cfSMichael Thalmeier rc = pn533_send_poll_frame(dev);
16219815c7cfSMichael Thalmeier if (rc)
16229815c7cfSMichael Thalmeier return;
16239815c7cfSMichael Thalmeier
16249815c7cfSMichael Thalmeier if (cur_mod->len == 0 && dev->poll_mod_count > 1)
16259815c7cfSMichael Thalmeier mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ);
16269815c7cfSMichael Thalmeier }
16279815c7cfSMichael Thalmeier
pn533_start_poll(struct nfc_dev * nfc_dev,u32 im_protocols,u32 tm_protocols)16289815c7cfSMichael Thalmeier static int pn533_start_poll(struct nfc_dev *nfc_dev,
16299815c7cfSMichael Thalmeier u32 im_protocols, u32 tm_protocols)
16309815c7cfSMichael Thalmeier {
16319815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
16329815c7cfSMichael Thalmeier struct pn533_poll_modulations *cur_mod;
1633c64b875fSLars Poeschel struct sk_buff *skb;
16349815c7cfSMichael Thalmeier u8 rand_mod;
16359815c7cfSMichael Thalmeier int rc;
16369815c7cfSMichael Thalmeier
16379815c7cfSMichael Thalmeier dev_dbg(dev->dev,
16389815c7cfSMichael Thalmeier "%s: im protocols 0x%x tm protocols 0x%x\n",
16399815c7cfSMichael Thalmeier __func__, im_protocols, tm_protocols);
16409815c7cfSMichael Thalmeier
16419815c7cfSMichael Thalmeier if (dev->tgt_active_prot) {
16429815c7cfSMichael Thalmeier nfc_err(dev->dev,
16439815c7cfSMichael Thalmeier "Cannot poll with a target already activated\n");
16449815c7cfSMichael Thalmeier return -EBUSY;
16459815c7cfSMichael Thalmeier }
16469815c7cfSMichael Thalmeier
16479815c7cfSMichael Thalmeier if (dev->tgt_mode) {
16489815c7cfSMichael Thalmeier nfc_err(dev->dev,
16499815c7cfSMichael Thalmeier "Cannot poll while already being activated\n");
16509815c7cfSMichael Thalmeier return -EBUSY;
16519815c7cfSMichael Thalmeier }
16529815c7cfSMichael Thalmeier
16539815c7cfSMichael Thalmeier if (tm_protocols) {
16549815c7cfSMichael Thalmeier dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len);
16559815c7cfSMichael Thalmeier if (dev->gb == NULL)
16569815c7cfSMichael Thalmeier tm_protocols = 0;
16579815c7cfSMichael Thalmeier }
16589815c7cfSMichael Thalmeier
16599815c7cfSMichael Thalmeier dev->poll_protocols = im_protocols;
16609815c7cfSMichael Thalmeier dev->listen_protocols = tm_protocols;
1661c64b875fSLars Poeschel if (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL) {
1662c64b875fSLars Poeschel skb = pn533_alloc_skb(dev, 4 + 6);
1663c64b875fSLars Poeschel if (!skb)
1664c64b875fSLars Poeschel return -ENOMEM;
1665c64b875fSLars Poeschel
1666c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1667c64b875fSLars Poeschel PN532_AUTOPOLL_POLLNR_INFINITE;
1668c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) = PN532_AUTOPOLL_PERIOD;
1669c64b875fSLars Poeschel
1670c64b875fSLars Poeschel if ((im_protocols & NFC_PROTO_MIFARE_MASK) &&
1671c64b875fSLars Poeschel (im_protocols & NFC_PROTO_ISO14443_MASK) &&
1672c64b875fSLars Poeschel (im_protocols & NFC_PROTO_NFC_DEP_MASK))
1673c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1674c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_GENERIC_106;
1675c64b875fSLars Poeschel else {
1676c64b875fSLars Poeschel if (im_protocols & NFC_PROTO_MIFARE_MASK)
1677c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1678c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_MIFARE;
1679c64b875fSLars Poeschel
1680c64b875fSLars Poeschel if (im_protocols & NFC_PROTO_ISO14443_MASK)
1681c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1682c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_ISOA;
1683c64b875fSLars Poeschel
1684c64b875fSLars Poeschel if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
1685c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1686c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106;
1687c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1688c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212;
1689c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1690c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424;
1691c64b875fSLars Poeschel }
1692c64b875fSLars Poeschel }
1693c64b875fSLars Poeschel
1694c64b875fSLars Poeschel if (im_protocols & NFC_PROTO_FELICA_MASK ||
1695c64b875fSLars Poeschel im_protocols & NFC_PROTO_NFC_DEP_MASK) {
1696c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1697c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_FELICA212;
1698c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1699c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_FELICA424;
1700c64b875fSLars Poeschel }
1701c64b875fSLars Poeschel
1702c64b875fSLars Poeschel if (im_protocols & NFC_PROTO_JEWEL_MASK)
1703c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1704c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_JEWEL;
1705c64b875fSLars Poeschel
1706c64b875fSLars Poeschel if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
1707c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1708c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_ISOB;
1709c64b875fSLars Poeschel
1710c64b875fSLars Poeschel if (tm_protocols)
1711c64b875fSLars Poeschel *((u8 *)skb_put(skb, sizeof(u8))) =
1712c64b875fSLars Poeschel PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106;
1713c64b875fSLars Poeschel
1714c64b875fSLars Poeschel rc = pn533_send_cmd_async(dev, PN533_CMD_IN_AUTOPOLL, skb,
1715c64b875fSLars Poeschel pn533_autopoll_complete, NULL);
1716c64b875fSLars Poeschel
1717c64b875fSLars Poeschel if (rc < 0)
1718c64b875fSLars Poeschel dev_kfree_skb(skb);
1719c64b875fSLars Poeschel else
1720c64b875fSLars Poeschel dev->poll_mod_count++;
1721c64b875fSLars Poeschel
1722c64b875fSLars Poeschel return rc;
1723c64b875fSLars Poeschel }
1724c64b875fSLars Poeschel
1725c64b875fSLars Poeschel pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
1726*56ad559cSAleksandr Mishin if (!dev->poll_mod_count) {
1727*56ad559cSAleksandr Mishin nfc_err(dev->dev,
1728*56ad559cSAleksandr Mishin "Poll mod list is empty\n");
1729*56ad559cSAleksandr Mishin return -EINVAL;
1730*56ad559cSAleksandr Mishin }
17319815c7cfSMichael Thalmeier
17329815c7cfSMichael Thalmeier /* Do not always start polling from the same modulation */
17339815c7cfSMichael Thalmeier get_random_bytes(&rand_mod, sizeof(rand_mod));
17349815c7cfSMichael Thalmeier rand_mod %= dev->poll_mod_count;
17359815c7cfSMichael Thalmeier dev->poll_mod_curr = rand_mod;
17369815c7cfSMichael Thalmeier
17379815c7cfSMichael Thalmeier cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
17389815c7cfSMichael Thalmeier
17399815c7cfSMichael Thalmeier rc = pn533_send_poll_frame(dev);
17409815c7cfSMichael Thalmeier
17419815c7cfSMichael Thalmeier /* Start listen timer */
17429815c7cfSMichael Thalmeier if (!rc && cur_mod->len == 0 && dev->poll_mod_count > 1)
17439815c7cfSMichael Thalmeier mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ);
17449815c7cfSMichael Thalmeier
17459815c7cfSMichael Thalmeier return rc;
17469815c7cfSMichael Thalmeier }
17479815c7cfSMichael Thalmeier
pn533_stop_poll(struct nfc_dev * nfc_dev)17489815c7cfSMichael Thalmeier static void pn533_stop_poll(struct nfc_dev *nfc_dev)
17499815c7cfSMichael Thalmeier {
17509815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
17519815c7cfSMichael Thalmeier
17529815c7cfSMichael Thalmeier del_timer(&dev->listen_timer);
17539815c7cfSMichael Thalmeier
17549815c7cfSMichael Thalmeier if (!dev->poll_mod_count) {
17559815c7cfSMichael Thalmeier dev_dbg(dev->dev,
17569815c7cfSMichael Thalmeier "Polling operation was not running\n");
17579815c7cfSMichael Thalmeier return;
17589815c7cfSMichael Thalmeier }
17599815c7cfSMichael Thalmeier
17609815c7cfSMichael Thalmeier dev->phy_ops->abort_cmd(dev, GFP_KERNEL);
17619815c7cfSMichael Thalmeier flush_delayed_work(&dev->poll_work);
17629815c7cfSMichael Thalmeier pn533_poll_reset_mod_list(dev);
17639815c7cfSMichael Thalmeier }
17649815c7cfSMichael Thalmeier
pn533_activate_target_nfcdep(struct pn533 * dev)17659815c7cfSMichael Thalmeier static int pn533_activate_target_nfcdep(struct pn533 *dev)
17669815c7cfSMichael Thalmeier {
17679815c7cfSMichael Thalmeier struct pn533_cmd_activate_response *rsp;
17689815c7cfSMichael Thalmeier u16 gt_len;
17699815c7cfSMichael Thalmeier int rc;
17709815c7cfSMichael Thalmeier struct sk_buff *skb;
17719815c7cfSMichael Thalmeier struct sk_buff *resp;
17729815c7cfSMichael Thalmeier
17739815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/
17749815c7cfSMichael Thalmeier if (!skb)
17759815c7cfSMichael Thalmeier return -ENOMEM;
17769815c7cfSMichael Thalmeier
1777634fef61SJohannes Berg skb_put_u8(skb, 1); /* TG */
1778634fef61SJohannes Berg skb_put_u8(skb, 0); /* Next */
17799815c7cfSMichael Thalmeier
17809815c7cfSMichael Thalmeier resp = pn533_send_cmd_sync(dev, PN533_CMD_IN_ATR, skb);
17819815c7cfSMichael Thalmeier if (IS_ERR(resp))
17829815c7cfSMichael Thalmeier return PTR_ERR(resp);
17839815c7cfSMichael Thalmeier
17849815c7cfSMichael Thalmeier rsp = (struct pn533_cmd_activate_response *)resp->data;
17859815c7cfSMichael Thalmeier rc = rsp->status & PN533_CMD_RET_MASK;
17869815c7cfSMichael Thalmeier if (rc != PN533_CMD_RET_SUCCESS) {
17879815c7cfSMichael Thalmeier nfc_err(dev->dev,
17889815c7cfSMichael Thalmeier "Target activation failed (error 0x%x)\n", rc);
17899815c7cfSMichael Thalmeier dev_kfree_skb(resp);
17909815c7cfSMichael Thalmeier return -EIO;
17919815c7cfSMichael Thalmeier }
17929815c7cfSMichael Thalmeier
17939815c7cfSMichael Thalmeier /* ATR_RES general bytes are located at offset 16 */
17949815c7cfSMichael Thalmeier gt_len = resp->len - 16;
17959815c7cfSMichael Thalmeier rc = nfc_set_remote_general_bytes(dev->nfc_dev, rsp->gt, gt_len);
17969815c7cfSMichael Thalmeier
17979815c7cfSMichael Thalmeier dev_kfree_skb(resp);
17989815c7cfSMichael Thalmeier return rc;
17999815c7cfSMichael Thalmeier }
18009815c7cfSMichael Thalmeier
pn533_activate_target(struct nfc_dev * nfc_dev,struct nfc_target * target,u32 protocol)18019815c7cfSMichael Thalmeier static int pn533_activate_target(struct nfc_dev *nfc_dev,
18029815c7cfSMichael Thalmeier struct nfc_target *target, u32 protocol)
18039815c7cfSMichael Thalmeier {
18049815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
18059815c7cfSMichael Thalmeier int rc;
18069815c7cfSMichael Thalmeier
18079815c7cfSMichael Thalmeier dev_dbg(dev->dev, "%s: protocol=%u\n", __func__, protocol);
18089815c7cfSMichael Thalmeier
18099815c7cfSMichael Thalmeier if (dev->poll_mod_count) {
18109815c7cfSMichael Thalmeier nfc_err(dev->dev,
18119815c7cfSMichael Thalmeier "Cannot activate while polling\n");
18129815c7cfSMichael Thalmeier return -EBUSY;
18139815c7cfSMichael Thalmeier }
18149815c7cfSMichael Thalmeier
18159815c7cfSMichael Thalmeier if (dev->tgt_active_prot) {
18169815c7cfSMichael Thalmeier nfc_err(dev->dev,
18179815c7cfSMichael Thalmeier "There is already an active target\n");
18189815c7cfSMichael Thalmeier return -EBUSY;
18199815c7cfSMichael Thalmeier }
18209815c7cfSMichael Thalmeier
18219815c7cfSMichael Thalmeier if (!dev->tgt_available_prots) {
18229815c7cfSMichael Thalmeier nfc_err(dev->dev,
18239815c7cfSMichael Thalmeier "There is no available target to activate\n");
18249815c7cfSMichael Thalmeier return -EINVAL;
18259815c7cfSMichael Thalmeier }
18269815c7cfSMichael Thalmeier
18279815c7cfSMichael Thalmeier if (!(dev->tgt_available_prots & (1 << protocol))) {
18289815c7cfSMichael Thalmeier nfc_err(dev->dev,
18299815c7cfSMichael Thalmeier "Target doesn't support requested proto %u\n",
18309815c7cfSMichael Thalmeier protocol);
18319815c7cfSMichael Thalmeier return -EINVAL;
18329815c7cfSMichael Thalmeier }
18339815c7cfSMichael Thalmeier
18349815c7cfSMichael Thalmeier if (protocol == NFC_PROTO_NFC_DEP) {
18359815c7cfSMichael Thalmeier rc = pn533_activate_target_nfcdep(dev);
18369815c7cfSMichael Thalmeier if (rc) {
18379815c7cfSMichael Thalmeier nfc_err(dev->dev,
18389815c7cfSMichael Thalmeier "Activating target with DEP failed %d\n", rc);
18399815c7cfSMichael Thalmeier return rc;
18409815c7cfSMichael Thalmeier }
18419815c7cfSMichael Thalmeier }
18429815c7cfSMichael Thalmeier
18439815c7cfSMichael Thalmeier dev->tgt_active_prot = protocol;
18449815c7cfSMichael Thalmeier dev->tgt_available_prots = 0;
18459815c7cfSMichael Thalmeier
18469815c7cfSMichael Thalmeier return 0;
18479815c7cfSMichael Thalmeier }
18489815c7cfSMichael Thalmeier
pn533_deactivate_target_complete(struct pn533 * dev,void * arg,struct sk_buff * resp)18499815c7cfSMichael Thalmeier static int pn533_deactivate_target_complete(struct pn533 *dev, void *arg,
18509815c7cfSMichael Thalmeier struct sk_buff *resp)
18519815c7cfSMichael Thalmeier {
18529815c7cfSMichael Thalmeier int rc = 0;
18539815c7cfSMichael Thalmeier
18549815c7cfSMichael Thalmeier if (IS_ERR(resp)) {
18559815c7cfSMichael Thalmeier rc = PTR_ERR(resp);
18569815c7cfSMichael Thalmeier
18579815c7cfSMichael Thalmeier nfc_err(dev->dev, "Target release error %d\n", rc);
18589815c7cfSMichael Thalmeier
18599815c7cfSMichael Thalmeier return rc;
18609815c7cfSMichael Thalmeier }
18619815c7cfSMichael Thalmeier
18629815c7cfSMichael Thalmeier rc = resp->data[0] & PN533_CMD_RET_MASK;
18639815c7cfSMichael Thalmeier if (rc != PN533_CMD_RET_SUCCESS)
18649815c7cfSMichael Thalmeier nfc_err(dev->dev,
18659815c7cfSMichael Thalmeier "Error 0x%x when releasing the target\n", rc);
18669815c7cfSMichael Thalmeier
18679815c7cfSMichael Thalmeier dev_kfree_skb(resp);
18689815c7cfSMichael Thalmeier return rc;
18699815c7cfSMichael Thalmeier }
18709815c7cfSMichael Thalmeier
pn533_deactivate_target(struct nfc_dev * nfc_dev,struct nfc_target * target,u8 mode)18719815c7cfSMichael Thalmeier static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
18729815c7cfSMichael Thalmeier struct nfc_target *target, u8 mode)
18739815c7cfSMichael Thalmeier {
18749815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
18759815c7cfSMichael Thalmeier struct sk_buff *skb;
18769815c7cfSMichael Thalmeier int rc;
18779815c7cfSMichael Thalmeier
18789815c7cfSMichael Thalmeier if (!dev->tgt_active_prot) {
18799815c7cfSMichael Thalmeier nfc_err(dev->dev, "There is no active target\n");
18809815c7cfSMichael Thalmeier return;
18819815c7cfSMichael Thalmeier }
18829815c7cfSMichael Thalmeier
18839815c7cfSMichael Thalmeier dev->tgt_active_prot = 0;
18849815c7cfSMichael Thalmeier skb_queue_purge(&dev->resp_q);
18859815c7cfSMichael Thalmeier
18869815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, sizeof(u8));
18879815c7cfSMichael Thalmeier if (!skb)
18889815c7cfSMichael Thalmeier return;
18899815c7cfSMichael Thalmeier
1890634fef61SJohannes Berg skb_put_u8(skb, 1); /* TG*/
18919815c7cfSMichael Thalmeier
18929815c7cfSMichael Thalmeier rc = pn533_send_cmd_async(dev, PN533_CMD_IN_RELEASE, skb,
18939815c7cfSMichael Thalmeier pn533_deactivate_target_complete, NULL);
18949815c7cfSMichael Thalmeier if (rc < 0) {
18959815c7cfSMichael Thalmeier dev_kfree_skb(skb);
18969815c7cfSMichael Thalmeier nfc_err(dev->dev, "Target release error %d\n", rc);
18979815c7cfSMichael Thalmeier }
18989815c7cfSMichael Thalmeier }
18999815c7cfSMichael Thalmeier
19009815c7cfSMichael Thalmeier
pn533_in_dep_link_up_complete(struct pn533 * dev,void * arg,struct sk_buff * resp)19019815c7cfSMichael Thalmeier static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
19029815c7cfSMichael Thalmeier struct sk_buff *resp)
19039815c7cfSMichael Thalmeier {
19049815c7cfSMichael Thalmeier struct pn533_cmd_jump_dep_response *rsp;
19059815c7cfSMichael Thalmeier u8 target_gt_len;
19069815c7cfSMichael Thalmeier int rc;
19079815c7cfSMichael Thalmeier u8 active = *(u8 *)arg;
19089815c7cfSMichael Thalmeier
19099815c7cfSMichael Thalmeier kfree(arg);
19109815c7cfSMichael Thalmeier
19119815c7cfSMichael Thalmeier if (IS_ERR(resp))
19129815c7cfSMichael Thalmeier return PTR_ERR(resp);
19139815c7cfSMichael Thalmeier
19149815c7cfSMichael Thalmeier if (dev->tgt_available_prots &&
19159815c7cfSMichael Thalmeier !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) {
19169815c7cfSMichael Thalmeier nfc_err(dev->dev,
19179815c7cfSMichael Thalmeier "The target does not support DEP\n");
19189815c7cfSMichael Thalmeier rc = -EINVAL;
19199815c7cfSMichael Thalmeier goto error;
19209815c7cfSMichael Thalmeier }
19219815c7cfSMichael Thalmeier
19229815c7cfSMichael Thalmeier rsp = (struct pn533_cmd_jump_dep_response *)resp->data;
19239815c7cfSMichael Thalmeier
19249815c7cfSMichael Thalmeier rc = rsp->status & PN533_CMD_RET_MASK;
19259815c7cfSMichael Thalmeier if (rc != PN533_CMD_RET_SUCCESS) {
19269815c7cfSMichael Thalmeier nfc_err(dev->dev,
19279815c7cfSMichael Thalmeier "Bringing DEP link up failed (error 0x%x)\n", rc);
19289815c7cfSMichael Thalmeier goto error;
19299815c7cfSMichael Thalmeier }
19309815c7cfSMichael Thalmeier
19319815c7cfSMichael Thalmeier if (!dev->tgt_available_prots) {
19329815c7cfSMichael Thalmeier struct nfc_target nfc_target;
19339815c7cfSMichael Thalmeier
19349815c7cfSMichael Thalmeier dev_dbg(dev->dev, "Creating new target\n");
19359815c7cfSMichael Thalmeier
19369f281577SMinsuk Kang memset(&nfc_target, 0, sizeof(struct nfc_target));
19379f281577SMinsuk Kang
19389815c7cfSMichael Thalmeier nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
19399815c7cfSMichael Thalmeier nfc_target.nfcid1_len = 10;
19409815c7cfSMichael Thalmeier memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len);
19419815c7cfSMichael Thalmeier rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1);
19429815c7cfSMichael Thalmeier if (rc)
19439815c7cfSMichael Thalmeier goto error;
19449815c7cfSMichael Thalmeier
19459815c7cfSMichael Thalmeier dev->tgt_available_prots = 0;
19469815c7cfSMichael Thalmeier }
19479815c7cfSMichael Thalmeier
19489815c7cfSMichael Thalmeier dev->tgt_active_prot = NFC_PROTO_NFC_DEP;
19499815c7cfSMichael Thalmeier
19509815c7cfSMichael Thalmeier /* ATR_RES general bytes are located at offset 17 */
19519815c7cfSMichael Thalmeier target_gt_len = resp->len - 17;
19529815c7cfSMichael Thalmeier rc = nfc_set_remote_general_bytes(dev->nfc_dev,
19539815c7cfSMichael Thalmeier rsp->gt, target_gt_len);
19549815c7cfSMichael Thalmeier if (rc == 0)
19559815c7cfSMichael Thalmeier rc = nfc_dep_link_is_up(dev->nfc_dev,
19569815c7cfSMichael Thalmeier dev->nfc_dev->targets[0].idx,
19579815c7cfSMichael Thalmeier !active, NFC_RF_INITIATOR);
19589815c7cfSMichael Thalmeier
19599815c7cfSMichael Thalmeier error:
19609815c7cfSMichael Thalmeier dev_kfree_skb(resp);
19619815c7cfSMichael Thalmeier return rc;
19629815c7cfSMichael Thalmeier }
19639815c7cfSMichael Thalmeier
19649815c7cfSMichael Thalmeier static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf);
pn533_dep_link_up(struct nfc_dev * nfc_dev,struct nfc_target * target,u8 comm_mode,u8 * gb,size_t gb_len)19659815c7cfSMichael Thalmeier static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
19669815c7cfSMichael Thalmeier u8 comm_mode, u8 *gb, size_t gb_len)
19679815c7cfSMichael Thalmeier {
19689815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
19699815c7cfSMichael Thalmeier struct sk_buff *skb;
19709815c7cfSMichael Thalmeier int rc, skb_len;
19719815c7cfSMichael Thalmeier u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE];
19729815c7cfSMichael Thalmeier u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
19739815c7cfSMichael Thalmeier
19749815c7cfSMichael Thalmeier if (dev->poll_mod_count) {
19759815c7cfSMichael Thalmeier nfc_err(dev->dev,
19769815c7cfSMichael Thalmeier "Cannot bring the DEP link up while polling\n");
19779815c7cfSMichael Thalmeier return -EBUSY;
19789815c7cfSMichael Thalmeier }
19799815c7cfSMichael Thalmeier
19809815c7cfSMichael Thalmeier if (dev->tgt_active_prot) {
19819815c7cfSMichael Thalmeier nfc_err(dev->dev,
19829815c7cfSMichael Thalmeier "There is already an active target\n");
19839815c7cfSMichael Thalmeier return -EBUSY;
19849815c7cfSMichael Thalmeier }
19859815c7cfSMichael Thalmeier
19869815c7cfSMichael Thalmeier skb_len = 3 + gb_len; /* ActPass + BR + Next */
19879815c7cfSMichael Thalmeier skb_len += PASSIVE_DATA_LEN;
19889815c7cfSMichael Thalmeier
19899815c7cfSMichael Thalmeier /* NFCID3 */
19909815c7cfSMichael Thalmeier skb_len += NFC_NFCID3_MAXSIZE;
19919815c7cfSMichael Thalmeier if (target && !target->nfcid2_len) {
19929815c7cfSMichael Thalmeier nfcid3[0] = 0x1;
19939815c7cfSMichael Thalmeier nfcid3[1] = 0xfe;
19949815c7cfSMichael Thalmeier get_random_bytes(nfcid3 + 2, 6);
19959815c7cfSMichael Thalmeier }
19969815c7cfSMichael Thalmeier
19979815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, skb_len);
19989815c7cfSMichael Thalmeier if (!skb)
19999815c7cfSMichael Thalmeier return -ENOMEM;
20009815c7cfSMichael Thalmeier
2001634fef61SJohannes Berg skb_put_u8(skb, !comm_mode); /* ActPass */
2002634fef61SJohannes Berg skb_put_u8(skb, 0x02); /* 424 kbps */
20039815c7cfSMichael Thalmeier
20049815c7cfSMichael Thalmeier next = skb_put(skb, 1); /* Next */
20059815c7cfSMichael Thalmeier *next = 0;
20069815c7cfSMichael Thalmeier
20079815c7cfSMichael Thalmeier /* Copy passive data */
200859ae1d12SJohannes Berg skb_put_data(skb, passive_data, PASSIVE_DATA_LEN);
20099815c7cfSMichael Thalmeier *next |= 1;
20109815c7cfSMichael Thalmeier
20119815c7cfSMichael Thalmeier /* Copy NFCID3 (which is NFCID2 from SENSF_RES) */
20129815c7cfSMichael Thalmeier if (target && target->nfcid2_len)
20139815c7cfSMichael Thalmeier memcpy(skb_put(skb, NFC_NFCID3_MAXSIZE), target->nfcid2,
20149815c7cfSMichael Thalmeier target->nfcid2_len);
20159815c7cfSMichael Thalmeier else
201659ae1d12SJohannes Berg skb_put_data(skb, nfcid3, NFC_NFCID3_MAXSIZE);
20179815c7cfSMichael Thalmeier *next |= 2;
20189815c7cfSMichael Thalmeier
20199815c7cfSMichael Thalmeier if (gb != NULL && gb_len > 0) {
202059ae1d12SJohannes Berg skb_put_data(skb, gb, gb_len);
20219815c7cfSMichael Thalmeier *next |= 4; /* We have some Gi */
20229815c7cfSMichael Thalmeier } else {
20239815c7cfSMichael Thalmeier *next = 0;
20249815c7cfSMichael Thalmeier }
20259815c7cfSMichael Thalmeier
20269815c7cfSMichael Thalmeier arg = kmalloc(sizeof(*arg), GFP_KERNEL);
20279815c7cfSMichael Thalmeier if (!arg) {
20289815c7cfSMichael Thalmeier dev_kfree_skb(skb);
20299815c7cfSMichael Thalmeier return -ENOMEM;
20309815c7cfSMichael Thalmeier }
20319815c7cfSMichael Thalmeier
20329815c7cfSMichael Thalmeier *arg = !comm_mode;
20339815c7cfSMichael Thalmeier
20349815c7cfSMichael Thalmeier pn533_rf_field(dev->nfc_dev, 0);
20359815c7cfSMichael Thalmeier
20369815c7cfSMichael Thalmeier rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb,
20379815c7cfSMichael Thalmeier pn533_in_dep_link_up_complete, arg);
20389815c7cfSMichael Thalmeier
20399815c7cfSMichael Thalmeier if (rc < 0) {
20409815c7cfSMichael Thalmeier dev_kfree_skb(skb);
20419815c7cfSMichael Thalmeier kfree(arg);
20429815c7cfSMichael Thalmeier }
20439815c7cfSMichael Thalmeier
20449815c7cfSMichael Thalmeier return rc;
20459815c7cfSMichael Thalmeier }
20469815c7cfSMichael Thalmeier
pn533_dep_link_down(struct nfc_dev * nfc_dev)20479815c7cfSMichael Thalmeier static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
20489815c7cfSMichael Thalmeier {
20499815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
20509815c7cfSMichael Thalmeier
20519815c7cfSMichael Thalmeier pn533_poll_reset_mod_list(dev);
20529815c7cfSMichael Thalmeier
20539815c7cfSMichael Thalmeier if (dev->tgt_mode || dev->tgt_active_prot)
20549815c7cfSMichael Thalmeier dev->phy_ops->abort_cmd(dev, GFP_KERNEL);
20559815c7cfSMichael Thalmeier
20569815c7cfSMichael Thalmeier dev->tgt_active_prot = 0;
20579815c7cfSMichael Thalmeier dev->tgt_mode = 0;
20589815c7cfSMichael Thalmeier
20599815c7cfSMichael Thalmeier skb_queue_purge(&dev->resp_q);
20609815c7cfSMichael Thalmeier
20619815c7cfSMichael Thalmeier return 0;
20629815c7cfSMichael Thalmeier }
20639815c7cfSMichael Thalmeier
20649815c7cfSMichael Thalmeier struct pn533_data_exchange_arg {
20659815c7cfSMichael Thalmeier data_exchange_cb_t cb;
20669815c7cfSMichael Thalmeier void *cb_context;
20679815c7cfSMichael Thalmeier };
20689815c7cfSMichael Thalmeier
pn533_build_response(struct pn533 * dev)20699815c7cfSMichael Thalmeier static struct sk_buff *pn533_build_response(struct pn533 *dev)
20709815c7cfSMichael Thalmeier {
20719815c7cfSMichael Thalmeier struct sk_buff *skb, *tmp, *t;
20729815c7cfSMichael Thalmeier unsigned int skb_len = 0, tmp_len = 0;
20739815c7cfSMichael Thalmeier
20749815c7cfSMichael Thalmeier if (skb_queue_empty(&dev->resp_q))
20759815c7cfSMichael Thalmeier return NULL;
20769815c7cfSMichael Thalmeier
20779815c7cfSMichael Thalmeier if (skb_queue_len(&dev->resp_q) == 1) {
20789815c7cfSMichael Thalmeier skb = skb_dequeue(&dev->resp_q);
20799815c7cfSMichael Thalmeier goto out;
20809815c7cfSMichael Thalmeier }
20819815c7cfSMichael Thalmeier
20829815c7cfSMichael Thalmeier skb_queue_walk_safe(&dev->resp_q, tmp, t)
20839815c7cfSMichael Thalmeier skb_len += tmp->len;
20849815c7cfSMichael Thalmeier
20859815c7cfSMichael Thalmeier dev_dbg(dev->dev, "%s total length %d\n",
20869815c7cfSMichael Thalmeier __func__, skb_len);
20879815c7cfSMichael Thalmeier
20889815c7cfSMichael Thalmeier skb = alloc_skb(skb_len, GFP_KERNEL);
20899815c7cfSMichael Thalmeier if (skb == NULL)
20909815c7cfSMichael Thalmeier goto out;
20919815c7cfSMichael Thalmeier
20929815c7cfSMichael Thalmeier skb_put(skb, skb_len);
20939815c7cfSMichael Thalmeier
20949815c7cfSMichael Thalmeier skb_queue_walk_safe(&dev->resp_q, tmp, t) {
20959815c7cfSMichael Thalmeier memcpy(skb->data + tmp_len, tmp->data, tmp->len);
20969815c7cfSMichael Thalmeier tmp_len += tmp->len;
20979815c7cfSMichael Thalmeier }
20989815c7cfSMichael Thalmeier
20999815c7cfSMichael Thalmeier out:
21009815c7cfSMichael Thalmeier skb_queue_purge(&dev->resp_q);
21019815c7cfSMichael Thalmeier
21029815c7cfSMichael Thalmeier return skb;
21039815c7cfSMichael Thalmeier }
21049815c7cfSMichael Thalmeier
pn533_data_exchange_complete(struct pn533 * dev,void * _arg,struct sk_buff * resp)21059815c7cfSMichael Thalmeier static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
21069815c7cfSMichael Thalmeier struct sk_buff *resp)
21079815c7cfSMichael Thalmeier {
21089815c7cfSMichael Thalmeier struct pn533_data_exchange_arg *arg = _arg;
21099815c7cfSMichael Thalmeier struct sk_buff *skb;
21109815c7cfSMichael Thalmeier int rc = 0;
21119815c7cfSMichael Thalmeier u8 status, ret, mi;
21129815c7cfSMichael Thalmeier
21139815c7cfSMichael Thalmeier if (IS_ERR(resp)) {
21149815c7cfSMichael Thalmeier rc = PTR_ERR(resp);
21159815c7cfSMichael Thalmeier goto _error;
21169815c7cfSMichael Thalmeier }
21179815c7cfSMichael Thalmeier
21189815c7cfSMichael Thalmeier status = resp->data[0];
21199815c7cfSMichael Thalmeier ret = status & PN533_CMD_RET_MASK;
21209815c7cfSMichael Thalmeier mi = status & PN533_CMD_MI_MASK;
21219815c7cfSMichael Thalmeier
21229815c7cfSMichael Thalmeier skb_pull(resp, sizeof(status));
21239815c7cfSMichael Thalmeier
21249815c7cfSMichael Thalmeier if (ret != PN533_CMD_RET_SUCCESS) {
21259815c7cfSMichael Thalmeier nfc_err(dev->dev,
21269815c7cfSMichael Thalmeier "Exchanging data failed (error 0x%x)\n", ret);
21279815c7cfSMichael Thalmeier rc = -EIO;
21289815c7cfSMichael Thalmeier goto error;
21299815c7cfSMichael Thalmeier }
21309815c7cfSMichael Thalmeier
21319815c7cfSMichael Thalmeier skb_queue_tail(&dev->resp_q, resp);
21329815c7cfSMichael Thalmeier
21339815c7cfSMichael Thalmeier if (mi) {
21349815c7cfSMichael Thalmeier dev->cmd_complete_mi_arg = arg;
21359815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->mi_rx_work);
21369815c7cfSMichael Thalmeier return -EINPROGRESS;
21379815c7cfSMichael Thalmeier }
21389815c7cfSMichael Thalmeier
21399815c7cfSMichael Thalmeier /* Prepare for the next round */
21409815c7cfSMichael Thalmeier if (skb_queue_len(&dev->fragment_skb) > 0) {
21419815c7cfSMichael Thalmeier dev->cmd_complete_dep_arg = arg;
21429815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->mi_tx_work);
21439815c7cfSMichael Thalmeier
21449815c7cfSMichael Thalmeier return -EINPROGRESS;
21459815c7cfSMichael Thalmeier }
21469815c7cfSMichael Thalmeier
21479815c7cfSMichael Thalmeier skb = pn533_build_response(dev);
21489815c7cfSMichael Thalmeier if (!skb) {
21499815c7cfSMichael Thalmeier rc = -ENOMEM;
21509815c7cfSMichael Thalmeier goto error;
21519815c7cfSMichael Thalmeier }
21529815c7cfSMichael Thalmeier
21539815c7cfSMichael Thalmeier arg->cb(arg->cb_context, skb, 0);
21549815c7cfSMichael Thalmeier kfree(arg);
21559815c7cfSMichael Thalmeier return 0;
21569815c7cfSMichael Thalmeier
21579815c7cfSMichael Thalmeier error:
21589815c7cfSMichael Thalmeier dev_kfree_skb(resp);
21599815c7cfSMichael Thalmeier _error:
21609815c7cfSMichael Thalmeier skb_queue_purge(&dev->resp_q);
21619815c7cfSMichael Thalmeier arg->cb(arg->cb_context, NULL, rc);
21629815c7cfSMichael Thalmeier kfree(arg);
21639815c7cfSMichael Thalmeier return rc;
21649815c7cfSMichael Thalmeier }
21659815c7cfSMichael Thalmeier
21669815c7cfSMichael Thalmeier /*
21679815c7cfSMichael Thalmeier * Receive an incoming pn533 frame. skb contains only header and payload.
21689815c7cfSMichael Thalmeier * If skb == NULL, it is a notification that the link below is dead.
21699815c7cfSMichael Thalmeier */
pn533_recv_frame(struct pn533 * dev,struct sk_buff * skb,int status)21709815c7cfSMichael Thalmeier void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status)
21719815c7cfSMichael Thalmeier {
2172b31d5103SMichael Thalmeier if (!dev->cmd)
2173b31d5103SMichael Thalmeier goto sched_wq;
2174b31d5103SMichael Thalmeier
21759815c7cfSMichael Thalmeier dev->cmd->status = status;
21769815c7cfSMichael Thalmeier
2177b31d5103SMichael Thalmeier if (status != 0) {
2178b31d5103SMichael Thalmeier dev_dbg(dev->dev, "%s: Error received: %d\n", __func__, status);
2179b31d5103SMichael Thalmeier goto sched_wq;
2180b31d5103SMichael Thalmeier }
2181b31d5103SMichael Thalmeier
21829815c7cfSMichael Thalmeier if (skb == NULL) {
21839981ab21SKrzysztof Kozlowski dev_err(dev->dev, "NULL Frame -> link is dead\n");
21849815c7cfSMichael Thalmeier goto sched_wq;
21859815c7cfSMichael Thalmeier }
21869815c7cfSMichael Thalmeier
21879815c7cfSMichael Thalmeier if (pn533_rx_frame_is_ack(skb->data)) {
21889815c7cfSMichael Thalmeier dev_dbg(dev->dev, "%s: Received ACK frame\n", __func__);
21899815c7cfSMichael Thalmeier dev_kfree_skb(skb);
21909815c7cfSMichael Thalmeier return;
21919815c7cfSMichael Thalmeier }
21929815c7cfSMichael Thalmeier
21939815c7cfSMichael Thalmeier print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, skb->data,
21949815c7cfSMichael Thalmeier dev->ops->rx_frame_size(skb->data), false);
21959815c7cfSMichael Thalmeier
21969815c7cfSMichael Thalmeier if (!dev->ops->rx_is_frame_valid(skb->data, dev)) {
21979815c7cfSMichael Thalmeier nfc_err(dev->dev, "Received an invalid frame\n");
21989815c7cfSMichael Thalmeier dev->cmd->status = -EIO;
21999815c7cfSMichael Thalmeier } else if (!pn533_rx_frame_is_cmd_response(dev, skb->data)) {
22009815c7cfSMichael Thalmeier nfc_err(dev->dev, "It it not the response to the last command\n");
22019815c7cfSMichael Thalmeier dev->cmd->status = -EIO;
22029815c7cfSMichael Thalmeier }
22039815c7cfSMichael Thalmeier
22049815c7cfSMichael Thalmeier dev->cmd->resp = skb;
22059815c7cfSMichael Thalmeier
22069815c7cfSMichael Thalmeier sched_wq:
22079815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->cmd_complete_work);
22089815c7cfSMichael Thalmeier }
22099815c7cfSMichael Thalmeier EXPORT_SYMBOL(pn533_recv_frame);
22109815c7cfSMichael Thalmeier
22119815c7cfSMichael Thalmeier /* Split the Tx skb into small chunks */
pn533_fill_fragment_skbs(struct pn533 * dev,struct sk_buff * skb)22129815c7cfSMichael Thalmeier static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb)
22139815c7cfSMichael Thalmeier {
22149815c7cfSMichael Thalmeier struct sk_buff *frag;
22159815c7cfSMichael Thalmeier int frag_size;
22169815c7cfSMichael Thalmeier
22179815c7cfSMichael Thalmeier do {
22189815c7cfSMichael Thalmeier /* Remaining size */
22199815c7cfSMichael Thalmeier if (skb->len > PN533_CMD_DATAFRAME_MAXLEN)
22209815c7cfSMichael Thalmeier frag_size = PN533_CMD_DATAFRAME_MAXLEN;
22219815c7cfSMichael Thalmeier else
22229815c7cfSMichael Thalmeier frag_size = skb->len;
22239815c7cfSMichael Thalmeier
22249815c7cfSMichael Thalmeier /* Allocate and reserve */
22259815c7cfSMichael Thalmeier frag = pn533_alloc_skb(dev, frag_size);
22269815c7cfSMichael Thalmeier if (!frag) {
22279815c7cfSMichael Thalmeier skb_queue_purge(&dev->fragment_skb);
22289fec40f8SChengfeng Ye return -ENOMEM;
22299815c7cfSMichael Thalmeier }
22309815c7cfSMichael Thalmeier
22319815c7cfSMichael Thalmeier if (!dev->tgt_mode) {
22329815c7cfSMichael Thalmeier /* Reserve the TG/MI byte */
22339815c7cfSMichael Thalmeier skb_reserve(frag, 1);
22349815c7cfSMichael Thalmeier
22359815c7cfSMichael Thalmeier /* MI + TG */
22369815c7cfSMichael Thalmeier if (frag_size == PN533_CMD_DATAFRAME_MAXLEN)
2237d58ff351SJohannes Berg *(u8 *)skb_push(frag, sizeof(u8)) =
22389815c7cfSMichael Thalmeier (PN533_CMD_MI_MASK | 1);
22399815c7cfSMichael Thalmeier else
2240d58ff351SJohannes Berg *(u8 *)skb_push(frag, sizeof(u8)) = 1; /* TG */
22419815c7cfSMichael Thalmeier }
22429815c7cfSMichael Thalmeier
224359ae1d12SJohannes Berg skb_put_data(frag, skb->data, frag_size);
22449815c7cfSMichael Thalmeier
22459815c7cfSMichael Thalmeier /* Reduce the size of incoming buffer */
22469815c7cfSMichael Thalmeier skb_pull(skb, frag_size);
22479815c7cfSMichael Thalmeier
22489815c7cfSMichael Thalmeier /* Add this to skb_queue */
22499815c7cfSMichael Thalmeier skb_queue_tail(&dev->fragment_skb, frag);
22509815c7cfSMichael Thalmeier
22519815c7cfSMichael Thalmeier } while (skb->len > 0);
22529815c7cfSMichael Thalmeier
22539815c7cfSMichael Thalmeier dev_kfree_skb(skb);
22549815c7cfSMichael Thalmeier
22559815c7cfSMichael Thalmeier return skb_queue_len(&dev->fragment_skb);
22569815c7cfSMichael Thalmeier }
22579815c7cfSMichael Thalmeier
pn533_transceive(struct nfc_dev * nfc_dev,struct nfc_target * target,struct sk_buff * skb,data_exchange_cb_t cb,void * cb_context)22589815c7cfSMichael Thalmeier static int pn533_transceive(struct nfc_dev *nfc_dev,
22599815c7cfSMichael Thalmeier struct nfc_target *target, struct sk_buff *skb,
22609815c7cfSMichael Thalmeier data_exchange_cb_t cb, void *cb_context)
22619815c7cfSMichael Thalmeier {
22629815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
22639815c7cfSMichael Thalmeier struct pn533_data_exchange_arg *arg = NULL;
22649815c7cfSMichael Thalmeier int rc;
22659815c7cfSMichael Thalmeier
22669815c7cfSMichael Thalmeier if (!dev->tgt_active_prot) {
22679815c7cfSMichael Thalmeier nfc_err(dev->dev,
22689815c7cfSMichael Thalmeier "Can't exchange data if there is no active target\n");
22699815c7cfSMichael Thalmeier rc = -EINVAL;
22709815c7cfSMichael Thalmeier goto error;
22719815c7cfSMichael Thalmeier }
22729815c7cfSMichael Thalmeier
22739815c7cfSMichael Thalmeier arg = kmalloc(sizeof(*arg), GFP_KERNEL);
22749815c7cfSMichael Thalmeier if (!arg) {
22759815c7cfSMichael Thalmeier rc = -ENOMEM;
22769815c7cfSMichael Thalmeier goto error;
22779815c7cfSMichael Thalmeier }
22789815c7cfSMichael Thalmeier
22799815c7cfSMichael Thalmeier arg->cb = cb;
22809815c7cfSMichael Thalmeier arg->cb_context = cb_context;
22819815c7cfSMichael Thalmeier
22829815c7cfSMichael Thalmeier switch (dev->device_type) {
22839815c7cfSMichael Thalmeier case PN533_DEVICE_PASORI:
22849815c7cfSMichael Thalmeier if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
22859815c7cfSMichael Thalmeier rc = pn533_send_data_async(dev, PN533_CMD_IN_COMM_THRU,
22869815c7cfSMichael Thalmeier skb,
22879815c7cfSMichael Thalmeier pn533_data_exchange_complete,
22889815c7cfSMichael Thalmeier arg);
22899815c7cfSMichael Thalmeier
22909815c7cfSMichael Thalmeier break;
22919815c7cfSMichael Thalmeier }
2292df561f66SGustavo A. R. Silva fallthrough;
22939815c7cfSMichael Thalmeier default:
22949815c7cfSMichael Thalmeier /* jumbo frame ? */
22959815c7cfSMichael Thalmeier if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
22969815c7cfSMichael Thalmeier rc = pn533_fill_fragment_skbs(dev, skb);
22979fec40f8SChengfeng Ye if (rc < 0)
22989815c7cfSMichael Thalmeier goto error;
22999815c7cfSMichael Thalmeier
23009815c7cfSMichael Thalmeier skb = skb_dequeue(&dev->fragment_skb);
23019815c7cfSMichael Thalmeier if (!skb) {
23029815c7cfSMichael Thalmeier rc = -EIO;
23039815c7cfSMichael Thalmeier goto error;
23049815c7cfSMichael Thalmeier }
23059815c7cfSMichael Thalmeier } else {
2306d58ff351SJohannes Berg *(u8 *)skb_push(skb, sizeof(u8)) = 1; /* TG */
23079815c7cfSMichael Thalmeier }
23089815c7cfSMichael Thalmeier
23099815c7cfSMichael Thalmeier rc = pn533_send_data_async(dev, PN533_CMD_IN_DATA_EXCHANGE,
23109815c7cfSMichael Thalmeier skb, pn533_data_exchange_complete,
23119815c7cfSMichael Thalmeier arg);
23129815c7cfSMichael Thalmeier
23139815c7cfSMichael Thalmeier break;
23149815c7cfSMichael Thalmeier }
23159815c7cfSMichael Thalmeier
23169815c7cfSMichael Thalmeier if (rc < 0) /* rc from send_async */
23179815c7cfSMichael Thalmeier goto error;
23189815c7cfSMichael Thalmeier
23199815c7cfSMichael Thalmeier return 0;
23209815c7cfSMichael Thalmeier
23219815c7cfSMichael Thalmeier error:
23229815c7cfSMichael Thalmeier kfree(arg);
23239815c7cfSMichael Thalmeier dev_kfree_skb(skb);
23249815c7cfSMichael Thalmeier return rc;
23259815c7cfSMichael Thalmeier }
23269815c7cfSMichael Thalmeier
pn533_tm_send_complete(struct pn533 * dev,void * arg,struct sk_buff * resp)23279815c7cfSMichael Thalmeier static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
23289815c7cfSMichael Thalmeier struct sk_buff *resp)
23299815c7cfSMichael Thalmeier {
23309815c7cfSMichael Thalmeier u8 status;
23319815c7cfSMichael Thalmeier
23329815c7cfSMichael Thalmeier if (IS_ERR(resp))
23339815c7cfSMichael Thalmeier return PTR_ERR(resp);
23349815c7cfSMichael Thalmeier
23359815c7cfSMichael Thalmeier status = resp->data[0];
23369815c7cfSMichael Thalmeier
23379815c7cfSMichael Thalmeier /* Prepare for the next round */
23389815c7cfSMichael Thalmeier if (skb_queue_len(&dev->fragment_skb) > 0) {
23399815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->mi_tm_tx_work);
23409815c7cfSMichael Thalmeier return -EINPROGRESS;
23419815c7cfSMichael Thalmeier }
23429815c7cfSMichael Thalmeier dev_kfree_skb(resp);
23439815c7cfSMichael Thalmeier
23449815c7cfSMichael Thalmeier if (status != 0) {
23459815c7cfSMichael Thalmeier nfc_tm_deactivated(dev->nfc_dev);
23469815c7cfSMichael Thalmeier
23479815c7cfSMichael Thalmeier dev->tgt_mode = 0;
23489815c7cfSMichael Thalmeier
23499815c7cfSMichael Thalmeier return 0;
23509815c7cfSMichael Thalmeier }
23519815c7cfSMichael Thalmeier
23529815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->tg_work);
23539815c7cfSMichael Thalmeier
23549815c7cfSMichael Thalmeier return 0;
23559815c7cfSMichael Thalmeier }
23569815c7cfSMichael Thalmeier
pn533_tm_send(struct nfc_dev * nfc_dev,struct sk_buff * skb)23579815c7cfSMichael Thalmeier static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
23589815c7cfSMichael Thalmeier {
23599815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
23609815c7cfSMichael Thalmeier int rc;
23619815c7cfSMichael Thalmeier
23629815c7cfSMichael Thalmeier /* let's split in multiple chunks if size's too big */
23639815c7cfSMichael Thalmeier if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
23649815c7cfSMichael Thalmeier rc = pn533_fill_fragment_skbs(dev, skb);
23659fec40f8SChengfeng Ye if (rc < 0)
23669815c7cfSMichael Thalmeier goto error;
23679815c7cfSMichael Thalmeier
23689815c7cfSMichael Thalmeier /* get the first skb */
23699815c7cfSMichael Thalmeier skb = skb_dequeue(&dev->fragment_skb);
23709815c7cfSMichael Thalmeier if (!skb) {
23719815c7cfSMichael Thalmeier rc = -EIO;
23729815c7cfSMichael Thalmeier goto error;
23739815c7cfSMichael Thalmeier }
23749815c7cfSMichael Thalmeier
23759815c7cfSMichael Thalmeier rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_META_DATA, skb,
23769815c7cfSMichael Thalmeier pn533_tm_send_complete, NULL);
23779815c7cfSMichael Thalmeier } else {
23789815c7cfSMichael Thalmeier /* Send th skb */
23799815c7cfSMichael Thalmeier rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_DATA, skb,
23809815c7cfSMichael Thalmeier pn533_tm_send_complete, NULL);
23819815c7cfSMichael Thalmeier }
23829815c7cfSMichael Thalmeier
23839815c7cfSMichael Thalmeier error:
23849815c7cfSMichael Thalmeier if (rc < 0) {
23859815c7cfSMichael Thalmeier dev_kfree_skb(skb);
23869815c7cfSMichael Thalmeier skb_queue_purge(&dev->fragment_skb);
23879815c7cfSMichael Thalmeier }
23889815c7cfSMichael Thalmeier
23899815c7cfSMichael Thalmeier return rc;
23909815c7cfSMichael Thalmeier }
23919815c7cfSMichael Thalmeier
pn533_wq_mi_recv(struct work_struct * work)23929815c7cfSMichael Thalmeier static void pn533_wq_mi_recv(struct work_struct *work)
23939815c7cfSMichael Thalmeier {
23949815c7cfSMichael Thalmeier struct pn533 *dev = container_of(work, struct pn533, mi_rx_work);
23959815c7cfSMichael Thalmeier struct sk_buff *skb;
23969815c7cfSMichael Thalmeier int rc;
23979815c7cfSMichael Thalmeier
23989815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN);
23999815c7cfSMichael Thalmeier if (!skb)
24009815c7cfSMichael Thalmeier goto error;
24019815c7cfSMichael Thalmeier
24029815c7cfSMichael Thalmeier switch (dev->device_type) {
24039815c7cfSMichael Thalmeier case PN533_DEVICE_PASORI:
24049815c7cfSMichael Thalmeier if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
24059815c7cfSMichael Thalmeier rc = pn533_send_cmd_direct_async(dev,
24069815c7cfSMichael Thalmeier PN533_CMD_IN_COMM_THRU,
24079815c7cfSMichael Thalmeier skb,
24089815c7cfSMichael Thalmeier pn533_data_exchange_complete,
24099815c7cfSMichael Thalmeier dev->cmd_complete_mi_arg);
24109815c7cfSMichael Thalmeier
24119815c7cfSMichael Thalmeier break;
24129815c7cfSMichael Thalmeier }
2413df561f66SGustavo A. R. Silva fallthrough;
24149815c7cfSMichael Thalmeier default:
2415634fef61SJohannes Berg skb_put_u8(skb, 1); /*TG*/
24169815c7cfSMichael Thalmeier
24179815c7cfSMichael Thalmeier rc = pn533_send_cmd_direct_async(dev,
24189815c7cfSMichael Thalmeier PN533_CMD_IN_DATA_EXCHANGE,
24199815c7cfSMichael Thalmeier skb,
24209815c7cfSMichael Thalmeier pn533_data_exchange_complete,
24219815c7cfSMichael Thalmeier dev->cmd_complete_mi_arg);
24229815c7cfSMichael Thalmeier
24239815c7cfSMichael Thalmeier break;
24249815c7cfSMichael Thalmeier }
24259815c7cfSMichael Thalmeier
24269815c7cfSMichael Thalmeier if (rc == 0) /* success */
24279815c7cfSMichael Thalmeier return;
24289815c7cfSMichael Thalmeier
24299815c7cfSMichael Thalmeier nfc_err(dev->dev,
24309815c7cfSMichael Thalmeier "Error %d when trying to perform data_exchange\n", rc);
24319815c7cfSMichael Thalmeier
24329815c7cfSMichael Thalmeier dev_kfree_skb(skb);
24339815c7cfSMichael Thalmeier kfree(dev->cmd_complete_mi_arg);
24349815c7cfSMichael Thalmeier
24359815c7cfSMichael Thalmeier error:
24369815c7cfSMichael Thalmeier dev->phy_ops->send_ack(dev, GFP_KERNEL);
24379815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->cmd_work);
24389815c7cfSMichael Thalmeier }
24399815c7cfSMichael Thalmeier
pn533_wq_mi_send(struct work_struct * work)24409815c7cfSMichael Thalmeier static void pn533_wq_mi_send(struct work_struct *work)
24419815c7cfSMichael Thalmeier {
24429815c7cfSMichael Thalmeier struct pn533 *dev = container_of(work, struct pn533, mi_tx_work);
24439815c7cfSMichael Thalmeier struct sk_buff *skb;
24449815c7cfSMichael Thalmeier int rc;
24459815c7cfSMichael Thalmeier
24469815c7cfSMichael Thalmeier /* Grab the first skb in the queue */
24479815c7cfSMichael Thalmeier skb = skb_dequeue(&dev->fragment_skb);
24489815c7cfSMichael Thalmeier
24499815c7cfSMichael Thalmeier if (skb == NULL) { /* No more data */
24509815c7cfSMichael Thalmeier /* Reset the queue for future use */
24519815c7cfSMichael Thalmeier skb_queue_head_init(&dev->fragment_skb);
24529815c7cfSMichael Thalmeier goto error;
24539815c7cfSMichael Thalmeier }
24549815c7cfSMichael Thalmeier
24559815c7cfSMichael Thalmeier switch (dev->device_type) {
24569815c7cfSMichael Thalmeier case PN533_DEVICE_PASORI:
24579815c7cfSMichael Thalmeier if (dev->tgt_active_prot != NFC_PROTO_FELICA) {
24589815c7cfSMichael Thalmeier rc = -EIO;
24599815c7cfSMichael Thalmeier break;
24609815c7cfSMichael Thalmeier }
24619815c7cfSMichael Thalmeier
24629815c7cfSMichael Thalmeier rc = pn533_send_cmd_direct_async(dev, PN533_CMD_IN_COMM_THRU,
24639815c7cfSMichael Thalmeier skb,
24649815c7cfSMichael Thalmeier pn533_data_exchange_complete,
24659815c7cfSMichael Thalmeier dev->cmd_complete_dep_arg);
24669815c7cfSMichael Thalmeier
24679815c7cfSMichael Thalmeier break;
24689815c7cfSMichael Thalmeier
24699815c7cfSMichael Thalmeier default:
24709815c7cfSMichael Thalmeier /* Still some fragments? */
24719815c7cfSMichael Thalmeier rc = pn533_send_cmd_direct_async(dev,
24729815c7cfSMichael Thalmeier PN533_CMD_IN_DATA_EXCHANGE,
24739815c7cfSMichael Thalmeier skb,
24749815c7cfSMichael Thalmeier pn533_data_exchange_complete,
24759815c7cfSMichael Thalmeier dev->cmd_complete_dep_arg);
24769815c7cfSMichael Thalmeier
24779815c7cfSMichael Thalmeier break;
24789815c7cfSMichael Thalmeier }
24799815c7cfSMichael Thalmeier
24809815c7cfSMichael Thalmeier if (rc == 0) /* success */
24819815c7cfSMichael Thalmeier return;
24829815c7cfSMichael Thalmeier
24839815c7cfSMichael Thalmeier nfc_err(dev->dev,
24849815c7cfSMichael Thalmeier "Error %d when trying to perform data_exchange\n", rc);
24859815c7cfSMichael Thalmeier
24869815c7cfSMichael Thalmeier dev_kfree_skb(skb);
24879815c7cfSMichael Thalmeier kfree(dev->cmd_complete_dep_arg);
24889815c7cfSMichael Thalmeier
24899815c7cfSMichael Thalmeier error:
24909815c7cfSMichael Thalmeier dev->phy_ops->send_ack(dev, GFP_KERNEL);
24919815c7cfSMichael Thalmeier queue_work(dev->wq, &dev->cmd_work);
24929815c7cfSMichael Thalmeier }
24939815c7cfSMichael Thalmeier
pn533_set_configuration(struct pn533 * dev,u8 cfgitem,u8 * cfgdata,u8 cfgdata_len)24949815c7cfSMichael Thalmeier static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
24959815c7cfSMichael Thalmeier u8 cfgdata_len)
24969815c7cfSMichael Thalmeier {
24979815c7cfSMichael Thalmeier struct sk_buff *skb;
24989815c7cfSMichael Thalmeier struct sk_buff *resp;
24999815c7cfSMichael Thalmeier int skb_len;
25009815c7cfSMichael Thalmeier
25019815c7cfSMichael Thalmeier skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */
25029815c7cfSMichael Thalmeier
25039815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, skb_len);
25049815c7cfSMichael Thalmeier if (!skb)
25059815c7cfSMichael Thalmeier return -ENOMEM;
25069815c7cfSMichael Thalmeier
2507634fef61SJohannes Berg skb_put_u8(skb, cfgitem);
250859ae1d12SJohannes Berg skb_put_data(skb, cfgdata, cfgdata_len);
25099815c7cfSMichael Thalmeier
25109815c7cfSMichael Thalmeier resp = pn533_send_cmd_sync(dev, PN533_CMD_RF_CONFIGURATION, skb);
25119815c7cfSMichael Thalmeier if (IS_ERR(resp))
25129815c7cfSMichael Thalmeier return PTR_ERR(resp);
25139815c7cfSMichael Thalmeier
25149815c7cfSMichael Thalmeier dev_kfree_skb(resp);
25159815c7cfSMichael Thalmeier return 0;
25169815c7cfSMichael Thalmeier }
25179815c7cfSMichael Thalmeier
pn533_get_firmware_version(struct pn533 * dev,struct pn533_fw_version * fv)25189815c7cfSMichael Thalmeier static int pn533_get_firmware_version(struct pn533 *dev,
25199815c7cfSMichael Thalmeier struct pn533_fw_version *fv)
25209815c7cfSMichael Thalmeier {
25219815c7cfSMichael Thalmeier struct sk_buff *skb;
25229815c7cfSMichael Thalmeier struct sk_buff *resp;
25239815c7cfSMichael Thalmeier
25249815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, 0);
25259815c7cfSMichael Thalmeier if (!skb)
25269815c7cfSMichael Thalmeier return -ENOMEM;
25279815c7cfSMichael Thalmeier
25289815c7cfSMichael Thalmeier resp = pn533_send_cmd_sync(dev, PN533_CMD_GET_FIRMWARE_VERSION, skb);
25299815c7cfSMichael Thalmeier if (IS_ERR(resp))
25309815c7cfSMichael Thalmeier return PTR_ERR(resp);
25319815c7cfSMichael Thalmeier
25329815c7cfSMichael Thalmeier fv->ic = resp->data[0];
25339815c7cfSMichael Thalmeier fv->ver = resp->data[1];
25349815c7cfSMichael Thalmeier fv->rev = resp->data[2];
25359815c7cfSMichael Thalmeier fv->support = resp->data[3];
25369815c7cfSMichael Thalmeier
25379815c7cfSMichael Thalmeier dev_kfree_skb(resp);
25389815c7cfSMichael Thalmeier return 0;
25399815c7cfSMichael Thalmeier }
25409815c7cfSMichael Thalmeier
pn533_pasori_fw_reset(struct pn533 * dev)25419815c7cfSMichael Thalmeier static int pn533_pasori_fw_reset(struct pn533 *dev)
25429815c7cfSMichael Thalmeier {
25439815c7cfSMichael Thalmeier struct sk_buff *skb;
25449815c7cfSMichael Thalmeier struct sk_buff *resp;
25459815c7cfSMichael Thalmeier
25469815c7cfSMichael Thalmeier skb = pn533_alloc_skb(dev, sizeof(u8));
25479815c7cfSMichael Thalmeier if (!skb)
25489815c7cfSMichael Thalmeier return -ENOMEM;
25499815c7cfSMichael Thalmeier
2550634fef61SJohannes Berg skb_put_u8(skb, 0x1);
25519815c7cfSMichael Thalmeier
25529815c7cfSMichael Thalmeier resp = pn533_send_cmd_sync(dev, 0x18, skb);
25539815c7cfSMichael Thalmeier if (IS_ERR(resp))
25549815c7cfSMichael Thalmeier return PTR_ERR(resp);
25559815c7cfSMichael Thalmeier
25569815c7cfSMichael Thalmeier dev_kfree_skb(resp);
25579815c7cfSMichael Thalmeier
25589815c7cfSMichael Thalmeier return 0;
25599815c7cfSMichael Thalmeier }
25609815c7cfSMichael Thalmeier
pn533_rf_field(struct nfc_dev * nfc_dev,u8 rf)25619815c7cfSMichael Thalmeier static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf)
25629815c7cfSMichael Thalmeier {
25639815c7cfSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
25649815c7cfSMichael Thalmeier u8 rf_field = !!rf;
25659815c7cfSMichael Thalmeier int rc;
25669815c7cfSMichael Thalmeier
25679815c7cfSMichael Thalmeier rf_field |= PN533_CFGITEM_RF_FIELD_AUTO_RFCA;
25689815c7cfSMichael Thalmeier
25699815c7cfSMichael Thalmeier rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD,
25709815c7cfSMichael Thalmeier (u8 *)&rf_field, 1);
25719815c7cfSMichael Thalmeier if (rc) {
25729815c7cfSMichael Thalmeier nfc_err(dev->dev, "Error on setting RF field\n");
25739815c7cfSMichael Thalmeier return rc;
25749815c7cfSMichael Thalmeier }
25759815c7cfSMichael Thalmeier
2576a115d24aSwengjianfeng return 0;
25779815c7cfSMichael Thalmeier }
25789815c7cfSMichael Thalmeier
pn532_sam_configuration(struct nfc_dev * nfc_dev)2579dd7bedcdSMichael Thalmeier static int pn532_sam_configuration(struct nfc_dev *nfc_dev)
2580dd7bedcdSMichael Thalmeier {
2581dd7bedcdSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
2582dd7bedcdSMichael Thalmeier struct sk_buff *skb;
2583dd7bedcdSMichael Thalmeier struct sk_buff *resp;
2584dd7bedcdSMichael Thalmeier
2585dd7bedcdSMichael Thalmeier skb = pn533_alloc_skb(dev, 1);
2586dd7bedcdSMichael Thalmeier if (!skb)
2587dd7bedcdSMichael Thalmeier return -ENOMEM;
2588dd7bedcdSMichael Thalmeier
2589634fef61SJohannes Berg skb_put_u8(skb, 0x01);
2590dd7bedcdSMichael Thalmeier
2591dd7bedcdSMichael Thalmeier resp = pn533_send_cmd_sync(dev, PN533_CMD_SAM_CONFIGURATION, skb);
2592dd7bedcdSMichael Thalmeier if (IS_ERR(resp))
2593dd7bedcdSMichael Thalmeier return PTR_ERR(resp);
2594dd7bedcdSMichael Thalmeier
2595dd7bedcdSMichael Thalmeier dev_kfree_skb(resp);
2596dd7bedcdSMichael Thalmeier return 0;
2597dd7bedcdSMichael Thalmeier }
2598dd7bedcdSMichael Thalmeier
pn533_dev_up(struct nfc_dev * nfc_dev)25999815c7cfSMichael Thalmeier static int pn533_dev_up(struct nfc_dev *nfc_dev)
26009815c7cfSMichael Thalmeier {
2601dd7bedcdSMichael Thalmeier struct pn533 *dev = nfc_get_drvdata(nfc_dev);
26021e37be7dSLars Poeschel int rc;
2603dd7bedcdSMichael Thalmeier
26041e37be7dSLars Poeschel if (dev->phy_ops->dev_up) {
26051e37be7dSLars Poeschel rc = dev->phy_ops->dev_up(dev);
26061e37be7dSLars Poeschel if (rc)
26071e37be7dSLars Poeschel return rc;
26081e37be7dSLars Poeschel }
26090bf2840cSLars Poeschel
2610c64b875fSLars Poeschel if ((dev->device_type == PN533_DEVICE_PN532) ||
2611c64b875fSLars Poeschel (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL)) {
26121e37be7dSLars Poeschel rc = pn532_sam_configuration(nfc_dev);
2613dd7bedcdSMichael Thalmeier
2614dd7bedcdSMichael Thalmeier if (rc)
2615dd7bedcdSMichael Thalmeier return rc;
2616dd7bedcdSMichael Thalmeier }
2617dd7bedcdSMichael Thalmeier
26189815c7cfSMichael Thalmeier return pn533_rf_field(nfc_dev, 1);
26199815c7cfSMichael Thalmeier }
26209815c7cfSMichael Thalmeier
pn533_dev_down(struct nfc_dev * nfc_dev)26219815c7cfSMichael Thalmeier static int pn533_dev_down(struct nfc_dev *nfc_dev)
26229815c7cfSMichael Thalmeier {
26230bf2840cSLars Poeschel struct pn533 *dev = nfc_get_drvdata(nfc_dev);
26240bf2840cSLars Poeschel int ret;
26250bf2840cSLars Poeschel
26260bf2840cSLars Poeschel ret = pn533_rf_field(nfc_dev, 0);
26270bf2840cSLars Poeschel if (dev->phy_ops->dev_down && !ret)
26281e37be7dSLars Poeschel ret = dev->phy_ops->dev_down(dev);
26290bf2840cSLars Poeschel
26300bf2840cSLars Poeschel return ret;
26319815c7cfSMichael Thalmeier }
26329815c7cfSMichael Thalmeier
2633f6c802a7SKrzysztof Kozlowski static const struct nfc_ops pn533_nfc_ops = {
26349815c7cfSMichael Thalmeier .dev_up = pn533_dev_up,
26359815c7cfSMichael Thalmeier .dev_down = pn533_dev_down,
26369815c7cfSMichael Thalmeier .dep_link_up = pn533_dep_link_up,
26379815c7cfSMichael Thalmeier .dep_link_down = pn533_dep_link_down,
26389815c7cfSMichael Thalmeier .start_poll = pn533_start_poll,
26399815c7cfSMichael Thalmeier .stop_poll = pn533_stop_poll,
26409815c7cfSMichael Thalmeier .activate_target = pn533_activate_target,
26419815c7cfSMichael Thalmeier .deactivate_target = pn533_deactivate_target,
26429815c7cfSMichael Thalmeier .im_transceive = pn533_transceive,
26439815c7cfSMichael Thalmeier .tm_send = pn533_tm_send,
26449815c7cfSMichael Thalmeier };
26459815c7cfSMichael Thalmeier
pn533_setup(struct pn533 * dev)26469815c7cfSMichael Thalmeier static int pn533_setup(struct pn533 *dev)
26479815c7cfSMichael Thalmeier {
26489815c7cfSMichael Thalmeier struct pn533_config_max_retries max_retries;
26499815c7cfSMichael Thalmeier struct pn533_config_timing timing;
26509815c7cfSMichael Thalmeier u8 pasori_cfg[3] = {0x08, 0x01, 0x08};
26519815c7cfSMichael Thalmeier int rc;
26529815c7cfSMichael Thalmeier
26539815c7cfSMichael Thalmeier switch (dev->device_type) {
26549815c7cfSMichael Thalmeier case PN533_DEVICE_STD:
26559815c7cfSMichael Thalmeier case PN533_DEVICE_PASORI:
26569815c7cfSMichael Thalmeier case PN533_DEVICE_ACR122U:
2657dd7bedcdSMichael Thalmeier case PN533_DEVICE_PN532:
2658c64b875fSLars Poeschel case PN533_DEVICE_PN532_AUTOPOLL:
26599815c7cfSMichael Thalmeier max_retries.mx_rty_atr = 0x2;
26609815c7cfSMichael Thalmeier max_retries.mx_rty_psl = 0x1;
26619815c7cfSMichael Thalmeier max_retries.mx_rty_passive_act =
26629815c7cfSMichael Thalmeier PN533_CONFIG_MAX_RETRIES_NO_RETRY;
26639815c7cfSMichael Thalmeier
26649815c7cfSMichael Thalmeier timing.rfu = PN533_CONFIG_TIMING_102;
26659815c7cfSMichael Thalmeier timing.atr_res_timeout = PN533_CONFIG_TIMING_102;
26669815c7cfSMichael Thalmeier timing.dep_timeout = PN533_CONFIG_TIMING_204;
26679815c7cfSMichael Thalmeier
26689815c7cfSMichael Thalmeier break;
26699815c7cfSMichael Thalmeier
26709815c7cfSMichael Thalmeier default:
26719815c7cfSMichael Thalmeier nfc_err(dev->dev, "Unknown device type %d\n",
26729815c7cfSMichael Thalmeier dev->device_type);
26739815c7cfSMichael Thalmeier return -EINVAL;
26749815c7cfSMichael Thalmeier }
26759815c7cfSMichael Thalmeier
26769815c7cfSMichael Thalmeier rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
26779815c7cfSMichael Thalmeier (u8 *)&max_retries, sizeof(max_retries));
26789815c7cfSMichael Thalmeier if (rc) {
26799815c7cfSMichael Thalmeier nfc_err(dev->dev,
26809815c7cfSMichael Thalmeier "Error on setting MAX_RETRIES config\n");
26819815c7cfSMichael Thalmeier return rc;
26829815c7cfSMichael Thalmeier }
26839815c7cfSMichael Thalmeier
26849815c7cfSMichael Thalmeier
26859815c7cfSMichael Thalmeier rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
26869815c7cfSMichael Thalmeier (u8 *)&timing, sizeof(timing));
26879815c7cfSMichael Thalmeier if (rc) {
26889815c7cfSMichael Thalmeier nfc_err(dev->dev, "Error on setting RF timings\n");
26899815c7cfSMichael Thalmeier return rc;
26909815c7cfSMichael Thalmeier }
26919815c7cfSMichael Thalmeier
26929815c7cfSMichael Thalmeier switch (dev->device_type) {
26939815c7cfSMichael Thalmeier case PN533_DEVICE_STD:
2694dd7bedcdSMichael Thalmeier case PN533_DEVICE_PN532:
2695c64b875fSLars Poeschel case PN533_DEVICE_PN532_AUTOPOLL:
26969815c7cfSMichael Thalmeier break;
26979815c7cfSMichael Thalmeier
26989815c7cfSMichael Thalmeier case PN533_DEVICE_PASORI:
26999815c7cfSMichael Thalmeier pn533_pasori_fw_reset(dev);
27009815c7cfSMichael Thalmeier
27019815c7cfSMichael Thalmeier rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI,
27029815c7cfSMichael Thalmeier pasori_cfg, 3);
27039815c7cfSMichael Thalmeier if (rc) {
27049815c7cfSMichael Thalmeier nfc_err(dev->dev,
27059815c7cfSMichael Thalmeier "Error while settings PASORI config\n");
27069815c7cfSMichael Thalmeier return rc;
27079815c7cfSMichael Thalmeier }
27089815c7cfSMichael Thalmeier
27099815c7cfSMichael Thalmeier pn533_pasori_fw_reset(dev);
27109815c7cfSMichael Thalmeier
27119815c7cfSMichael Thalmeier break;
27129815c7cfSMichael Thalmeier }
27139815c7cfSMichael Thalmeier
27149815c7cfSMichael Thalmeier return 0;
27159815c7cfSMichael Thalmeier }
27169815c7cfSMichael Thalmeier
pn533_finalize_setup(struct pn533 * dev)271732ecc75dSAndrey Rusalin int pn533_finalize_setup(struct pn533 *dev)
271832ecc75dSAndrey Rusalin {
271932ecc75dSAndrey Rusalin
272032ecc75dSAndrey Rusalin struct pn533_fw_version fw_ver;
272132ecc75dSAndrey Rusalin int rc;
272232ecc75dSAndrey Rusalin
272332ecc75dSAndrey Rusalin memset(&fw_ver, 0, sizeof(fw_ver));
272432ecc75dSAndrey Rusalin
272532ecc75dSAndrey Rusalin rc = pn533_get_firmware_version(dev, &fw_ver);
272632ecc75dSAndrey Rusalin if (rc) {
272732ecc75dSAndrey Rusalin nfc_err(dev->dev, "Unable to get FW version\n");
272832ecc75dSAndrey Rusalin return rc;
272932ecc75dSAndrey Rusalin }
273032ecc75dSAndrey Rusalin
273132ecc75dSAndrey Rusalin nfc_info(dev->dev, "NXP PN5%02X firmware ver %d.%d now attached\n",
273232ecc75dSAndrey Rusalin fw_ver.ic, fw_ver.ver, fw_ver.rev);
273332ecc75dSAndrey Rusalin
273432ecc75dSAndrey Rusalin rc = pn533_setup(dev);
273532ecc75dSAndrey Rusalin if (rc)
273632ecc75dSAndrey Rusalin return rc;
273732ecc75dSAndrey Rusalin
273832ecc75dSAndrey Rusalin return 0;
273932ecc75dSAndrey Rusalin }
274032ecc75dSAndrey Rusalin EXPORT_SYMBOL_GPL(pn533_finalize_setup);
274132ecc75dSAndrey Rusalin
pn53x_common_init(u32 device_type,enum pn533_protocol_type protocol_type,void * phy,const struct pn533_phy_ops * phy_ops,struct pn533_frame_ops * fops,struct device * dev)2742843cc92eSLars Poeschel struct pn533 *pn53x_common_init(u32 device_type,
27439815c7cfSMichael Thalmeier enum pn533_protocol_type protocol_type,
27449815c7cfSMichael Thalmeier void *phy,
2745bc642817SRikard Falkeborn const struct pn533_phy_ops *phy_ops,
27469815c7cfSMichael Thalmeier struct pn533_frame_ops *fops,
2747843cc92eSLars Poeschel struct device *dev)
27489815c7cfSMichael Thalmeier {
27499815c7cfSMichael Thalmeier struct pn533 *priv;
27509815c7cfSMichael Thalmeier
27519815c7cfSMichael Thalmeier priv = kzalloc(sizeof(*priv), GFP_KERNEL);
27529815c7cfSMichael Thalmeier if (!priv)
27539815c7cfSMichael Thalmeier return ERR_PTR(-ENOMEM);
27549815c7cfSMichael Thalmeier
27559815c7cfSMichael Thalmeier priv->phy = phy;
27569815c7cfSMichael Thalmeier priv->phy_ops = phy_ops;
27579815c7cfSMichael Thalmeier priv->dev = dev;
27589815c7cfSMichael Thalmeier if (fops != NULL)
27599815c7cfSMichael Thalmeier priv->ops = fops;
27609815c7cfSMichael Thalmeier else
27619815c7cfSMichael Thalmeier priv->ops = &pn533_std_frame_ops;
27629815c7cfSMichael Thalmeier
27639815c7cfSMichael Thalmeier priv->protocol_type = protocol_type;
27649815c7cfSMichael Thalmeier priv->device_type = device_type;
27659815c7cfSMichael Thalmeier
27669815c7cfSMichael Thalmeier mutex_init(&priv->cmd_lock);
27679815c7cfSMichael Thalmeier
27689815c7cfSMichael Thalmeier INIT_WORK(&priv->cmd_work, pn533_wq_cmd);
27699815c7cfSMichael Thalmeier INIT_WORK(&priv->cmd_complete_work, pn533_wq_cmd_complete);
27709815c7cfSMichael Thalmeier INIT_WORK(&priv->mi_rx_work, pn533_wq_mi_recv);
27719815c7cfSMichael Thalmeier INIT_WORK(&priv->mi_tx_work, pn533_wq_mi_send);
27729815c7cfSMichael Thalmeier INIT_WORK(&priv->tg_work, pn533_wq_tg_get_data);
27739815c7cfSMichael Thalmeier INIT_WORK(&priv->mi_tm_rx_work, pn533_wq_tm_mi_recv);
27749815c7cfSMichael Thalmeier INIT_WORK(&priv->mi_tm_tx_work, pn533_wq_tm_mi_send);
27759815c7cfSMichael Thalmeier INIT_DELAYED_WORK(&priv->poll_work, pn533_wq_poll);
27769815c7cfSMichael Thalmeier INIT_WORK(&priv->rf_work, pn533_wq_rf);
27779815c7cfSMichael Thalmeier priv->wq = alloc_ordered_workqueue("pn533", 0);
27789815c7cfSMichael Thalmeier if (priv->wq == NULL)
27799815c7cfSMichael Thalmeier goto error;
27809815c7cfSMichael Thalmeier
2781e99e88a9SKees Cook timer_setup(&priv->listen_timer, pn533_listen_mode_timer, 0);
27829815c7cfSMichael Thalmeier
27839815c7cfSMichael Thalmeier skb_queue_head_init(&priv->resp_q);
27849815c7cfSMichael Thalmeier skb_queue_head_init(&priv->fragment_skb);
27859815c7cfSMichael Thalmeier
27869815c7cfSMichael Thalmeier INIT_LIST_HEAD(&priv->cmd_queue);
27879815c7cfSMichael Thalmeier return priv;
27889815c7cfSMichael Thalmeier
27899815c7cfSMichael Thalmeier error:
27909815c7cfSMichael Thalmeier kfree(priv);
2791a115d24aSwengjianfeng return ERR_PTR(-ENOMEM);
27929815c7cfSMichael Thalmeier }
2793843cc92eSLars Poeschel EXPORT_SYMBOL_GPL(pn53x_common_init);
27949815c7cfSMichael Thalmeier
pn53x_common_clean(struct pn533 * priv)2795843cc92eSLars Poeschel void pn53x_common_clean(struct pn533 *priv)
27969815c7cfSMichael Thalmeier {
27979815c7cfSMichael Thalmeier struct pn533_cmd *cmd, *n;
27989815c7cfSMichael Thalmeier
2799b8cedb70SLin Ma /* delete the timer before cleanup the worker */
2800292a089dSSteven Rostedt (Google) timer_shutdown_sync(&priv->listen_timer);
2801b8cedb70SLin Ma
28029815c7cfSMichael Thalmeier flush_delayed_work(&priv->poll_work);
28039815c7cfSMichael Thalmeier destroy_workqueue(priv->wq);
28049815c7cfSMichael Thalmeier
28059815c7cfSMichael Thalmeier skb_queue_purge(&priv->resp_q);
28069815c7cfSMichael Thalmeier
28079815c7cfSMichael Thalmeier list_for_each_entry_safe(cmd, n, &priv->cmd_queue, queue) {
28089815c7cfSMichael Thalmeier list_del(&cmd->queue);
28099815c7cfSMichael Thalmeier kfree(cmd);
28109815c7cfSMichael Thalmeier }
28119815c7cfSMichael Thalmeier
28129815c7cfSMichael Thalmeier kfree(priv);
28139815c7cfSMichael Thalmeier }
2814843cc92eSLars Poeschel EXPORT_SYMBOL_GPL(pn53x_common_clean);
28159815c7cfSMichael Thalmeier
pn532_i2c_nfc_alloc(struct pn533 * priv,u32 protocols,struct device * parent)2816843cc92eSLars Poeschel int pn532_i2c_nfc_alloc(struct pn533 *priv, u32 protocols,
2817843cc92eSLars Poeschel struct device *parent)
2818843cc92eSLars Poeschel {
2819843cc92eSLars Poeschel priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
2820843cc92eSLars Poeschel priv->ops->tx_header_len +
2821843cc92eSLars Poeschel PN533_CMD_DATAEXCH_HEAD_LEN,
2822843cc92eSLars Poeschel priv->ops->tx_tail_len);
2823843cc92eSLars Poeschel if (!priv->nfc_dev)
2824843cc92eSLars Poeschel return -ENOMEM;
2825843cc92eSLars Poeschel
2826843cc92eSLars Poeschel nfc_set_parent_dev(priv->nfc_dev, parent);
2827843cc92eSLars Poeschel nfc_set_drvdata(priv->nfc_dev, priv);
2828843cc92eSLars Poeschel return 0;
2829843cc92eSLars Poeschel }
2830843cc92eSLars Poeschel EXPORT_SYMBOL_GPL(pn532_i2c_nfc_alloc);
2831843cc92eSLars Poeschel
pn53x_register_nfc(struct pn533 * priv,u32 protocols,struct device * parent)2832843cc92eSLars Poeschel int pn53x_register_nfc(struct pn533 *priv, u32 protocols,
2833843cc92eSLars Poeschel struct device *parent)
2834843cc92eSLars Poeschel {
2835843cc92eSLars Poeschel int rc;
2836843cc92eSLars Poeschel
2837843cc92eSLars Poeschel rc = pn532_i2c_nfc_alloc(priv, protocols, parent);
2838843cc92eSLars Poeschel if (rc)
2839843cc92eSLars Poeschel return rc;
2840843cc92eSLars Poeschel
2841843cc92eSLars Poeschel rc = nfc_register_device(priv->nfc_dev);
2842843cc92eSLars Poeschel if (rc)
2843843cc92eSLars Poeschel nfc_free_device(priv->nfc_dev);
2844843cc92eSLars Poeschel
2845843cc92eSLars Poeschel return rc;
2846843cc92eSLars Poeschel }
2847843cc92eSLars Poeschel EXPORT_SYMBOL_GPL(pn53x_register_nfc);
2848843cc92eSLars Poeschel
pn53x_unregister_nfc(struct pn533 * priv)2849843cc92eSLars Poeschel void pn53x_unregister_nfc(struct pn533 *priv)
2850843cc92eSLars Poeschel {
2851843cc92eSLars Poeschel nfc_unregister_device(priv->nfc_dev);
2852843cc92eSLars Poeschel nfc_free_device(priv->nfc_dev);
2853843cc92eSLars Poeschel }
2854843cc92eSLars Poeschel EXPORT_SYMBOL_GPL(pn53x_unregister_nfc);
28559815c7cfSMichael Thalmeier
28569815c7cfSMichael Thalmeier MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
28579815c7cfSMichael Thalmeier MODULE_AUTHOR("Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
28589815c7cfSMichael Thalmeier MODULE_AUTHOR("Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>");
28599815c7cfSMichael Thalmeier MODULE_DESCRIPTION("PN533 driver ver " VERSION);
28609815c7cfSMichael Thalmeier MODULE_VERSION(VERSION);
28619815c7cfSMichael Thalmeier MODULE_LICENSE("GPL");
2862