2019-05-19 16:51:43 +03:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2011-07-02 02:31:37 +04:00
|
|
|
/*
|
2016-03-25 17:46:53 +03:00
|
|
|
* Driver for NXP PN533 NFC Chip - core functions
|
|
|
|
*
|
2011-07-02 02:31:37 +04:00
|
|
|
* Copyright (C) 2011 Instituto Nokia de Tecnologia
|
2013-04-03 10:02:01 +04:00
|
|
|
* Copyright (C) 2012-2013 Tieto Poland
|
2011-07-02 02:31:37 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/nfc.h>
|
|
|
|
#include <linux/netdevice.h>
|
2011-09-18 12:19:34 +04:00
|
|
|
#include <net/nfc/nfc.h>
|
2016-03-25 17:46:53 +03:00
|
|
|
#include "pn533.h"
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
#define VERSION "0.3"
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
/* How much time we spend listening for initiators */
|
|
|
|
#define PN533_LISTEN_TIME 2
|
2013-07-03 16:50:36 +04:00
|
|
|
/* Delay between each poll frame (ms) */
|
|
|
|
#define PN533_POLL_INTERVAL 10
|
2012-05-30 19:20:25 +04:00
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
/* structs for pn533 commands */
|
|
|
|
|
|
|
|
/* PN533_CMD_GET_FIRMWARE_VERSION */
|
|
|
|
struct pn533_fw_version {
|
|
|
|
u8 ic;
|
|
|
|
u8 ver;
|
|
|
|
u8 rev;
|
|
|
|
u8 support;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* PN533_CMD_RF_CONFIGURATION */
|
2013-04-11 13:45:41 +04:00
|
|
|
#define PN533_CFGITEM_RF_FIELD 0x01
|
|
|
|
#define PN533_CFGITEM_TIMING 0x02
|
2011-07-02 02:31:37 +04:00
|
|
|
#define PN533_CFGITEM_MAX_RETRIES 0x05
|
2013-04-11 13:45:41 +04:00
|
|
|
#define PN533_CFGITEM_PASORI 0x82
|
|
|
|
|
2013-07-01 19:26:58 +04:00
|
|
|
#define PN533_CFGITEM_RF_FIELD_AUTO_RFCA 0x2
|
|
|
|
#define PN533_CFGITEM_RF_FIELD_ON 0x1
|
|
|
|
#define PN533_CFGITEM_RF_FIELD_OFF 0x0
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-05-29 23:34:08 +04:00
|
|
|
#define PN533_CONFIG_TIMING_102 0xb
|
|
|
|
#define PN533_CONFIG_TIMING_204 0xc
|
|
|
|
#define PN533_CONFIG_TIMING_409 0xd
|
|
|
|
#define PN533_CONFIG_TIMING_819 0xe
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
#define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00
|
|
|
|
#define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF
|
|
|
|
|
|
|
|
struct pn533_config_max_retries {
|
|
|
|
u8 mx_rty_atr;
|
|
|
|
u8 mx_rty_psl;
|
|
|
|
u8 mx_rty_passive_act;
|
|
|
|
} __packed;
|
|
|
|
|
2012-05-29 23:34:08 +04:00
|
|
|
struct pn533_config_timing {
|
|
|
|
u8 rfu;
|
|
|
|
u8 atr_res_timeout;
|
|
|
|
u8 dep_timeout;
|
|
|
|
} __packed;
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
/* PN533_CMD_IN_LIST_PASSIVE_TARGET */
|
|
|
|
|
|
|
|
/* felica commands opcode */
|
|
|
|
#define PN533_FELICA_OPC_SENSF_REQ 0
|
|
|
|
#define PN533_FELICA_OPC_SENSF_RES 1
|
|
|
|
/* felica SENSF_REQ parameters */
|
|
|
|
#define PN533_FELICA_SENSF_SC_ALL 0xFFFF
|
|
|
|
#define PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE 0
|
|
|
|
#define PN533_FELICA_SENSF_RC_SYSTEM_CODE 1
|
|
|
|
#define PN533_FELICA_SENSF_RC_ADVANCED_PROTOCOL 2
|
|
|
|
|
|
|
|
/* type B initiator_data values */
|
|
|
|
#define PN533_TYPE_B_AFI_ALL_FAMILIES 0
|
|
|
|
#define PN533_TYPE_B_POLL_METHOD_TIMESLOT 0
|
|
|
|
#define PN533_TYPE_B_POLL_METHOD_PROBABILISTIC 1
|
|
|
|
|
|
|
|
union pn533_cmd_poll_initdata {
|
|
|
|
struct {
|
|
|
|
u8 afi;
|
|
|
|
u8 polling_method;
|
|
|
|
} __packed type_b;
|
|
|
|
struct {
|
|
|
|
u8 opcode;
|
|
|
|
__be16 sc;
|
|
|
|
u8 rc;
|
|
|
|
u8 tsn;
|
|
|
|
} __packed felica;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct pn533_poll_modulations {
|
|
|
|
struct {
|
|
|
|
u8 maxtg;
|
|
|
|
u8 brty;
|
|
|
|
union pn533_cmd_poll_initdata initiator_data;
|
|
|
|
} __packed data;
|
|
|
|
u8 len;
|
|
|
|
};
|
|
|
|
|
2013-01-16 18:51:51 +04:00
|
|
|
static const struct pn533_poll_modulations poll_mod[] = {
|
2011-07-02 02:31:37 +04:00
|
|
|
[PN533_POLL_MOD_106KBPS_A] = {
|
|
|
|
.data = {
|
|
|
|
.maxtg = 1,
|
|
|
|
.brty = 0,
|
|
|
|
},
|
|
|
|
.len = 2,
|
|
|
|
},
|
|
|
|
[PN533_POLL_MOD_212KBPS_FELICA] = {
|
|
|
|
.data = {
|
|
|
|
.maxtg = 1,
|
|
|
|
.brty = 1,
|
|
|
|
.initiator_data.felica = {
|
|
|
|
.opcode = PN533_FELICA_OPC_SENSF_REQ,
|
|
|
|
.sc = PN533_FELICA_SENSF_SC_ALL,
|
2013-06-28 17:43:19 +04:00
|
|
|
.rc = PN533_FELICA_SENSF_RC_SYSTEM_CODE,
|
2013-05-27 16:59:40 +04:00
|
|
|
.tsn = 0x03,
|
2011-07-02 02:31:37 +04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
.len = 7,
|
|
|
|
},
|
|
|
|
[PN533_POLL_MOD_424KBPS_FELICA] = {
|
|
|
|
.data = {
|
|
|
|
.maxtg = 1,
|
|
|
|
.brty = 2,
|
|
|
|
.initiator_data.felica = {
|
|
|
|
.opcode = PN533_FELICA_OPC_SENSF_REQ,
|
|
|
|
.sc = PN533_FELICA_SENSF_SC_ALL,
|
2013-06-28 17:43:19 +04:00
|
|
|
.rc = PN533_FELICA_SENSF_RC_SYSTEM_CODE,
|
2013-05-27 16:59:40 +04:00
|
|
|
.tsn = 0x03,
|
2011-07-02 02:31:37 +04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
.len = 7,
|
|
|
|
},
|
|
|
|
[PN533_POLL_MOD_106KBPS_JEWEL] = {
|
|
|
|
.data = {
|
|
|
|
.maxtg = 1,
|
|
|
|
.brty = 4,
|
|
|
|
},
|
|
|
|
.len = 2,
|
|
|
|
},
|
|
|
|
[PN533_POLL_MOD_847KBPS_B] = {
|
|
|
|
.data = {
|
|
|
|
.maxtg = 1,
|
|
|
|
.brty = 8,
|
|
|
|
.initiator_data.type_b = {
|
|
|
|
.afi = PN533_TYPE_B_AFI_ALL_FAMILIES,
|
|
|
|
.polling_method =
|
|
|
|
PN533_TYPE_B_POLL_METHOD_TIMESLOT,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
.len = 3,
|
|
|
|
},
|
2012-05-30 19:20:25 +04:00
|
|
|
[PN533_LISTEN_MOD] = {
|
|
|
|
.len = 0,
|
|
|
|
},
|
2011-07-02 02:31:37 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
/* PN533_CMD_IN_ATR */
|
|
|
|
|
|
|
|
struct pn533_cmd_activate_response {
|
|
|
|
u8 status;
|
|
|
|
u8 nfcid3t[10];
|
|
|
|
u8 didt;
|
|
|
|
u8 bst;
|
|
|
|
u8 brt;
|
|
|
|
u8 to;
|
|
|
|
u8 ppt;
|
|
|
|
/* optional */
|
|
|
|
u8 gt[];
|
|
|
|
} __packed;
|
|
|
|
|
2011-12-14 19:43:11 +04:00
|
|
|
struct pn533_cmd_jump_dep_response {
|
|
|
|
u8 status;
|
|
|
|
u8 tg;
|
|
|
|
u8 nfcid3t[10];
|
|
|
|
u8 didt;
|
|
|
|
u8 bst;
|
|
|
|
u8 brt;
|
|
|
|
u8 to;
|
|
|
|
u8 ppt;
|
|
|
|
/* optional */
|
|
|
|
u8 gt[];
|
|
|
|
} __packed;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2019-10-29 17:47:43 +03:00
|
|
|
struct pn532_autopoll_resp {
|
|
|
|
u8 type;
|
|
|
|
u8 ln;
|
|
|
|
u8 tg;
|
|
|
|
u8 tgdata[];
|
|
|
|
};
|
|
|
|
|
|
|
|
/* PN532_CMD_IN_AUTOPOLL */
|
|
|
|
#define PN532_AUTOPOLL_POLLNR_INFINITE 0xff
|
|
|
|
#define PN532_AUTOPOLL_PERIOD 0x03 /* in units of 150 ms */
|
|
|
|
|
|
|
|
#define PN532_AUTOPOLL_TYPE_GENERIC_106 0x00
|
|
|
|
#define PN532_AUTOPOLL_TYPE_GENERIC_212 0x01
|
|
|
|
#define PN532_AUTOPOLL_TYPE_GENERIC_424 0x02
|
|
|
|
#define PN532_AUTOPOLL_TYPE_JEWEL 0x04
|
|
|
|
#define PN532_AUTOPOLL_TYPE_MIFARE 0x10
|
|
|
|
#define PN532_AUTOPOLL_TYPE_FELICA212 0x11
|
|
|
|
#define PN532_AUTOPOLL_TYPE_FELICA424 0x12
|
|
|
|
#define PN532_AUTOPOLL_TYPE_ISOA 0x20
|
|
|
|
#define PN532_AUTOPOLL_TYPE_ISOB 0x23
|
|
|
|
#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106 0x40
|
|
|
|
#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212 0x41
|
|
|
|
#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424 0x42
|
|
|
|
#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106 0x80
|
|
|
|
#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_212 0x81
|
|
|
|
#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_424 0x82
|
2012-05-31 01:54:55 +04:00
|
|
|
|
|
|
|
/* PN533_TG_INIT_AS_TARGET */
|
|
|
|
#define PN533_INIT_TARGET_PASSIVE 0x1
|
|
|
|
#define PN533_INIT_TARGET_DEP 0x2
|
|
|
|
|
2012-06-01 15:21:13 +04:00
|
|
|
#define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3
|
|
|
|
#define PN533_INIT_TARGET_RESP_ACTIVE 0x1
|
|
|
|
#define PN533_INIT_TARGET_RESP_DEP 0x4
|
|
|
|
|
2013-06-13 17:43:27 +04:00
|
|
|
/* The rule: value(high byte) + value(low byte) + checksum = 0 */
|
|
|
|
static inline u8 pn533_ext_checksum(u16 value)
|
|
|
|
{
|
|
|
|
return ~(u8)(((value & 0xFF00) >> 8) + (u8)(value & 0xFF)) + 1;
|
|
|
|
}
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
/* The rule: value + checksum = 0 */
|
2013-04-03 10:01:58 +04:00
|
|
|
static inline u8 pn533_std_checksum(u8 value)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
|
|
|
return ~value + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The rule: sum(data elements) + checksum = 0 */
|
2013-04-03 10:01:58 +04:00
|
|
|
static u8 pn533_std_data_checksum(u8 *data, int datalen)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
|
|
|
u8 sum = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < datalen; i++)
|
|
|
|
sum += data[i];
|
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
return pn533_std_checksum(sum);
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
static void pn533_std_tx_frame_init(void *_frame, u8 cmd_code)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
2013-04-03 10:01:58 +04:00
|
|
|
struct pn533_std_frame *frame = _frame;
|
2012-12-10 17:43:01 +04:00
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
frame->preamble = 0;
|
2013-04-03 10:01:58 +04:00
|
|
|
frame->start_frame = cpu_to_be16(PN533_STD_FRAME_SOF);
|
|
|
|
PN533_STD_FRAME_IDENTIFIER(frame) = PN533_STD_FRAME_DIR_OUT;
|
2013-06-13 17:43:27 +04:00
|
|
|
PN533_FRAME_CMD(frame) = cmd_code;
|
2011-07-02 02:31:37 +04:00
|
|
|
frame->datalen = 2;
|
|
|
|
}
|
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
static void pn533_std_tx_frame_finish(void *_frame)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
2013-04-03 10:01:58 +04:00
|
|
|
struct pn533_std_frame *frame = _frame;
|
2012-12-10 17:43:01 +04:00
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
frame->datalen_checksum = pn533_std_checksum(frame->datalen);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
PN533_STD_FRAME_CHECKSUM(frame) =
|
|
|
|
pn533_std_data_checksum(frame->data, frame->datalen);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
PN533_STD_FRAME_POSTAMBLE(frame) = 0;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
static void pn533_std_tx_update_payload_len(void *_frame, int len)
|
2012-12-10 17:43:01 +04:00
|
|
|
{
|
2013-04-03 10:01:58 +04:00
|
|
|
struct pn533_std_frame *frame = _frame;
|
2012-12-10 17:43:01 +04:00
|
|
|
|
|
|
|
frame->datalen += len;
|
|
|
|
}
|
|
|
|
|
2013-06-13 17:43:29 +04:00
|
|
|
static bool pn533_std_rx_frame_is_valid(void *_frame, struct pn533 *dev)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
|
|
|
u8 checksum;
|
2013-06-13 17:43:27 +04:00
|
|
|
struct pn533_std_frame *stdf = _frame;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2013-06-13 17:43:27 +04:00
|
|
|
if (stdf->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
|
2011-07-02 02:31:37 +04:00
|
|
|
return false;
|
|
|
|
|
2013-06-13 17:43:27 +04:00
|
|
|
if (likely(!PN533_STD_IS_EXTENDED(stdf))) {
|
|
|
|
/* Standard frame code */
|
2013-06-13 17:43:29 +04:00
|
|
|
dev->ops->rx_header_len = PN533_STD_FRAME_HEADER_LEN;
|
2013-06-13 17:43:27 +04:00
|
|
|
|
|
|
|
checksum = pn533_std_checksum(stdf->datalen);
|
|
|
|
if (checksum != stdf->datalen_checksum)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
checksum = pn533_std_data_checksum(stdf->data, stdf->datalen);
|
|
|
|
if (checksum != PN533_STD_FRAME_CHECKSUM(stdf))
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
/* Extended */
|
|
|
|
struct pn533_ext_frame *eif = _frame;
|
|
|
|
|
2013-06-13 17:43:29 +04:00
|
|
|
dev->ops->rx_header_len = PN533_EXT_FRAME_HEADER_LEN;
|
|
|
|
|
2013-06-13 17:43:27 +04:00
|
|
|
checksum = pn533_ext_checksum(be16_to_cpu(eif->datalen));
|
|
|
|
if (checksum != eif->datalen_checksum)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* check data checksum */
|
|
|
|
checksum = pn533_std_data_checksum(eif->data,
|
|
|
|
be16_to_cpu(eif->datalen));
|
|
|
|
if (checksum != PN533_EXT_FRAME_CHECKSUM(eif))
|
|
|
|
return false;
|
|
|
|
}
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
bool pn533_rx_frame_is_ack(void *_frame)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
2016-03-25 17:46:53 +03:00
|
|
|
struct pn533_std_frame *frame = _frame;
|
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
|
2011-07-02 02:31:37 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (frame->datalen != 0 || frame->datalen_checksum != 0xFF)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2016-03-25 17:46:53 +03:00
|
|
|
EXPORT_SYMBOL_GPL(pn533_rx_frame_is_ack);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
static inline int pn533_std_rx_frame_size(void *frame)
|
2012-12-10 17:43:01 +04:00
|
|
|
{
|
2013-04-03 10:01:58 +04:00
|
|
|
struct pn533_std_frame *f = frame;
|
2012-12-10 17:43:01 +04:00
|
|
|
|
2013-06-13 17:43:27 +04:00
|
|
|
/* check for Extended Information frame */
|
|
|
|
if (PN533_STD_IS_EXTENDED(f)) {
|
|
|
|
struct pn533_ext_frame *eif = frame;
|
|
|
|
|
|
|
|
return sizeof(struct pn533_ext_frame)
|
|
|
|
+ be16_to_cpu(eif->datalen) + PN533_STD_FRAME_TAIL_LEN;
|
|
|
|
}
|
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
return sizeof(struct pn533_std_frame) + f->datalen +
|
|
|
|
PN533_STD_FRAME_TAIL_LEN;
|
2012-12-10 17:43:01 +04:00
|
|
|
}
|
|
|
|
|
2013-04-03 10:01:58 +04:00
|
|
|
static u8 pn533_std_get_cmd_code(void *frame)
|
2012-12-10 17:43:01 +04:00
|
|
|
{
|
2013-04-03 10:01:58 +04:00
|
|
|
struct pn533_std_frame *f = frame;
|
2013-06-13 17:43:27 +04:00
|
|
|
struct pn533_ext_frame *eif = frame;
|
2012-12-10 17:43:01 +04:00
|
|
|
|
2013-06-13 17:43:27 +04:00
|
|
|
if (PN533_STD_IS_EXTENDED(f))
|
|
|
|
return PN533_FRAME_CMD(eif);
|
|
|
|
else
|
|
|
|
return PN533_FRAME_CMD(f);
|
2012-12-10 17:43:01 +04:00
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame)
|
|
|
|
{
|
|
|
|
return (dev->ops->get_cmd_code(frame) ==
|
|
|
|
PN533_CMD_RESPONSE(dev->cmd->code));
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pn533_rx_frame_is_cmd_response);
|
|
|
|
|
|
|
|
|
2013-01-16 18:51:51 +04:00
|
|
|
static struct pn533_frame_ops pn533_std_frame_ops = {
|
2013-04-03 10:01:58 +04:00
|
|
|
.tx_frame_init = pn533_std_tx_frame_init,
|
|
|
|
.tx_frame_finish = pn533_std_tx_frame_finish,
|
|
|
|
.tx_update_payload_len = pn533_std_tx_update_payload_len,
|
|
|
|
.tx_header_len = PN533_STD_FRAME_HEADER_LEN,
|
|
|
|
.tx_tail_len = PN533_STD_FRAME_TAIL_LEN,
|
|
|
|
|
|
|
|
.rx_is_frame_valid = pn533_std_rx_frame_is_valid,
|
|
|
|
.rx_frame_size = pn533_std_rx_frame_size,
|
|
|
|
.rx_header_len = PN533_STD_FRAME_HEADER_LEN,
|
|
|
|
.rx_tail_len = PN533_STD_FRAME_TAIL_LEN,
|
|
|
|
|
|
|
|
.max_payload_len = PN533_STD_FRAME_MAX_PAYLOAD_LEN,
|
|
|
|
.get_cmd_code = pn533_std_get_cmd_code,
|
2012-12-10 17:43:01 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code,
|
|
|
|
struct sk_buff *skb)
|
2012-11-26 17:18:34 +04:00
|
|
|
{
|
|
|
|
/* payload is already there, just update datalen */
|
|
|
|
int payload_len = skb->len;
|
2012-12-10 17:43:01 +04:00
|
|
|
struct pn533_frame_ops *ops = dev->ops;
|
2012-11-26 17:18:34 +04:00
|
|
|
|
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb_push(skb, ops->tx_header_len);
|
|
|
|
skb_put(skb, ops->tx_tail_len);
|
2012-11-26 17:18:34 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
ops->tx_frame_init(skb->data, cmd_code);
|
|
|
|
ops->tx_update_payload_len(skb->data, payload_len);
|
|
|
|
ops->tx_frame_finish(skb->data);
|
2012-11-26 17:18:34 +04:00
|
|
|
}
|
|
|
|
|
2013-04-03 10:02:08 +04:00
|
|
|
static int pn533_send_async_complete(struct pn533 *dev)
|
2012-11-26 17:18:34 +04:00
|
|
|
{
|
2013-04-03 10:02:08 +04:00
|
|
|
struct pn533_cmd *cmd = dev->cmd;
|
2016-12-28 20:10:58 +03:00
|
|
|
struct sk_buff *resp;
|
|
|
|
int status, rc = 0;
|
2012-11-26 17:18:34 +04:00
|
|
|
|
2016-12-28 20:10:58 +03:00
|
|
|
if (!cmd) {
|
|
|
|
dev_dbg(dev->dev, "%s: cmd not set\n", __func__);
|
|
|
|
goto done;
|
|
|
|
}
|
2012-11-26 17:18:34 +04:00
|
|
|
|
2016-12-28 20:10:58 +03:00
|
|
|
dev_kfree_skb(cmd->req);
|
2012-11-26 17:18:34 +04:00
|
|
|
|
2016-12-28 20:10:58 +03:00
|
|
|
status = cmd->status;
|
|
|
|
resp = cmd->resp;
|
2012-11-26 17:18:34 +04:00
|
|
|
|
2012-12-10 17:42:59 +04:00
|
|
|
if (status < 0) {
|
2013-04-03 10:02:04 +04:00
|
|
|
rc = cmd->complete_cb(dev, cmd->complete_cb_context,
|
|
|
|
ERR_PTR(status));
|
2012-11-26 17:18:34 +04:00
|
|
|
dev_kfree_skb(resp);
|
2013-04-03 10:02:05 +04:00
|
|
|
goto done;
|
2012-11-26 17:18:34 +04:00
|
|
|
}
|
|
|
|
|
2016-12-28 20:10:58 +03:00
|
|
|
/* when no response is set we got interrupted */
|
|
|
|
if (!resp)
|
|
|
|
resp = ERR_PTR(-EINTR);
|
|
|
|
|
|
|
|
if (!IS_ERR(resp)) {
|
|
|
|
skb_pull(resp, dev->ops->rx_header_len);
|
|
|
|
skb_trim(resp, resp->len - dev->ops->rx_tail_len);
|
|
|
|
}
|
2012-11-26 17:18:34 +04:00
|
|
|
|
2013-04-03 10:02:04 +04:00
|
|
|
rc = cmd->complete_cb(dev, cmd->complete_cb_context, resp);
|
2012-11-26 17:18:34 +04:00
|
|
|
|
2013-04-03 10:02:05 +04:00
|
|
|
done:
|
2013-04-03 10:02:04 +04:00
|
|
|
kfree(cmd);
|
2013-04-03 10:02:05 +04:00
|
|
|
dev->cmd = NULL;
|
2012-11-26 17:18:34 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __pn533_send_async(struct pn533 *dev, u8 cmd_code,
|
2016-03-25 17:46:53 +03:00
|
|
|
struct sk_buff *req,
|
2012-11-26 17:18:34 +04:00
|
|
|
pn533_send_async_complete_t complete_cb,
|
|
|
|
void *complete_cb_context)
|
|
|
|
{
|
|
|
|
struct pn533_cmd *cmd;
|
|
|
|
int rc = 0;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "Sending command 0x%x\n", cmd_code);
|
2012-11-26 17:18:34 +04:00
|
|
|
|
2013-04-03 10:02:04 +04:00
|
|
|
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
|
|
|
if (!cmd)
|
2012-11-26 17:18:34 +04:00
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-04-03 10:02:06 +04:00
|
|
|
cmd->code = cmd_code;
|
2013-04-03 10:02:04 +04:00
|
|
|
cmd->req = req;
|
|
|
|
cmd->complete_cb = complete_cb;
|
|
|
|
cmd->complete_cb_context = complete_cb_context;
|
2012-11-26 17:18:34 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
pn533_build_cmd_frame(dev, cmd_code, req);
|
2012-11-26 17:18:34 +04:00
|
|
|
|
|
|
|
mutex_lock(&dev->cmd_lock);
|
|
|
|
|
|
|
|
if (!dev->cmd_pending) {
|
2016-12-28 20:10:58 +03:00
|
|
|
dev->cmd = cmd;
|
2016-03-25 17:46:53 +03:00
|
|
|
rc = dev->phy_ops->send_frame(dev, req);
|
2016-12-28 20:10:58 +03:00
|
|
|
if (rc) {
|
|
|
|
dev->cmd = NULL;
|
2012-11-26 17:18:34 +04:00
|
|
|
goto error;
|
2016-12-28 20:10:58 +03:00
|
|
|
}
|
2012-11-26 17:18:34 +04:00
|
|
|
|
|
|
|
dev->cmd_pending = 1;
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s Queueing command 0x%x\n",
|
2013-04-05 23:27:37 +04:00
|
|
|
__func__, cmd_code);
|
2012-11-26 17:18:34 +04:00
|
|
|
|
|
|
|
INIT_LIST_HEAD(&cmd->queue);
|
|
|
|
list_add_tail(&cmd->queue, &dev->cmd_queue);
|
|
|
|
|
|
|
|
goto unlock;
|
|
|
|
|
|
|
|
error:
|
2013-04-03 10:02:04 +04:00
|
|
|
kfree(cmd);
|
2012-11-26 17:18:34 +04:00
|
|
|
unlock:
|
|
|
|
mutex_unlock(&dev->cmd_lock);
|
|
|
|
return rc;
|
2012-11-26 17:18:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_send_data_async(struct pn533 *dev, u8 cmd_code,
|
|
|
|
struct sk_buff *req,
|
|
|
|
pn533_send_async_complete_t complete_cb,
|
|
|
|
void *complete_cb_context)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
rc = __pn533_send_async(dev, cmd_code, req, complete_cb,
|
2012-11-26 17:18:35 +04:00
|
|
|
complete_cb_context);
|
|
|
|
|
|
|
|
return rc;
|
2012-11-26 17:18:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code,
|
|
|
|
struct sk_buff *req,
|
|
|
|
pn533_send_async_complete_t complete_cb,
|
|
|
|
void *complete_cb_context)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
rc = __pn533_send_async(dev, cmd_code, req, complete_cb,
|
2012-12-10 17:43:01 +04:00
|
|
|
complete_cb_context);
|
2012-11-26 17:18:34 +04:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
/*
|
|
|
|
* pn533_send_cmd_direct_async
|
|
|
|
*
|
2017-02-28 01:29:39 +03:00
|
|
|
* The function sends a piority cmd directly to the chip omitting the cmd
|
2012-12-10 17:42:46 +04:00
|
|
|
* queue. It's intended to be used by chaining mechanism of received responses
|
|
|
|
* where the host has to request every single chunk of data before scheduling
|
|
|
|
* next cmd from the queue.
|
|
|
|
*/
|
|
|
|
static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code,
|
|
|
|
struct sk_buff *req,
|
|
|
|
pn533_send_async_complete_t complete_cb,
|
|
|
|
void *complete_cb_context)
|
|
|
|
{
|
2013-04-03 10:02:04 +04:00
|
|
|
struct pn533_cmd *cmd;
|
2012-12-10 17:42:46 +04:00
|
|
|
int rc;
|
|
|
|
|
2013-04-03 10:02:04 +04:00
|
|
|
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
2016-03-25 17:46:53 +03:00
|
|
|
if (!cmd)
|
2012-12-10 17:42:46 +04:00
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-04-03 10:02:06 +04:00
|
|
|
cmd->code = cmd_code;
|
2013-04-03 10:02:04 +04:00
|
|
|
cmd->req = req;
|
|
|
|
cmd->complete_cb = complete_cb;
|
|
|
|
cmd->complete_cb_context = complete_cb_context;
|
2012-12-10 17:42:46 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
pn533_build_cmd_frame(dev, cmd_code, req);
|
2012-12-10 17:42:46 +04:00
|
|
|
|
2016-12-28 20:10:58 +03:00
|
|
|
dev->cmd = cmd;
|
2016-03-25 17:46:53 +03:00
|
|
|
rc = dev->phy_ops->send_frame(dev, req);
|
2016-12-28 20:10:58 +03:00
|
|
|
if (rc < 0) {
|
|
|
|
dev->cmd = NULL;
|
2013-04-03 10:02:04 +04:00
|
|
|
kfree(cmd);
|
2016-12-28 20:10:58 +03:00
|
|
|
}
|
2012-12-10 17:42:46 +04:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2013-04-03 10:02:09 +04:00
|
|
|
static void pn533_wq_cmd_complete(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work);
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = pn533_send_async_complete(dev);
|
|
|
|
if (rc != -EINPROGRESS)
|
|
|
|
queue_work(dev->wq, &dev->cmd_work);
|
|
|
|
}
|
|
|
|
|
2012-08-18 01:47:54 +04:00
|
|
|
static void pn533_wq_cmd(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = container_of(work, struct pn533, cmd_work);
|
|
|
|
struct pn533_cmd *cmd;
|
2013-04-03 10:02:03 +04:00
|
|
|
int rc;
|
2012-08-18 01:47:54 +04:00
|
|
|
|
|
|
|
mutex_lock(&dev->cmd_lock);
|
|
|
|
|
|
|
|
if (list_empty(&dev->cmd_queue)) {
|
|
|
|
dev->cmd_pending = 0;
|
|
|
|
mutex_unlock(&dev->cmd_lock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue);
|
|
|
|
|
2012-10-25 19:29:45 +04:00
|
|
|
list_del(&cmd->queue);
|
|
|
|
|
2012-08-18 01:47:54 +04:00
|
|
|
mutex_unlock(&dev->cmd_lock);
|
|
|
|
|
2016-12-28 20:10:58 +03:00
|
|
|
dev->cmd = cmd;
|
2016-03-25 17:46:53 +03:00
|
|
|
rc = dev->phy_ops->send_frame(dev, cmd->req);
|
2013-04-03 10:02:03 +04:00
|
|
|
if (rc < 0) {
|
2016-12-28 20:10:58 +03:00
|
|
|
dev->cmd = NULL;
|
2013-04-03 10:02:03 +04:00
|
|
|
dev_kfree_skb(cmd->req);
|
2013-04-03 10:02:04 +04:00
|
|
|
kfree(cmd);
|
2013-04-03 10:02:05 +04:00
|
|
|
return;
|
2013-04-03 10:02:03 +04:00
|
|
|
}
|
2013-04-03 10:02:05 +04:00
|
|
|
|
2012-08-18 01:47:54 +04:00
|
|
|
}
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
struct pn533_sync_cmd_response {
|
2012-11-26 17:18:36 +04:00
|
|
|
struct sk_buff *resp;
|
2011-07-02 02:31:37 +04:00
|
|
|
struct completion done;
|
|
|
|
};
|
|
|
|
|
2012-11-26 17:18:36 +04:00
|
|
|
static int pn533_send_sync_complete(struct pn533 *dev, void *_arg,
|
|
|
|
struct sk_buff *resp)
|
|
|
|
{
|
|
|
|
struct pn533_sync_cmd_response *arg = _arg;
|
|
|
|
|
|
|
|
arg->resp = resp;
|
|
|
|
complete(&arg->done);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pn533_send_cmd_sync
|
|
|
|
*
|
|
|
|
* Please note the req parameter is freed inside the function to
|
|
|
|
* limit a number of return value interpretations by the caller.
|
|
|
|
*
|
|
|
|
* 1. negative in case of error during TX path -> req should be freed
|
|
|
|
*
|
|
|
|
* 2. negative in case of error during RX path -> req should not be freed
|
2016-03-25 17:46:53 +03:00
|
|
|
* as it's been already freed at the beginning of RX path by
|
2012-11-26 17:18:36 +04:00
|
|
|
* async_complete_cb.
|
|
|
|
*
|
|
|
|
* 3. valid pointer in case of succesfult RX path
|
|
|
|
*
|
|
|
|
* A caller has to check a return value with IS_ERR macro. If the test pass,
|
|
|
|
* the returned pointer is valid.
|
|
|
|
*
|
2016-03-25 17:46:53 +03:00
|
|
|
*/
|
2012-11-26 17:18:36 +04:00
|
|
|
static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code,
|
|
|
|
struct sk_buff *req)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
struct pn533_sync_cmd_response arg;
|
|
|
|
|
|
|
|
init_completion(&arg.done);
|
|
|
|
|
|
|
|
rc = pn533_send_cmd_async(dev, cmd_code, req,
|
|
|
|
pn533_send_sync_complete, &arg);
|
|
|
|
if (rc) {
|
|
|
|
dev_kfree_skb(req);
|
|
|
|
return ERR_PTR(rc);
|
|
|
|
}
|
|
|
|
|
|
|
|
wait_for_completion(&arg.done);
|
|
|
|
|
|
|
|
return arg.resp;
|
|
|
|
}
|
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
static struct sk_buff *pn533_alloc_skb(struct pn533 *dev, unsigned int size)
|
2012-11-26 17:18:37 +04:00
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = alloc_skb(dev->ops->tx_header_len +
|
2012-11-26 17:18:37 +04:00
|
|
|
size +
|
2012-12-10 17:43:01 +04:00
|
|
|
dev->ops->tx_tail_len, GFP_KERNEL);
|
2012-11-26 17:18:37 +04:00
|
|
|
|
|
|
|
if (skb)
|
2012-12-10 17:43:01 +04:00
|
|
|
skb_reserve(skb, dev->ops->tx_header_len);
|
2012-11-26 17:18:37 +04:00
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
struct pn533_target_type_a {
|
|
|
|
__be16 sens_res;
|
|
|
|
u8 sel_res;
|
|
|
|
u8 nfcid_len;
|
|
|
|
u8 nfcid_data[];
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
|
|
|
|
#define PN533_TYPE_A_SENS_RES_NFCID1(x) ((u8)((be16_to_cpu(x) & 0x00C0) >> 6))
|
|
|
|
#define PN533_TYPE_A_SENS_RES_SSD(x) ((u8)((be16_to_cpu(x) & 0x001F) >> 0))
|
|
|
|
#define PN533_TYPE_A_SENS_RES_PLATCONF(x) ((u8)((be16_to_cpu(x) & 0x0F00) >> 8))
|
|
|
|
|
|
|
|
#define PN533_TYPE_A_SENS_RES_SSD_JEWEL 0x00
|
|
|
|
#define PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL 0x0C
|
|
|
|
|
|
|
|
#define PN533_TYPE_A_SEL_PROT(x) (((x) & 0x60) >> 5)
|
|
|
|
#define PN533_TYPE_A_SEL_CASCADE(x) (((x) & 0x04) >> 2)
|
|
|
|
|
|
|
|
#define PN533_TYPE_A_SEL_PROT_MIFARE 0
|
|
|
|
#define PN533_TYPE_A_SEL_PROT_ISO14443 1
|
|
|
|
#define PN533_TYPE_A_SEL_PROT_DEP 2
|
|
|
|
#define PN533_TYPE_A_SEL_PROT_ISO14443_DEP 3
|
|
|
|
|
|
|
|
static bool pn533_target_type_a_is_valid(struct pn533_target_type_a *type_a,
|
|
|
|
int target_data_len)
|
|
|
|
{
|
|
|
|
u8 ssd;
|
|
|
|
u8 platconf;
|
|
|
|
|
|
|
|
if (target_data_len < sizeof(struct pn533_target_type_a))
|
|
|
|
return false;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
/*
|
|
|
|
* The length check of nfcid[] and ats[] are not being performed because
|
|
|
|
* the values are not being used
|
|
|
|
*/
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
/* Requirement 4.6.3.3 from NFC Forum Digital Spec */
|
|
|
|
ssd = PN533_TYPE_A_SENS_RES_SSD(type_a->sens_res);
|
|
|
|
platconf = PN533_TYPE_A_SENS_RES_PLATCONF(type_a->sens_res);
|
|
|
|
|
|
|
|
if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
|
2012-12-10 17:42:51 +04:00
|
|
|
platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) ||
|
|
|
|
(ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
|
|
|
|
platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL))
|
2011-07-02 02:31:37 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
/* Requirements 4.8.2.1, 4.8.2.3, 4.8.2.5 and 4.8.2.7 from NFC Forum */
|
|
|
|
if (PN533_TYPE_A_SEL_CASCADE(type_a->sel_res) != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_target_found_type_a(struct nfc_target *nfc_tgt, u8 *tgt_data,
|
|
|
|
int tgt_data_len)
|
|
|
|
{
|
|
|
|
struct pn533_target_type_a *tgt_type_a;
|
|
|
|
|
2012-12-10 17:42:50 +04:00
|
|
|
tgt_type_a = (struct pn533_target_type_a *)tgt_data;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
if (!pn533_target_type_a_is_valid(tgt_type_a, tgt_data_len))
|
|
|
|
return -EPROTO;
|
|
|
|
|
|
|
|
switch (PN533_TYPE_A_SEL_PROT(tgt_type_a->sel_res)) {
|
|
|
|
case PN533_TYPE_A_SEL_PROT_MIFARE:
|
|
|
|
nfc_tgt->supported_protocols = NFC_PROTO_MIFARE_MASK;
|
|
|
|
break;
|
|
|
|
case PN533_TYPE_A_SEL_PROT_ISO14443:
|
|
|
|
nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK;
|
|
|
|
break;
|
|
|
|
case PN533_TYPE_A_SEL_PROT_DEP:
|
|
|
|
nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
|
|
|
|
break;
|
|
|
|
case PN533_TYPE_A_SEL_PROT_ISO14443_DEP:
|
|
|
|
nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK |
|
|
|
|
NFC_PROTO_NFC_DEP_MASK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
nfc_tgt->sens_res = be16_to_cpu(tgt_type_a->sens_res);
|
|
|
|
nfc_tgt->sel_res = tgt_type_a->sel_res;
|
2012-03-05 04:03:33 +04:00
|
|
|
nfc_tgt->nfcid1_len = tgt_type_a->nfcid_len;
|
|
|
|
memcpy(nfc_tgt->nfcid1, tgt_type_a->nfcid_data, nfc_tgt->nfcid1_len);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct pn533_target_felica {
|
|
|
|
u8 pol_res;
|
|
|
|
u8 opcode;
|
2013-05-27 17:29:11 +04:00
|
|
|
u8 nfcid2[NFC_NFCID2_MAXSIZE];
|
2011-07-02 02:31:37 +04:00
|
|
|
u8 pad[8];
|
|
|
|
/* optional */
|
|
|
|
u8 syst_code[];
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
#define PN533_FELICA_SENSF_NFCID2_DEP_B1 0x01
|
|
|
|
#define PN533_FELICA_SENSF_NFCID2_DEP_B2 0xFE
|
|
|
|
|
|
|
|
static bool pn533_target_felica_is_valid(struct pn533_target_felica *felica,
|
|
|
|
int target_data_len)
|
|
|
|
{
|
|
|
|
if (target_data_len < sizeof(struct pn533_target_felica))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (felica->opcode != PN533_FELICA_OPC_SENSF_RES)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data,
|
|
|
|
int tgt_data_len)
|
|
|
|
{
|
|
|
|
struct pn533_target_felica *tgt_felica;
|
|
|
|
|
2012-12-10 17:42:50 +04:00
|
|
|
tgt_felica = (struct pn533_target_felica *)tgt_data;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
if (!pn533_target_felica_is_valid(tgt_felica, tgt_data_len))
|
|
|
|
return -EPROTO;
|
|
|
|
|
2012-12-10 17:42:51 +04:00
|
|
|
if ((tgt_felica->nfcid2[0] == PN533_FELICA_SENSF_NFCID2_DEP_B1) &&
|
|
|
|
(tgt_felica->nfcid2[1] == PN533_FELICA_SENSF_NFCID2_DEP_B2))
|
2011-07-02 02:31:37 +04:00
|
|
|
nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
|
|
|
|
else
|
|
|
|
nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK;
|
|
|
|
|
2012-03-05 04:03:45 +04:00
|
|
|
memcpy(nfc_tgt->sensf_res, &tgt_felica->opcode, 9);
|
|
|
|
nfc_tgt->sensf_res_len = 9;
|
|
|
|
|
2013-05-27 17:29:11 +04:00
|
|
|
memcpy(nfc_tgt->nfcid2, tgt_felica->nfcid2, NFC_NFCID2_MAXSIZE);
|
|
|
|
nfc_tgt->nfcid2_len = NFC_NFCID2_MAXSIZE;
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct pn533_target_jewel {
|
|
|
|
__be16 sens_res;
|
|
|
|
u8 jewelid[4];
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
static bool pn533_target_jewel_is_valid(struct pn533_target_jewel *jewel,
|
|
|
|
int target_data_len)
|
|
|
|
{
|
|
|
|
u8 ssd;
|
|
|
|
u8 platconf;
|
|
|
|
|
|
|
|
if (target_data_len < sizeof(struct pn533_target_jewel))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* Requirement 4.6.3.3 from NFC Forum Digital Spec */
|
|
|
|
ssd = PN533_TYPE_A_SENS_RES_SSD(jewel->sens_res);
|
|
|
|
platconf = PN533_TYPE_A_SENS_RES_PLATCONF(jewel->sens_res);
|
|
|
|
|
|
|
|
if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
|
2012-12-10 17:42:51 +04:00
|
|
|
platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) ||
|
|
|
|
(ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
|
|
|
|
platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL))
|
2011-07-02 02:31:37 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_target_found_jewel(struct nfc_target *nfc_tgt, u8 *tgt_data,
|
|
|
|
int tgt_data_len)
|
|
|
|
{
|
|
|
|
struct pn533_target_jewel *tgt_jewel;
|
|
|
|
|
2012-12-10 17:42:50 +04:00
|
|
|
tgt_jewel = (struct pn533_target_jewel *)tgt_data;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
if (!pn533_target_jewel_is_valid(tgt_jewel, tgt_data_len))
|
|
|
|
return -EPROTO;
|
|
|
|
|
|
|
|
nfc_tgt->supported_protocols = NFC_PROTO_JEWEL_MASK;
|
|
|
|
nfc_tgt->sens_res = be16_to_cpu(tgt_jewel->sens_res);
|
2012-03-05 04:03:46 +04:00
|
|
|
nfc_tgt->nfcid1_len = 4;
|
|
|
|
memcpy(nfc_tgt->nfcid1, tgt_jewel->jewelid, nfc_tgt->nfcid1_len);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct pn533_type_b_prot_info {
|
|
|
|
u8 bitrate;
|
|
|
|
u8 fsci_type;
|
|
|
|
u8 fwi_adc_fo;
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
#define PN533_TYPE_B_PROT_FCSI(x) (((x) & 0xF0) >> 4)
|
|
|
|
#define PN533_TYPE_B_PROT_TYPE(x) (((x) & 0x0F) >> 0)
|
|
|
|
#define PN533_TYPE_B_PROT_TYPE_RFU_MASK 0x8
|
|
|
|
|
|
|
|
struct pn533_type_b_sens_res {
|
|
|
|
u8 opcode;
|
|
|
|
u8 nfcid[4];
|
|
|
|
u8 appdata[4];
|
|
|
|
struct pn533_type_b_prot_info prot_info;
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
#define PN533_TYPE_B_OPC_SENSB_RES 0x50
|
|
|
|
|
|
|
|
struct pn533_target_type_b {
|
|
|
|
struct pn533_type_b_sens_res sensb_res;
|
|
|
|
u8 attrib_res_len;
|
|
|
|
u8 attrib_res[];
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
static bool pn533_target_type_b_is_valid(struct pn533_target_type_b *type_b,
|
|
|
|
int target_data_len)
|
|
|
|
{
|
|
|
|
if (target_data_len < sizeof(struct pn533_target_type_b))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (type_b->sensb_res.opcode != PN533_TYPE_B_OPC_SENSB_RES)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (PN533_TYPE_B_PROT_TYPE(type_b->sensb_res.prot_info.fsci_type) &
|
|
|
|
PN533_TYPE_B_PROT_TYPE_RFU_MASK)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data,
|
|
|
|
int tgt_data_len)
|
|
|
|
{
|
|
|
|
struct pn533_target_type_b *tgt_type_b;
|
|
|
|
|
2012-12-10 17:42:50 +04:00
|
|
|
tgt_type_b = (struct pn533_target_type_b *)tgt_data;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len))
|
|
|
|
return -EPROTO;
|
|
|
|
|
2012-07-04 02:14:04 +04:00
|
|
|
nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-21 17:43:52 +03:00
|
|
|
static void pn533_poll_reset_mod_list(struct pn533 *dev);
|
2012-12-10 17:42:48 +04:00
|
|
|
static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata,
|
|
|
|
int tgdata_len)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
|
|
|
struct nfc_target nfc_tgt;
|
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s: modulation=%d\n",
|
2013-04-05 23:27:37 +04:00
|
|
|
__func__, dev->poll_mod_curr);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
if (tg != 1)
|
2011-07-02 02:31:37 +04:00
|
|
|
return -EPROTO;
|
|
|
|
|
2012-03-05 04:03:39 +04:00
|
|
|
memset(&nfc_tgt, 0, sizeof(struct nfc_target));
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
switch (dev->poll_mod_curr) {
|
|
|
|
case PN533_POLL_MOD_106KBPS_A:
|
2012-12-10 17:42:48 +04:00
|
|
|
rc = pn533_target_found_type_a(&nfc_tgt, tgdata, tgdata_len);
|
2011-07-02 02:31:37 +04:00
|
|
|
break;
|
|
|
|
case PN533_POLL_MOD_212KBPS_FELICA:
|
|
|
|
case PN533_POLL_MOD_424KBPS_FELICA:
|
2012-12-10 17:42:48 +04:00
|
|
|
rc = pn533_target_found_felica(&nfc_tgt, tgdata, tgdata_len);
|
2011-07-02 02:31:37 +04:00
|
|
|
break;
|
|
|
|
case PN533_POLL_MOD_106KBPS_JEWEL:
|
2012-12-10 17:42:48 +04:00
|
|
|
rc = pn533_target_found_jewel(&nfc_tgt, tgdata, tgdata_len);
|
2011-07-02 02:31:37 +04:00
|
|
|
break;
|
|
|
|
case PN533_POLL_MOD_847KBPS_B:
|
2012-12-10 17:42:48 +04:00
|
|
|
rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len);
|
2011-07-02 02:31:37 +04:00
|
|
|
break;
|
|
|
|
default:
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Unknown current poll modulation\n");
|
2011-07-02 02:31:37 +04:00
|
|
|
return -EPROTO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) {
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev,
|
2013-04-05 23:27:37 +04:00
|
|
|
"The Tg found doesn't have the desired protocol\n");
|
2011-07-02 02:31:37 +04:00
|
|
|
return -EAGAIN;
|
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev,
|
2013-04-05 23:27:37 +04:00
|
|
|
"Target found - supported protocols: 0x%x\n",
|
|
|
|
nfc_tgt.supported_protocols);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
dev->tgt_available_prots = nfc_tgt.supported_protocols;
|
|
|
|
|
2016-04-21 17:43:52 +03:00
|
|
|
pn533_poll_reset_mod_list(dev);
|
2011-07-02 02:31:37 +04:00
|
|
|
nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
static inline void pn533_poll_next_mod(struct pn533 *dev)
|
|
|
|
{
|
|
|
|
dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
|
|
|
|
}
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
static void pn533_poll_reset_mod_list(struct pn533 *dev)
|
|
|
|
{
|
|
|
|
dev->poll_mod_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index)
|
|
|
|
{
|
|
|
|
dev->poll_mod_active[dev->poll_mod_count] =
|
2012-12-10 17:42:50 +04:00
|
|
|
(struct pn533_poll_modulations *)&poll_mod[mod_index];
|
2011-07-02 02:31:37 +04:00
|
|
|
dev->poll_mod_count++;
|
|
|
|
}
|
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
static void pn533_poll_create_mod_list(struct pn533 *dev,
|
|
|
|
u32 im_protocols, u32 tm_protocols)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
|
|
|
pn533_poll_reset_mod_list(dev);
|
|
|
|
|
2012-12-10 17:42:52 +04:00
|
|
|
if ((im_protocols & NFC_PROTO_MIFARE_MASK) ||
|
|
|
|
(im_protocols & NFC_PROTO_ISO14443_MASK) ||
|
|
|
|
(im_protocols & NFC_PROTO_NFC_DEP_MASK))
|
2011-07-02 02:31:37 +04:00
|
|
|
pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A);
|
|
|
|
|
2012-12-10 17:42:52 +04:00
|
|
|
if (im_protocols & NFC_PROTO_FELICA_MASK ||
|
|
|
|
im_protocols & NFC_PROTO_NFC_DEP_MASK) {
|
2011-07-02 02:31:37 +04:00
|
|
|
pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA);
|
|
|
|
pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA);
|
|
|
|
}
|
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
if (im_protocols & NFC_PROTO_JEWEL_MASK)
|
2011-07-02 02:31:37 +04:00
|
|
|
pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);
|
|
|
|
|
2012-07-04 02:14:04 +04:00
|
|
|
if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
|
2011-07-02 02:31:37 +04:00
|
|
|
pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
|
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
if (tm_protocols)
|
|
|
|
pn533_poll_add_mod(dev, PN533_LISTEN_MOD);
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
2012-12-10 17:42:48 +04:00
|
|
|
u8 nbtg, tg, *tgdata;
|
|
|
|
int rc, tgdata_len;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2013-08-21 17:06:55 +04:00
|
|
|
/* Toggle the DEP polling */
|
2016-03-25 17:46:51 +03:00
|
|
|
if (dev->poll_protocols & NFC_PROTO_NFC_DEP_MASK)
|
|
|
|
dev->poll_dep = 1;
|
2013-08-21 17:06:55 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
nbtg = resp->data[0];
|
|
|
|
tg = resp->data[1];
|
|
|
|
tgdata = &resp->data[2];
|
|
|
|
tgdata_len = resp->len - 2; /* nbtg + tg */
|
|
|
|
|
|
|
|
if (nbtg) {
|
|
|
|
rc = pn533_target_found(dev, tg, tgdata, tgdata_len);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
/* We must stop the poll after a valid target found */
|
2016-04-21 17:43:52 +03:00
|
|
|
if (rc == 0)
|
2012-05-30 19:20:25 +04:00
|
|
|
return 0;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
return -EAGAIN;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev)
|
2012-05-31 01:54:55 +04:00
|
|
|
{
|
2012-12-10 17:42:48 +04:00
|
|
|
struct sk_buff *skb;
|
2017-06-18 17:52:04 +03:00
|
|
|
u8 *felica, *nfcid3;
|
2012-12-10 17:42:48 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
u8 *gbytes = dev->gb;
|
|
|
|
size_t gbytes_len = dev->gb_len;
|
|
|
|
|
2012-05-30 03:48:46 +04:00
|
|
|
u8 felica_params[18] = {0x1, 0xfe, /* DEP */
|
|
|
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */
|
|
|
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
|
|
|
0xff, 0xff}; /* System code */
|
2012-12-10 17:42:48 +04:00
|
|
|
|
2012-05-30 03:48:46 +04:00
|
|
|
u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */
|
|
|
|
0x0, 0x0, 0x0,
|
|
|
|
0x40}; /* SEL_RES for DEP */
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
unsigned int skb_len = 36 + /*
|
|
|
|
* mode (1), mifare (6),
|
|
|
|
* felica (18), nfcid3 (10), gb_len (1)
|
|
|
|
*/
|
2012-12-10 17:42:48 +04:00
|
|
|
gbytes_len +
|
|
|
|
1; /* len Tk*/
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, skb_len);
|
2012-12-10 17:42:48 +04:00
|
|
|
if (!skb)
|
|
|
|
return NULL;
|
2012-05-31 01:54:55 +04:00
|
|
|
|
|
|
|
/* DEP support only */
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, PN533_INIT_TARGET_DEP);
|
2012-12-10 17:42:48 +04:00
|
|
|
|
|
|
|
/* MIFARE params */
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(skb, mifare_params, 6);
|
2012-05-30 03:48:46 +04:00
|
|
|
|
|
|
|
/* Felica params */
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
felica = skb_put_data(skb, felica_params, 18);
|
2012-12-10 17:42:48 +04:00
|
|
|
get_random_bytes(felica + 2, 6);
|
2012-05-30 03:48:46 +04:00
|
|
|
|
|
|
|
/* NFCID3 */
|
2017-06-13 15:28:18 +03:00
|
|
|
nfcid3 = skb_put_zero(skb, 10);
|
2012-12-10 17:42:48 +04:00
|
|
|
memcpy(nfcid3, felica, 8);
|
2012-05-30 03:48:46 +04:00
|
|
|
|
|
|
|
/* General bytes */
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, gbytes_len);
|
2012-05-30 03:48:46 +04:00
|
|
|
|
2017-06-18 17:52:04 +03:00
|
|
|
skb_put_data(skb, gbytes, gbytes_len);
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
/* Len Tk */
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, 0);
|
2012-05-30 03:48:46 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
return skb;
|
2012-05-31 01:54:55 +04:00
|
|
|
}
|
|
|
|
|
2013-09-23 14:24:38 +04:00
|
|
|
static void pn533_wq_tm_mi_recv(struct work_struct *work);
|
|
|
|
static struct sk_buff *pn533_build_response(struct pn533 *dev);
|
|
|
|
|
2012-05-31 02:07:51 +04:00
|
|
|
static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg,
|
2012-12-10 17:42:44 +04:00
|
|
|
struct sk_buff *resp)
|
2012-05-31 02:07:51 +04:00
|
|
|
{
|
2013-09-23 14:24:38 +04:00
|
|
|
struct sk_buff *skb;
|
|
|
|
u8 status, ret, mi;
|
|
|
|
int rc;
|
2012-05-31 02:07:51 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-05-31 02:07:51 +04:00
|
|
|
|
2013-09-23 14:24:38 +04:00
|
|
|
if (IS_ERR(resp)) {
|
|
|
|
skb_queue_purge(&dev->resp_q);
|
2012-12-10 17:42:44 +04:00
|
|
|
return PTR_ERR(resp);
|
2013-09-23 14:24:38 +04:00
|
|
|
}
|
2012-05-31 02:07:51 +04:00
|
|
|
|
2012-12-10 17:42:44 +04:00
|
|
|
status = resp->data[0];
|
2013-09-23 14:24:38 +04:00
|
|
|
|
|
|
|
ret = status & PN533_CMD_RET_MASK;
|
|
|
|
mi = status & PN533_CMD_MI_MASK;
|
|
|
|
|
2012-12-10 17:42:44 +04:00
|
|
|
skb_pull(resp, sizeof(status));
|
2012-05-31 02:07:51 +04:00
|
|
|
|
2013-09-23 14:24:38 +04:00
|
|
|
if (ret != PN533_CMD_RET_SUCCESS) {
|
|
|
|
rc = -EIO;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb_queue_tail(&dev->resp_q, resp);
|
|
|
|
|
|
|
|
if (mi) {
|
|
|
|
queue_work(dev->wq, &dev->mi_tm_rx_work);
|
|
|
|
return -EINPROGRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb = pn533_build_response(dev);
|
|
|
|
if (!skb) {
|
|
|
|
rc = -EIO;
|
|
|
|
goto error;
|
2012-05-31 02:07:51 +04:00
|
|
|
}
|
|
|
|
|
2013-09-23 14:24:38 +04:00
|
|
|
return nfc_tm_data_received(dev->nfc_dev, skb);
|
|
|
|
|
|
|
|
error:
|
|
|
|
nfc_tm_deactivated(dev->nfc_dev);
|
|
|
|
dev->tgt_mode = 0;
|
|
|
|
skb_queue_purge(&dev->resp_q);
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pn533_wq_tm_mi_recv(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = container_of(work, struct pn533, mi_tm_rx_work);
|
|
|
|
struct sk_buff *skb;
|
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2013-09-23 14:24:38 +04:00
|
|
|
|
|
|
|
skb = pn533_alloc_skb(dev, 0);
|
|
|
|
if (!skb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
rc = pn533_send_cmd_direct_async(dev,
|
|
|
|
PN533_CMD_TG_GET_DATA,
|
|
|
|
skb,
|
|
|
|
pn533_tm_get_data_complete,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
dev_kfree_skb(skb);
|
2012-05-31 02:07:51 +04:00
|
|
|
}
|
|
|
|
|
2013-09-23 14:24:39 +04:00
|
|
|
static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
|
|
|
|
struct sk_buff *resp);
|
|
|
|
static void pn533_wq_tm_mi_send(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = container_of(work, struct pn533, mi_tm_tx_work);
|
|
|
|
struct sk_buff *skb;
|
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2013-09-23 14:24:39 +04:00
|
|
|
|
|
|
|
/* Grab the first skb in the queue */
|
|
|
|
skb = skb_dequeue(&dev->fragment_skb);
|
|
|
|
if (skb == NULL) { /* No more data */
|
|
|
|
/* Reset the queue for future use */
|
|
|
|
skb_queue_head_init(&dev->fragment_skb);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* last entry - remove MI bit */
|
|
|
|
if (skb_queue_len(&dev->fragment_skb) == 0) {
|
|
|
|
rc = pn533_send_cmd_direct_async(dev, PN533_CMD_TG_SET_DATA,
|
|
|
|
skb, pn533_tm_send_complete, NULL);
|
|
|
|
} else
|
|
|
|
rc = pn533_send_cmd_direct_async(dev,
|
|
|
|
PN533_CMD_TG_SET_META_DATA,
|
|
|
|
skb, pn533_tm_send_complete, NULL);
|
|
|
|
|
|
|
|
if (rc == 0) /* success */
|
|
|
|
return;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_err(dev->dev,
|
2013-09-23 14:24:39 +04:00
|
|
|
"Error %d when trying to perform set meta data_exchange", rc);
|
|
|
|
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
|
|
|
|
error:
|
2016-03-25 17:46:53 +03:00
|
|
|
dev->phy_ops->send_ack(dev, GFP_KERNEL);
|
2013-09-23 14:24:39 +04:00
|
|
|
queue_work(dev->wq, &dev->cmd_work);
|
|
|
|
}
|
|
|
|
|
2012-05-31 02:07:51 +04:00
|
|
|
static void pn533_wq_tg_get_data(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = container_of(work, struct pn533, tg_work);
|
2012-12-10 17:42:44 +04:00
|
|
|
struct sk_buff *skb;
|
|
|
|
int rc;
|
2012-05-31 02:07:51 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-05-31 02:07:51 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, 0);
|
2012-12-10 17:42:44 +04:00
|
|
|
if (!skb)
|
2012-05-31 02:07:51 +04:00
|
|
|
return;
|
|
|
|
|
2012-12-10 17:42:44 +04:00
|
|
|
rc = pn533_send_data_async(dev, PN533_CMD_TG_GET_DATA, skb,
|
|
|
|
pn533_tm_get_data_complete, NULL);
|
2012-05-31 02:07:51 +04:00
|
|
|
|
2012-12-10 17:42:44 +04:00
|
|
|
if (rc < 0)
|
|
|
|
dev_kfree_skb(skb);
|
2012-05-31 02:07:51 +04:00
|
|
|
}
|
|
|
|
|
2012-06-01 15:21:13 +04:00
|
|
|
#define ATR_REQ_GB_OFFSET 17
|
2012-12-10 17:42:48 +04:00
|
|
|
static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp)
|
2012-05-15 17:57:06 +04:00
|
|
|
{
|
2012-12-10 17:42:48 +04:00
|
|
|
u8 mode, *cmd, comm_mode = NFC_COMM_PASSIVE, *gb;
|
2012-06-01 15:21:13 +04:00
|
|
|
size_t gb_len;
|
2012-05-31 02:07:51 +04:00
|
|
|
int rc;
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
if (resp->len < ATR_REQ_GB_OFFSET + 1)
|
2012-06-01 15:21:13 +04:00
|
|
|
return -EINVAL;
|
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
mode = resp->data[0];
|
|
|
|
cmd = &resp->data[1];
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "Target mode 0x%x len %d\n",
|
2013-04-05 23:27:37 +04:00
|
|
|
mode, resp->len);
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) ==
|
|
|
|
PN533_INIT_TARGET_RESP_ACTIVE)
|
2012-06-01 15:21:13 +04:00
|
|
|
comm_mode = NFC_COMM_ACTIVE;
|
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
if ((mode & PN533_INIT_TARGET_RESP_DEP) == 0) /* Only DEP supported */
|
2012-06-01 15:21:13 +04:00
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
gb = cmd + ATR_REQ_GB_OFFSET;
|
|
|
|
gb_len = resp->len - (ATR_REQ_GB_OFFSET + 1);
|
2012-06-01 15:21:13 +04:00
|
|
|
|
2012-05-31 02:07:51 +04:00
|
|
|
rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
|
|
|
|
comm_mode, gb, gb_len);
|
|
|
|
if (rc < 0) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Error when signaling target activation\n");
|
2012-05-31 02:07:51 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-05-31 22:01:32 +04:00
|
|
|
dev->tgt_mode = 1;
|
2012-05-31 02:07:51 +04:00
|
|
|
queue_work(dev->wq, &dev->tg_work);
|
|
|
|
|
|
|
|
return 0;
|
2012-05-15 17:57:06 +04:00
|
|
|
}
|
|
|
|
|
treewide: setup_timer() -> timer_setup()
This converts all remaining cases of the old setup_timer() API into using
timer_setup(), where the callback argument is the structure already
holding the struct timer_list. These should have no behavioral changes,
since they just change which pointer is passed into the callback with
the same available pointers after conversion. It handles the following
examples, in addition to some other variations.
Casting from unsigned long:
void my_callback(unsigned long data)
{
struct something *ptr = (struct something *)data;
...
}
...
setup_timer(&ptr->my_timer, my_callback, ptr);
and forced object casts:
void my_callback(struct something *ptr)
{
...
}
...
setup_timer(&ptr->my_timer, my_callback, (unsigned long)ptr);
become:
void my_callback(struct timer_list *t)
{
struct something *ptr = from_timer(ptr, t, my_timer);
...
}
...
timer_setup(&ptr->my_timer, my_callback, 0);
Direct function assignments:
void my_callback(unsigned long data)
{
struct something *ptr = (struct something *)data;
...
}
...
ptr->my_timer.function = my_callback;
have a temporary cast added, along with converting the args:
void my_callback(struct timer_list *t)
{
struct something *ptr = from_timer(ptr, t, my_timer);
...
}
...
ptr->my_timer.function = (TIMER_FUNC_TYPE)my_callback;
And finally, callbacks without a data assignment:
void my_callback(unsigned long data)
{
...
}
...
setup_timer(&ptr->my_timer, my_callback, 0);
have their argument renamed to verify they're unused during conversion:
void my_callback(struct timer_list *unused)
{
...
}
...
timer_setup(&ptr->my_timer, my_callback, 0);
The conversion is done with the following Coccinelle script:
spatch --very-quiet --all-includes --include-headers \
-I ./arch/x86/include -I ./arch/x86/include/generated \
-I ./include -I ./arch/x86/include/uapi \
-I ./arch/x86/include/generated/uapi -I ./include/uapi \
-I ./include/generated/uapi --include ./include/linux/kconfig.h \
--dir . \
--cocci-file ~/src/data/timer_setup.cocci
@fix_address_of@
expression e;
@@
setup_timer(
-&(e)
+&e
, ...)
// Update any raw setup_timer() usages that have a NULL callback, but
// would otherwise match change_timer_function_usage, since the latter
// will update all function assignments done in the face of a NULL
// function initialization in setup_timer().
@change_timer_function_usage_NULL@
expression _E;
identifier _timer;
type _cast_data;
@@
(
-setup_timer(&_E->_timer, NULL, _E);
+timer_setup(&_E->_timer, NULL, 0);
|
-setup_timer(&_E->_timer, NULL, (_cast_data)_E);
+timer_setup(&_E->_timer, NULL, 0);
|
-setup_timer(&_E._timer, NULL, &_E);
+timer_setup(&_E._timer, NULL, 0);
|
-setup_timer(&_E._timer, NULL, (_cast_data)&_E);
+timer_setup(&_E._timer, NULL, 0);
)
@change_timer_function_usage@
expression _E;
identifier _timer;
struct timer_list _stl;
identifier _callback;
type _cast_func, _cast_data;
@@
(
-setup_timer(&_E->_timer, _callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, &_callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, _callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, &_callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)_callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)&_callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)_callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)&_callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, &_callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, &_callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
_E->_timer@_stl.function = _callback;
|
_E->_timer@_stl.function = &_callback;
|
_E->_timer@_stl.function = (_cast_func)_callback;
|
_E->_timer@_stl.function = (_cast_func)&_callback;
|
_E._timer@_stl.function = _callback;
|
_E._timer@_stl.function = &_callback;
|
_E._timer@_stl.function = (_cast_func)_callback;
|
_E._timer@_stl.function = (_cast_func)&_callback;
)
// callback(unsigned long arg)
@change_callback_handle_cast
depends on change_timer_function_usage@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _origtype;
identifier _origarg;
type _handletype;
identifier _handle;
@@
void _callback(
-_origtype _origarg
+struct timer_list *t
)
{
(
... when != _origarg
_handletype *_handle =
-(_handletype *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
|
... when != _origarg
_handletype *_handle =
-(void *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
|
... when != _origarg
_handletype *_handle;
... when != _handle
_handle =
-(_handletype *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
|
... when != _origarg
_handletype *_handle;
... when != _handle
_handle =
-(void *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
)
}
// callback(unsigned long arg) without existing variable
@change_callback_handle_cast_no_arg
depends on change_timer_function_usage &&
!change_callback_handle_cast@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _origtype;
identifier _origarg;
type _handletype;
@@
void _callback(
-_origtype _origarg
+struct timer_list *t
)
{
+ _handletype *_origarg = from_timer(_origarg, t, _timer);
+
... when != _origarg
- (_handletype *)_origarg
+ _origarg
... when != _origarg
}
// Avoid already converted callbacks.
@match_callback_converted
depends on change_timer_function_usage &&
!change_callback_handle_cast &&
!change_callback_handle_cast_no_arg@
identifier change_timer_function_usage._callback;
identifier t;
@@
void _callback(struct timer_list *t)
{ ... }
// callback(struct something *handle)
@change_callback_handle_arg
depends on change_timer_function_usage &&
!match_callback_converted &&
!change_callback_handle_cast &&
!change_callback_handle_cast_no_arg@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _handletype;
identifier _handle;
@@
void _callback(
-_handletype *_handle
+struct timer_list *t
)
{
+ _handletype *_handle = from_timer(_handle, t, _timer);
...
}
// If change_callback_handle_arg ran on an empty function, remove
// the added handler.
@unchange_callback_handle_arg
depends on change_timer_function_usage &&
change_callback_handle_arg@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _handletype;
identifier _handle;
identifier t;
@@
void _callback(struct timer_list *t)
{
- _handletype *_handle = from_timer(_handle, t, _timer);
}
// We only want to refactor the setup_timer() data argument if we've found
// the matching callback. This undoes changes in change_timer_function_usage.
@unchange_timer_function_usage
depends on change_timer_function_usage &&
!change_callback_handle_cast &&
!change_callback_handle_cast_no_arg &&
!change_callback_handle_arg@
expression change_timer_function_usage._E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type change_timer_function_usage._cast_data;
@@
(
-timer_setup(&_E->_timer, _callback, 0);
+setup_timer(&_E->_timer, _callback, (_cast_data)_E);
|
-timer_setup(&_E._timer, _callback, 0);
+setup_timer(&_E._timer, _callback, (_cast_data)&_E);
)
// If we fixed a callback from a .function assignment, fix the
// assignment cast now.
@change_timer_function_assignment
depends on change_timer_function_usage &&
(change_callback_handle_cast ||
change_callback_handle_cast_no_arg ||
change_callback_handle_arg)@
expression change_timer_function_usage._E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type _cast_func;
typedef TIMER_FUNC_TYPE;
@@
(
_E->_timer.function =
-_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E->_timer.function =
-&_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E->_timer.function =
-(_cast_func)_callback;
+(TIMER_FUNC_TYPE)_callback
;
|
_E->_timer.function =
-(_cast_func)&_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-&_callback;
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-(_cast_func)_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-(_cast_func)&_callback
+(TIMER_FUNC_TYPE)_callback
;
)
// Sometimes timer functions are called directly. Replace matched args.
@change_timer_function_calls
depends on change_timer_function_usage &&
(change_callback_handle_cast ||
change_callback_handle_cast_no_arg ||
change_callback_handle_arg)@
expression _E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type _cast_data;
@@
_callback(
(
-(_cast_data)_E
+&_E->_timer
|
-(_cast_data)&_E
+&_E._timer
|
-_E
+&_E->_timer
)
)
// If a timer has been configured without a data argument, it can be
// converted without regard to the callback argument, since it is unused.
@match_timer_function_unused_data@
expression _E;
identifier _timer;
identifier _callback;
@@
(
-setup_timer(&_E->_timer, _callback, 0);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, _callback, 0L);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, _callback, 0UL);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, 0);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, 0L);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, 0UL);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_timer, _callback, 0);
+timer_setup(&_timer, _callback, 0);
|
-setup_timer(&_timer, _callback, 0L);
+timer_setup(&_timer, _callback, 0);
|
-setup_timer(&_timer, _callback, 0UL);
+timer_setup(&_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0);
+timer_setup(_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0L);
+timer_setup(_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0UL);
+timer_setup(_timer, _callback, 0);
)
@change_callback_unused_data
depends on match_timer_function_unused_data@
identifier match_timer_function_unused_data._callback;
type _origtype;
identifier _origarg;
@@
void _callback(
-_origtype _origarg
+struct timer_list *unused
)
{
... when != _origarg
}
Signed-off-by: Kees Cook <keescook@chromium.org>
2017-10-17 00:43:17 +03:00
|
|
|
static void pn533_listen_mode_timer(struct timer_list *t)
|
2012-05-31 01:54:55 +04:00
|
|
|
{
|
treewide: setup_timer() -> timer_setup()
This converts all remaining cases of the old setup_timer() API into using
timer_setup(), where the callback argument is the structure already
holding the struct timer_list. These should have no behavioral changes,
since they just change which pointer is passed into the callback with
the same available pointers after conversion. It handles the following
examples, in addition to some other variations.
Casting from unsigned long:
void my_callback(unsigned long data)
{
struct something *ptr = (struct something *)data;
...
}
...
setup_timer(&ptr->my_timer, my_callback, ptr);
and forced object casts:
void my_callback(struct something *ptr)
{
...
}
...
setup_timer(&ptr->my_timer, my_callback, (unsigned long)ptr);
become:
void my_callback(struct timer_list *t)
{
struct something *ptr = from_timer(ptr, t, my_timer);
...
}
...
timer_setup(&ptr->my_timer, my_callback, 0);
Direct function assignments:
void my_callback(unsigned long data)
{
struct something *ptr = (struct something *)data;
...
}
...
ptr->my_timer.function = my_callback;
have a temporary cast added, along with converting the args:
void my_callback(struct timer_list *t)
{
struct something *ptr = from_timer(ptr, t, my_timer);
...
}
...
ptr->my_timer.function = (TIMER_FUNC_TYPE)my_callback;
And finally, callbacks without a data assignment:
void my_callback(unsigned long data)
{
...
}
...
setup_timer(&ptr->my_timer, my_callback, 0);
have their argument renamed to verify they're unused during conversion:
void my_callback(struct timer_list *unused)
{
...
}
...
timer_setup(&ptr->my_timer, my_callback, 0);
The conversion is done with the following Coccinelle script:
spatch --very-quiet --all-includes --include-headers \
-I ./arch/x86/include -I ./arch/x86/include/generated \
-I ./include -I ./arch/x86/include/uapi \
-I ./arch/x86/include/generated/uapi -I ./include/uapi \
-I ./include/generated/uapi --include ./include/linux/kconfig.h \
--dir . \
--cocci-file ~/src/data/timer_setup.cocci
@fix_address_of@
expression e;
@@
setup_timer(
-&(e)
+&e
, ...)
// Update any raw setup_timer() usages that have a NULL callback, but
// would otherwise match change_timer_function_usage, since the latter
// will update all function assignments done in the face of a NULL
// function initialization in setup_timer().
@change_timer_function_usage_NULL@
expression _E;
identifier _timer;
type _cast_data;
@@
(
-setup_timer(&_E->_timer, NULL, _E);
+timer_setup(&_E->_timer, NULL, 0);
|
-setup_timer(&_E->_timer, NULL, (_cast_data)_E);
+timer_setup(&_E->_timer, NULL, 0);
|
-setup_timer(&_E._timer, NULL, &_E);
+timer_setup(&_E._timer, NULL, 0);
|
-setup_timer(&_E._timer, NULL, (_cast_data)&_E);
+timer_setup(&_E._timer, NULL, 0);
)
@change_timer_function_usage@
expression _E;
identifier _timer;
struct timer_list _stl;
identifier _callback;
type _cast_func, _cast_data;
@@
(
-setup_timer(&_E->_timer, _callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, &_callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, _callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, &_callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)_callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)&_callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)_callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)&_callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, &_callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, &_callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
_E->_timer@_stl.function = _callback;
|
_E->_timer@_stl.function = &_callback;
|
_E->_timer@_stl.function = (_cast_func)_callback;
|
_E->_timer@_stl.function = (_cast_func)&_callback;
|
_E._timer@_stl.function = _callback;
|
_E._timer@_stl.function = &_callback;
|
_E._timer@_stl.function = (_cast_func)_callback;
|
_E._timer@_stl.function = (_cast_func)&_callback;
)
// callback(unsigned long arg)
@change_callback_handle_cast
depends on change_timer_function_usage@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _origtype;
identifier _origarg;
type _handletype;
identifier _handle;
@@
void _callback(
-_origtype _origarg
+struct timer_list *t
)
{
(
... when != _origarg
_handletype *_handle =
-(_handletype *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
|
... when != _origarg
_handletype *_handle =
-(void *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
|
... when != _origarg
_handletype *_handle;
... when != _handle
_handle =
-(_handletype *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
|
... when != _origarg
_handletype *_handle;
... when != _handle
_handle =
-(void *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
)
}
// callback(unsigned long arg) without existing variable
@change_callback_handle_cast_no_arg
depends on change_timer_function_usage &&
!change_callback_handle_cast@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _origtype;
identifier _origarg;
type _handletype;
@@
void _callback(
-_origtype _origarg
+struct timer_list *t
)
{
+ _handletype *_origarg = from_timer(_origarg, t, _timer);
+
... when != _origarg
- (_handletype *)_origarg
+ _origarg
... when != _origarg
}
// Avoid already converted callbacks.
@match_callback_converted
depends on change_timer_function_usage &&
!change_callback_handle_cast &&
!change_callback_handle_cast_no_arg@
identifier change_timer_function_usage._callback;
identifier t;
@@
void _callback(struct timer_list *t)
{ ... }
// callback(struct something *handle)
@change_callback_handle_arg
depends on change_timer_function_usage &&
!match_callback_converted &&
!change_callback_handle_cast &&
!change_callback_handle_cast_no_arg@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _handletype;
identifier _handle;
@@
void _callback(
-_handletype *_handle
+struct timer_list *t
)
{
+ _handletype *_handle = from_timer(_handle, t, _timer);
...
}
// If change_callback_handle_arg ran on an empty function, remove
// the added handler.
@unchange_callback_handle_arg
depends on change_timer_function_usage &&
change_callback_handle_arg@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _handletype;
identifier _handle;
identifier t;
@@
void _callback(struct timer_list *t)
{
- _handletype *_handle = from_timer(_handle, t, _timer);
}
// We only want to refactor the setup_timer() data argument if we've found
// the matching callback. This undoes changes in change_timer_function_usage.
@unchange_timer_function_usage
depends on change_timer_function_usage &&
!change_callback_handle_cast &&
!change_callback_handle_cast_no_arg &&
!change_callback_handle_arg@
expression change_timer_function_usage._E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type change_timer_function_usage._cast_data;
@@
(
-timer_setup(&_E->_timer, _callback, 0);
+setup_timer(&_E->_timer, _callback, (_cast_data)_E);
|
-timer_setup(&_E._timer, _callback, 0);
+setup_timer(&_E._timer, _callback, (_cast_data)&_E);
)
// If we fixed a callback from a .function assignment, fix the
// assignment cast now.
@change_timer_function_assignment
depends on change_timer_function_usage &&
(change_callback_handle_cast ||
change_callback_handle_cast_no_arg ||
change_callback_handle_arg)@
expression change_timer_function_usage._E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type _cast_func;
typedef TIMER_FUNC_TYPE;
@@
(
_E->_timer.function =
-_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E->_timer.function =
-&_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E->_timer.function =
-(_cast_func)_callback;
+(TIMER_FUNC_TYPE)_callback
;
|
_E->_timer.function =
-(_cast_func)&_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-&_callback;
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-(_cast_func)_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-(_cast_func)&_callback
+(TIMER_FUNC_TYPE)_callback
;
)
// Sometimes timer functions are called directly. Replace matched args.
@change_timer_function_calls
depends on change_timer_function_usage &&
(change_callback_handle_cast ||
change_callback_handle_cast_no_arg ||
change_callback_handle_arg)@
expression _E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type _cast_data;
@@
_callback(
(
-(_cast_data)_E
+&_E->_timer
|
-(_cast_data)&_E
+&_E._timer
|
-_E
+&_E->_timer
)
)
// If a timer has been configured without a data argument, it can be
// converted without regard to the callback argument, since it is unused.
@match_timer_function_unused_data@
expression _E;
identifier _timer;
identifier _callback;
@@
(
-setup_timer(&_E->_timer, _callback, 0);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, _callback, 0L);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, _callback, 0UL);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, 0);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, 0L);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, 0UL);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_timer, _callback, 0);
+timer_setup(&_timer, _callback, 0);
|
-setup_timer(&_timer, _callback, 0L);
+timer_setup(&_timer, _callback, 0);
|
-setup_timer(&_timer, _callback, 0UL);
+timer_setup(&_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0);
+timer_setup(_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0L);
+timer_setup(_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0UL);
+timer_setup(_timer, _callback, 0);
)
@change_callback_unused_data
depends on match_timer_function_unused_data@
identifier match_timer_function_unused_data._callback;
type _origtype;
identifier _origarg;
@@
void _callback(
-_origtype _origarg
+struct timer_list *unused
)
{
... when != _origarg
}
Signed-off-by: Kees Cook <keescook@chromium.org>
2017-10-17 00:43:17 +03:00
|
|
|
struct pn533 *dev = from_timer(dev, t, listen_timer);
|
2012-05-30 19:20:25 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "Listen mode timeout\n");
|
2012-05-30 19:20:25 +04:00
|
|
|
|
|
|
|
dev->cancel_listen = 1;
|
|
|
|
|
|
|
|
pn533_poll_next_mod(dev);
|
|
|
|
|
2013-07-03 16:50:36 +04:00
|
|
|
queue_delayed_work(dev->wq, &dev->poll_work,
|
|
|
|
msecs_to_jiffies(PN533_POLL_INTERVAL));
|
2012-05-30 19:20:25 +04:00
|
|
|
}
|
|
|
|
|
2013-06-26 20:16:21 +04:00
|
|
|
static int pn533_rf_complete(struct pn533 *dev, void *arg,
|
|
|
|
struct sk_buff *resp)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2013-06-26 20:16:21 +04:00
|
|
|
|
|
|
|
if (IS_ERR(resp)) {
|
|
|
|
rc = PTR_ERR(resp);
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "RF setting error %d\n", rc);
|
2013-06-26 20:16:21 +04:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2013-07-03 16:50:36 +04:00
|
|
|
queue_delayed_work(dev->wq, &dev->poll_work,
|
|
|
|
msecs_to_jiffies(PN533_POLL_INTERVAL));
|
2013-06-26 20:16:21 +04:00
|
|
|
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pn533_wq_rf(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = container_of(work, struct pn533, rf_work);
|
|
|
|
struct sk_buff *skb;
|
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2013-06-26 20:16:21 +04:00
|
|
|
|
|
|
|
skb = pn533_alloc_skb(dev, 2);
|
|
|
|
if (!skb)
|
|
|
|
return;
|
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, PN533_CFGITEM_RF_FIELD);
|
|
|
|
skb_put_u8(skb, PN533_CFGITEM_RF_FIELD_AUTO_RFCA);
|
2013-06-26 20:16:21 +04:00
|
|
|
|
|
|
|
rc = pn533_send_cmd_async(dev, PN533_CMD_RF_CONFIGURATION, skb,
|
|
|
|
pn533_rf_complete, NULL);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_kfree_skb(skb);
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "RF setting error %d\n", rc);
|
2013-06-26 20:16:21 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-21 17:06:55 +04:00
|
|
|
static int pn533_poll_dep_complete(struct pn533 *dev, void *arg,
|
|
|
|
struct sk_buff *resp)
|
|
|
|
{
|
|
|
|
struct pn533_cmd_jump_dep_response *rsp;
|
|
|
|
struct nfc_target nfc_target;
|
|
|
|
u8 target_gt_len;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (IS_ERR(resp))
|
|
|
|
return PTR_ERR(resp);
|
|
|
|
|
|
|
|
rsp = (struct pn533_cmd_jump_dep_response *)resp->data;
|
|
|
|
|
|
|
|
rc = rsp->status & PN533_CMD_RET_MASK;
|
|
|
|
if (rc != PN533_CMD_RET_SUCCESS) {
|
|
|
|
/* Not target found, turn radio off */
|
|
|
|
queue_work(dev->wq, &dev->rf_work);
|
|
|
|
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "Creating new target");
|
2013-08-21 17:06:55 +04:00
|
|
|
|
|
|
|
nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
|
|
|
|
nfc_target.nfcid1_len = 10;
|
|
|
|
memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len);
|
|
|
|
rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1);
|
|
|
|
if (rc)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
dev->tgt_available_prots = 0;
|
|
|
|
dev->tgt_active_prot = NFC_PROTO_NFC_DEP;
|
|
|
|
|
|
|
|
/* ATR_RES general bytes are located at offset 17 */
|
|
|
|
target_gt_len = resp->len - 17;
|
|
|
|
rc = nfc_set_remote_general_bytes(dev->nfc_dev,
|
|
|
|
rsp->gt, target_gt_len);
|
|
|
|
if (!rc) {
|
|
|
|
rc = nfc_dep_link_is_up(dev->nfc_dev,
|
|
|
|
dev->nfc_dev->targets[0].idx,
|
|
|
|
0, NFC_RF_INITIATOR);
|
|
|
|
|
|
|
|
if (!rc)
|
|
|
|
pn533_poll_reset_mod_list(dev);
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define PASSIVE_DATA_LEN 5
|
|
|
|
static int pn533_poll_dep(struct nfc_dev *nfc_dev)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
|
struct sk_buff *skb;
|
|
|
|
int rc, skb_len;
|
|
|
|
u8 *next, nfcid3[NFC_NFCID3_MAXSIZE];
|
|
|
|
u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s", __func__);
|
2013-08-21 17:06:55 +04:00
|
|
|
|
|
|
|
if (!dev->gb) {
|
|
|
|
dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len);
|
|
|
|
|
|
|
|
if (!dev->gb || !dev->gb_len) {
|
|
|
|
dev->poll_dep = 0;
|
|
|
|
queue_work(dev->wq, &dev->rf_work);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
skb_len = 3 + dev->gb_len; /* ActPass + BR + Next */
|
|
|
|
skb_len += PASSIVE_DATA_LEN;
|
|
|
|
|
|
|
|
/* NFCID3 */
|
|
|
|
skb_len += NFC_NFCID3_MAXSIZE;
|
|
|
|
nfcid3[0] = 0x1;
|
|
|
|
nfcid3[1] = 0xfe;
|
|
|
|
get_random_bytes(nfcid3 + 2, 6);
|
|
|
|
|
|
|
|
skb = pn533_alloc_skb(dev, skb_len);
|
|
|
|
if (!skb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, 0x01); /* Active */
|
|
|
|
skb_put_u8(skb, 0x02); /* 424 kbps */
|
2013-08-21 17:06:55 +04:00
|
|
|
|
|
|
|
next = skb_put(skb, 1); /* Next */
|
|
|
|
*next = 0;
|
|
|
|
|
|
|
|
/* Copy passive data */
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(skb, passive_data, PASSIVE_DATA_LEN);
|
2013-08-21 17:06:55 +04:00
|
|
|
*next |= 1;
|
|
|
|
|
|
|
|
/* Copy NFCID3 (which is NFCID2 from SENSF_RES) */
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(skb, nfcid3, NFC_NFCID3_MAXSIZE);
|
2013-08-21 17:06:55 +04:00
|
|
|
*next |= 2;
|
|
|
|
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(skb, dev->gb, dev->gb_len);
|
2013-08-21 17:06:55 +04:00
|
|
|
*next |= 4; /* We have some Gi */
|
|
|
|
|
|
|
|
rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb,
|
|
|
|
pn533_poll_dep_complete, NULL);
|
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-10-29 17:47:43 +03:00
|
|
|
static int pn533_autopoll_complete(struct pn533 *dev, void *arg,
|
|
|
|
struct sk_buff *resp)
|
|
|
|
{
|
|
|
|
struct pn532_autopoll_resp *apr;
|
|
|
|
struct nfc_target nfc_tgt;
|
|
|
|
u8 nbtg;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (IS_ERR(resp)) {
|
|
|
|
rc = PTR_ERR(resp);
|
|
|
|
|
|
|
|
nfc_err(dev->dev, "%s autopoll complete error %d\n",
|
|
|
|
__func__, rc);
|
|
|
|
|
|
|
|
if (rc == -ENOENT) {
|
|
|
|
if (dev->poll_mod_count != 0)
|
|
|
|
return rc;
|
|
|
|
goto stop_poll;
|
|
|
|
} else if (rc < 0) {
|
|
|
|
nfc_err(dev->dev,
|
|
|
|
"Error %d when running autopoll\n", rc);
|
|
|
|
goto stop_poll;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nbtg = resp->data[0];
|
|
|
|
if ((nbtg > 2) || (nbtg <= 0))
|
|
|
|
return -EAGAIN;
|
|
|
|
|
|
|
|
apr = (struct pn532_autopoll_resp *)&resp->data[1];
|
|
|
|
while (nbtg--) {
|
|
|
|
memset(&nfc_tgt, 0, sizeof(struct nfc_target));
|
|
|
|
switch (apr->type) {
|
|
|
|
case PN532_AUTOPOLL_TYPE_ISOA:
|
|
|
|
dev_dbg(dev->dev, "ISOA\n");
|
|
|
|
rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
|
|
|
|
apr->ln - 1);
|
|
|
|
break;
|
|
|
|
case PN532_AUTOPOLL_TYPE_FELICA212:
|
|
|
|
case PN532_AUTOPOLL_TYPE_FELICA424:
|
|
|
|
dev_dbg(dev->dev, "FELICA\n");
|
|
|
|
rc = pn533_target_found_felica(&nfc_tgt, apr->tgdata,
|
|
|
|
apr->ln - 1);
|
|
|
|
break;
|
|
|
|
case PN532_AUTOPOLL_TYPE_JEWEL:
|
|
|
|
dev_dbg(dev->dev, "JEWEL\n");
|
|
|
|
rc = pn533_target_found_jewel(&nfc_tgt, apr->tgdata,
|
|
|
|
apr->ln - 1);
|
|
|
|
break;
|
|
|
|
case PN532_AUTOPOLL_TYPE_ISOB:
|
|
|
|
dev_dbg(dev->dev, "ISOB\n");
|
|
|
|
rc = pn533_target_found_type_b(&nfc_tgt, apr->tgdata,
|
|
|
|
apr->ln - 1);
|
|
|
|
break;
|
|
|
|
case PN532_AUTOPOLL_TYPE_MIFARE:
|
|
|
|
dev_dbg(dev->dev, "Mifare\n");
|
|
|
|
rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
|
|
|
|
apr->ln - 1);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
nfc_err(dev->dev,
|
|
|
|
"Unknown current poll modulation\n");
|
|
|
|
rc = -EPROTO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) {
|
|
|
|
nfc_err(dev->dev,
|
|
|
|
"The Tg found doesn't have the desired protocol\n");
|
|
|
|
rc = -EAGAIN;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev->tgt_available_prots = nfc_tgt.supported_protocols;
|
|
|
|
apr = (struct pn532_autopoll_resp *)
|
|
|
|
(apr->tgdata + (apr->ln - 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
pn533_poll_reset_mod_list(dev);
|
|
|
|
nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);
|
|
|
|
|
|
|
|
done:
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
stop_poll:
|
|
|
|
nfc_err(dev->dev, "autopoll operation has been stopped\n");
|
|
|
|
|
|
|
|
pn533_poll_reset_mod_list(dev);
|
|
|
|
dev->poll_protocols = 0;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
static int pn533_poll_complete(struct pn533 *dev, void *arg,
|
2012-12-10 17:42:48 +04:00
|
|
|
struct sk_buff *resp)
|
2012-05-30 19:20:25 +04:00
|
|
|
{
|
|
|
|
struct pn533_poll_modulations *cur_mod;
|
2012-05-31 01:54:55 +04:00
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
if (IS_ERR(resp)) {
|
|
|
|
rc = PTR_ERR(resp);
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "%s Poll complete error %d\n",
|
2013-04-05 23:27:38 +04:00
|
|
|
__func__, rc);
|
2012-12-10 17:42:48 +04:00
|
|
|
|
|
|
|
if (rc == -ENOENT) {
|
|
|
|
if (dev->poll_mod_count != 0)
|
|
|
|
return rc;
|
2016-03-25 17:46:53 +03:00
|
|
|
goto stop_poll;
|
2012-12-10 17:42:48 +04:00
|
|
|
} else if (rc < 0) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Error %d when running poll\n", rc);
|
2012-12-10 17:42:48 +04:00
|
|
|
goto stop_poll;
|
|
|
|
}
|
2012-05-30 19:20:25 +04:00
|
|
|
}
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
|
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
if (cur_mod->len == 0) { /* Target mode */
|
2012-05-30 19:20:25 +04:00
|
|
|
del_timer(&dev->listen_timer);
|
2012-12-10 17:42:48 +04:00
|
|
|
rc = pn533_init_target_complete(dev, resp);
|
|
|
|
goto done;
|
2012-05-30 19:20:25 +04:00
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
/* Initiator mode */
|
|
|
|
rc = pn533_start_poll_complete(dev, resp);
|
|
|
|
if (!rc)
|
|
|
|
goto done;
|
2012-05-30 19:20:25 +04:00
|
|
|
|
2013-04-03 10:02:00 +04:00
|
|
|
if (!dev->poll_mod_count) {
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "Polling has been stopped\n");
|
2013-04-03 10:02:00 +04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
pn533_poll_next_mod(dev);
|
2013-06-26 20:16:21 +04:00
|
|
|
/* Not target found, turn radio off */
|
|
|
|
queue_work(dev->wq, &dev->rf_work);
|
2012-05-30 19:20:25 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
done:
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return rc;
|
2012-05-30 19:20:25 +04:00
|
|
|
|
|
|
|
stop_poll:
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "Polling operation has been stopped\n");
|
2012-12-10 17:42:48 +04:00
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
pn533_poll_reset_mod_list(dev);
|
|
|
|
dev->poll_protocols = 0;
|
2012-12-10 17:42:48 +04:00
|
|
|
return rc;
|
2012-05-31 01:54:55 +04:00
|
|
|
}
|
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
static struct sk_buff *pn533_alloc_poll_in_frame(struct pn533 *dev,
|
|
|
|
struct pn533_poll_modulations *mod)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
2012-12-10 17:42:48 +04:00
|
|
|
struct sk_buff *skb;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, mod->len);
|
2012-12-10 17:42:48 +04:00
|
|
|
if (!skb)
|
|
|
|
return NULL;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(skb, &mod->data, mod->len);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
return skb;
|
2012-05-30 19:20:25 +04:00
|
|
|
}
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
static int pn533_send_poll_frame(struct pn533 *dev)
|
|
|
|
{
|
2012-12-10 17:42:48 +04:00
|
|
|
struct pn533_poll_modulations *mod;
|
|
|
|
struct sk_buff *skb;
|
2012-05-30 19:20:25 +04:00
|
|
|
int rc;
|
2012-12-10 17:42:48 +04:00
|
|
|
u8 cmd_code;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
mod = dev->poll_mod_active[dev->poll_mod_curr];
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s mod len %d\n",
|
2013-04-05 23:27:37 +04:00
|
|
|
__func__, mod->len);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:51 +03:00
|
|
|
if ((dev->poll_protocols & NFC_PROTO_NFC_DEP_MASK) && dev->poll_dep) {
|
2013-08-21 17:06:55 +04:00
|
|
|
dev->poll_dep = 0;
|
|
|
|
return pn533_poll_dep(dev->nfc_dev);
|
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:48 +04:00
|
|
|
if (mod->len == 0) { /* Listen mode */
|
|
|
|
cmd_code = PN533_CMD_TG_INIT_AS_TARGET;
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_poll_tg_frame(dev);
|
2012-12-10 17:42:48 +04:00
|
|
|
} else { /* Polling mode */
|
|
|
|
cmd_code = PN533_CMD_IN_LIST_PASSIVE_TARGET;
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_poll_in_frame(dev, mod);
|
2012-12-10 17:42:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!skb) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "Failed to allocate skb\n");
|
2012-12-10 17:42:48 +04:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = pn533_send_cmd_async(dev, cmd_code, skb, pn533_poll_complete,
|
|
|
|
NULL);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_kfree_skb(skb);
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "Polling loop error %d\n", rc);
|
2012-12-10 17:42:48 +04:00
|
|
|
}
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pn533_wq_poll(struct work_struct *work)
|
|
|
|
{
|
2013-07-03 16:50:36 +04:00
|
|
|
struct pn533 *dev = container_of(work, struct pn533, poll_work.work);
|
2012-05-30 19:20:25 +04:00
|
|
|
struct pn533_poll_modulations *cur_mod;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev,
|
2013-04-05 23:27:37 +04:00
|
|
|
"%s cancel_listen %d modulation len %d\n",
|
|
|
|
__func__, dev->cancel_listen, cur_mod->len);
|
2012-05-30 19:20:25 +04:00
|
|
|
|
|
|
|
if (dev->cancel_listen == 1) {
|
|
|
|
dev->cancel_listen = 0;
|
2016-03-25 17:46:53 +03:00
|
|
|
dev->phy_ops->abort_cmd(dev, GFP_ATOMIC);
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
rc = pn533_send_poll_frame(dev);
|
|
|
|
if (rc)
|
|
|
|
return;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
if (cur_mod->len == 0 && dev->poll_mod_count > 1)
|
|
|
|
mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ);
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2012-05-15 17:57:06 +04:00
|
|
|
static int pn533_start_poll(struct nfc_dev *nfc_dev,
|
|
|
|
u32 im_protocols, u32 tm_protocols)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
2013-08-21 17:12:06 +04:00
|
|
|
struct pn533_poll_modulations *cur_mod;
|
2019-10-29 17:47:43 +03:00
|
|
|
struct sk_buff *skb;
|
2013-07-03 17:14:17 +04:00
|
|
|
u8 rand_mod;
|
2013-08-21 17:12:06 +04:00
|
|
|
int rc;
|
2012-05-15 17:57:06 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev,
|
2013-04-05 23:27:37 +04:00
|
|
|
"%s: im protocols 0x%x tm protocols 0x%x\n",
|
|
|
|
__func__, im_protocols, tm_protocols);
|
2012-05-15 17:57:06 +04:00
|
|
|
|
|
|
|
if (dev->tgt_active_prot) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Cannot poll with a target already activated\n");
|
2012-05-15 17:57:06 +04:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
2012-05-31 22:01:32 +04:00
|
|
|
if (dev->tgt_mode) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Cannot poll while already being activated\n");
|
2012-05-31 22:01:32 +04:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
if (tm_protocols) {
|
|
|
|
dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len);
|
|
|
|
if (dev->gb == NULL)
|
|
|
|
tm_protocols = 0;
|
|
|
|
}
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
dev->poll_protocols = im_protocols;
|
|
|
|
dev->listen_protocols = tm_protocols;
|
2019-10-29 17:47:43 +03:00
|
|
|
if (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL) {
|
|
|
|
skb = pn533_alloc_skb(dev, 4 + 6);
|
|
|
|
if (!skb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_POLLNR_INFINITE;
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) = PN532_AUTOPOLL_PERIOD;
|
|
|
|
|
|
|
|
if ((im_protocols & NFC_PROTO_MIFARE_MASK) &&
|
|
|
|
(im_protocols & NFC_PROTO_ISO14443_MASK) &&
|
|
|
|
(im_protocols & NFC_PROTO_NFC_DEP_MASK))
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_GENERIC_106;
|
|
|
|
else {
|
|
|
|
if (im_protocols & NFC_PROTO_MIFARE_MASK)
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_MIFARE;
|
|
|
|
|
|
|
|
if (im_protocols & NFC_PROTO_ISO14443_MASK)
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_ISOA;
|
|
|
|
|
|
|
|
if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106;
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212;
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (im_protocols & NFC_PROTO_FELICA_MASK ||
|
|
|
|
im_protocols & NFC_PROTO_NFC_DEP_MASK) {
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_FELICA212;
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_FELICA424;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (im_protocols & NFC_PROTO_JEWEL_MASK)
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_JEWEL;
|
|
|
|
|
|
|
|
if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_ISOB;
|
|
|
|
|
|
|
|
if (tm_protocols)
|
|
|
|
*((u8 *)skb_put(skb, sizeof(u8))) =
|
|
|
|
PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106;
|
|
|
|
|
|
|
|
rc = pn533_send_cmd_async(dev, PN533_CMD_IN_AUTOPOLL, skb,
|
|
|
|
pn533_autopoll_complete, NULL);
|
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
else
|
|
|
|
dev->poll_mod_count++;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
|
2012-05-31 01:54:55 +04:00
|
|
|
|
2013-07-03 17:14:17 +04:00
|
|
|
/* Do not always start polling from the same modulation */
|
|
|
|
get_random_bytes(&rand_mod, sizeof(rand_mod));
|
|
|
|
rand_mod %= dev->poll_mod_count;
|
|
|
|
dev->poll_mod_curr = rand_mod;
|
|
|
|
|
2013-08-21 17:12:06 +04:00
|
|
|
cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
|
|
|
|
|
|
|
|
rc = pn533_send_poll_frame(dev);
|
|
|
|
|
|
|
|
/* Start listen timer */
|
|
|
|
if (!rc && cur_mod->len == 0 && dev->poll_mod_count > 1)
|
|
|
|
mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ);
|
|
|
|
|
|
|
|
return rc;
|
2012-05-15 17:57:06 +04:00
|
|
|
}
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
static void pn533_stop_poll(struct nfc_dev *nfc_dev)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
del_timer(&dev->listen_timer);
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
if (!dev->poll_mod_count) {
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev,
|
2013-04-05 23:27:37 +04:00
|
|
|
"Polling operation was not running\n");
|
2011-07-02 02:31:37 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev->phy_ops->abort_cmd(dev, GFP_KERNEL);
|
2013-07-03 16:50:36 +04:00
|
|
|
flush_delayed_work(&dev->poll_work);
|
2012-05-21 18:20:01 +04:00
|
|
|
pn533_poll_reset_mod_list(dev);
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_activate_target_nfcdep(struct pn533 *dev)
|
|
|
|
{
|
2012-11-26 17:18:38 +04:00
|
|
|
struct pn533_cmd_activate_response *rsp;
|
2011-12-14 19:43:10 +04:00
|
|
|
u16 gt_len;
|
2011-07-02 02:31:37 +04:00
|
|
|
int rc;
|
2012-11-26 17:18:38 +04:00
|
|
|
struct sk_buff *skb;
|
|
|
|
struct sk_buff *resp;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/
|
2012-11-26 17:18:38 +04:00
|
|
|
if (!skb)
|
|
|
|
return -ENOMEM;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, 1); /* TG */
|
|
|
|
skb_put_u8(skb, 0); /* Next */
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-11-26 17:18:38 +04:00
|
|
|
resp = pn533_send_cmd_sync(dev, PN533_CMD_IN_ATR, skb);
|
|
|
|
if (IS_ERR(resp))
|
|
|
|
return PTR_ERR(resp);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-12-10 17:42:50 +04:00
|
|
|
rsp = (struct pn533_cmd_activate_response *)resp->data;
|
2012-11-26 17:18:38 +04:00
|
|
|
rc = rsp->status & PN533_CMD_RET_MASK;
|
2012-12-21 13:39:01 +04:00
|
|
|
if (rc != PN533_CMD_RET_SUCCESS) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Target activation failed (error 0x%x)\n", rc);
|
2012-11-26 17:18:38 +04:00
|
|
|
dev_kfree_skb(resp);
|
2011-07-02 02:31:37 +04:00
|
|
|
return -EIO;
|
2012-12-21 13:39:01 +04:00
|
|
|
}
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2011-12-14 19:43:10 +04:00
|
|
|
/* ATR_RES general bytes are located at offset 16 */
|
2012-11-26 17:18:38 +04:00
|
|
|
gt_len = resp->len - 16;
|
|
|
|
rc = nfc_set_remote_general_bytes(dev->nfc_dev, rsp->gt, gt_len);
|
2011-12-14 19:43:10 +04:00
|
|
|
|
2012-11-26 17:18:38 +04:00
|
|
|
dev_kfree_skb(resp);
|
2011-12-14 19:43:10 +04:00
|
|
|
return rc;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2012-05-07 14:31:13 +04:00
|
|
|
static int pn533_activate_target(struct nfc_dev *nfc_dev,
|
|
|
|
struct nfc_target *target, u32 protocol)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s: protocol=%u\n", __func__, protocol);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
if (dev->poll_mod_count) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:37 +04:00
|
|
|
"Cannot activate while polling\n");
|
2011-07-02 02:31:37 +04:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dev->tgt_active_prot) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"There is already an active target\n");
|
2011-07-02 02:31:37 +04:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!dev->tgt_available_prots) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"There is no available target to activate\n");
|
2011-07-02 02:31:37 +04:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(dev->tgt_available_prots & (1 << protocol))) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Target doesn't support requested proto %u\n",
|
|
|
|
protocol);
|
2011-07-02 02:31:37 +04:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (protocol == NFC_PROTO_NFC_DEP) {
|
|
|
|
rc = pn533_activate_target_nfcdep(dev);
|
|
|
|
if (rc) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Activating target with DEP failed %d\n", rc);
|
2011-07-02 02:31:37 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dev->tgt_active_prot = protocol;
|
|
|
|
dev->tgt_available_prots = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:52 +03:00
|
|
|
static int pn533_deactivate_target_complete(struct pn533 *dev, void *arg,
|
|
|
|
struct sk_buff *resp)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2016-03-25 17:46:52 +03:00
|
|
|
|
|
|
|
if (IS_ERR(resp)) {
|
|
|
|
rc = PTR_ERR(resp);
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "Target release error %d\n", rc);
|
2016-03-25 17:46:52 +03:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = resp->data[0] & PN533_CMD_RET_MASK;
|
|
|
|
if (rc != PN533_CMD_RET_SUCCESS)
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2016-03-25 17:46:52 +03:00
|
|
|
"Error 0x%x when releasing the target\n", rc);
|
|
|
|
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-05-07 14:31:13 +04:00
|
|
|
static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
|
2015-10-26 00:54:43 +03:00
|
|
|
struct nfc_target *target, u8 mode)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
2012-11-26 17:18:38 +04:00
|
|
|
struct sk_buff *skb;
|
2011-07-02 02:31:37 +04:00
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
if (!dev->tgt_active_prot) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "There is no active target\n");
|
2011-07-02 02:31:37 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev->tgt_active_prot = 0;
|
2012-04-10 21:43:18 +04:00
|
|
|
skb_queue_purge(&dev->resp_q);
|
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, sizeof(u8));
|
2012-11-26 17:18:38 +04:00
|
|
|
if (!skb)
|
|
|
|
return;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, 1); /* TG*/
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:52 +03:00
|
|
|
rc = pn533_send_cmd_async(dev, PN533_CMD_IN_RELEASE, skb,
|
|
|
|
pn533_deactivate_target_complete, NULL);
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_kfree_skb(skb);
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "Target release error %d\n", rc);
|
2016-03-25 17:46:52 +03:00
|
|
|
}
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2011-12-14 19:43:11 +04:00
|
|
|
|
|
|
|
static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
|
2012-12-10 17:42:45 +04:00
|
|
|
struct sk_buff *resp)
|
2011-12-14 19:43:11 +04:00
|
|
|
{
|
2012-12-10 17:42:45 +04:00
|
|
|
struct pn533_cmd_jump_dep_response *rsp;
|
2011-12-14 19:43:11 +04:00
|
|
|
u8 target_gt_len;
|
|
|
|
int rc;
|
2012-12-10 17:42:45 +04:00
|
|
|
u8 active = *(u8 *)arg;
|
2012-10-11 16:04:00 +04:00
|
|
|
|
|
|
|
kfree(arg);
|
2011-12-14 19:43:11 +04:00
|
|
|
|
2012-12-10 17:42:45 +04:00
|
|
|
if (IS_ERR(resp))
|
|
|
|
return PTR_ERR(resp);
|
2011-12-14 19:43:11 +04:00
|
|
|
|
|
|
|
if (dev->tgt_available_prots &&
|
|
|
|
!(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"The target does not support DEP\n");
|
2012-12-10 17:42:45 +04:00
|
|
|
rc = -EINVAL;
|
|
|
|
goto error;
|
2011-12-14 19:43:11 +04:00
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:45 +04:00
|
|
|
rsp = (struct pn533_cmd_jump_dep_response *)resp->data;
|
|
|
|
|
|
|
|
rc = rsp->status & PN533_CMD_RET_MASK;
|
2011-12-14 19:43:11 +04:00
|
|
|
if (rc != PN533_CMD_RET_SUCCESS) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Bringing DEP link up failed (error 0x%x)\n", rc);
|
2012-12-10 17:42:45 +04:00
|
|
|
goto error;
|
2011-12-14 19:43:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!dev->tgt_available_prots) {
|
2012-12-10 17:42:45 +04:00
|
|
|
struct nfc_target nfc_target;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "Creating new target\n");
|
2011-12-14 19:43:11 +04:00
|
|
|
|
|
|
|
nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
|
2012-03-05 04:03:47 +04:00
|
|
|
nfc_target.nfcid1_len = 10;
|
2012-12-10 17:42:45 +04:00
|
|
|
memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len);
|
2011-12-14 19:43:11 +04:00
|
|
|
rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1);
|
|
|
|
if (rc)
|
2012-12-10 17:42:45 +04:00
|
|
|
goto error;
|
2011-12-14 19:43:11 +04:00
|
|
|
|
|
|
|
dev->tgt_available_prots = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev->tgt_active_prot = NFC_PROTO_NFC_DEP;
|
|
|
|
|
|
|
|
/* ATR_RES general bytes are located at offset 17 */
|
2012-12-10 17:42:45 +04:00
|
|
|
target_gt_len = resp->len - 17;
|
2011-12-14 19:43:11 +04:00
|
|
|
rc = nfc_set_remote_general_bytes(dev->nfc_dev,
|
2012-12-10 17:42:45 +04:00
|
|
|
rsp->gt, target_gt_len);
|
2011-12-14 19:43:11 +04:00
|
|
|
if (rc == 0)
|
|
|
|
rc = nfc_dep_link_is_up(dev->nfc_dev,
|
2012-12-10 17:42:45 +04:00
|
|
|
dev->nfc_dev->targets[0].idx,
|
|
|
|
!active, NFC_RF_INITIATOR);
|
2011-12-14 19:43:11 +04:00
|
|
|
|
2012-12-10 17:42:45 +04:00
|
|
|
error:
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return rc;
|
2011-12-14 19:43:11 +04:00
|
|
|
}
|
|
|
|
|
2013-06-26 20:16:21 +04:00
|
|
|
static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf);
|
2012-05-07 14:31:13 +04:00
|
|
|
static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
|
2012-12-10 17:42:50 +04:00
|
|
|
u8 comm_mode, u8 *gb, size_t gb_len)
|
2011-12-14 19:43:11 +04:00
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
2012-12-10 17:42:45 +04:00
|
|
|
struct sk_buff *skb;
|
2013-07-01 12:58:12 +04:00
|
|
|
int rc, skb_len;
|
|
|
|
u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE];
|
2012-05-29 23:45:21 +04:00
|
|
|
u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
|
2011-12-14 19:43:11 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2011-12-14 19:43:11 +04:00
|
|
|
|
|
|
|
if (dev->poll_mod_count) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Cannot bring the DEP link up while polling\n");
|
2011-12-14 19:43:11 +04:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dev->tgt_active_prot) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"There is already an active target\n");
|
2011-12-14 19:43:11 +04:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:45 +04:00
|
|
|
skb_len = 3 + gb_len; /* ActPass + BR + Next */
|
2013-07-01 12:58:12 +04:00
|
|
|
skb_len += PASSIVE_DATA_LEN;
|
2012-05-29 23:45:21 +04:00
|
|
|
|
2013-07-01 12:58:12 +04:00
|
|
|
/* NFCID3 */
|
|
|
|
skb_len += NFC_NFCID3_MAXSIZE;
|
|
|
|
if (target && !target->nfcid2_len) {
|
|
|
|
nfcid3[0] = 0x1;
|
|
|
|
nfcid3[1] = 0xfe;
|
|
|
|
get_random_bytes(nfcid3 + 2, 6);
|
|
|
|
}
|
2013-05-27 17:29:11 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, skb_len);
|
2012-12-10 17:42:45 +04:00
|
|
|
if (!skb)
|
2011-12-14 19:43:11 +04:00
|
|
|
return -ENOMEM;
|
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, !comm_mode); /* ActPass */
|
|
|
|
skb_put_u8(skb, 0x02); /* 424 kbps */
|
2012-12-10 17:42:45 +04:00
|
|
|
|
|
|
|
next = skb_put(skb, 1); /* Next */
|
|
|
|
*next = 0;
|
2011-12-14 19:43:11 +04:00
|
|
|
|
2013-07-01 12:58:12 +04:00
|
|
|
/* Copy passive data */
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(skb, passive_data, PASSIVE_DATA_LEN);
|
2013-07-01 12:58:12 +04:00
|
|
|
*next |= 1;
|
2012-05-29 23:45:21 +04:00
|
|
|
|
2013-07-01 12:58:12 +04:00
|
|
|
/* Copy NFCID3 (which is NFCID2 from SENSF_RES) */
|
|
|
|
if (target && target->nfcid2_len)
|
2013-05-27 17:29:11 +04:00
|
|
|
memcpy(skb_put(skb, NFC_NFCID3_MAXSIZE), target->nfcid2,
|
|
|
|
target->nfcid2_len);
|
2013-07-01 12:58:12 +04:00
|
|
|
else
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(skb, nfcid3, NFC_NFCID3_MAXSIZE);
|
2013-07-01 12:58:12 +04:00
|
|
|
*next |= 2;
|
2013-05-27 17:29:11 +04:00
|
|
|
|
2012-03-05 04:03:50 +04:00
|
|
|
if (gb != NULL && gb_len > 0) {
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(skb, gb, gb_len);
|
2012-12-10 17:42:45 +04:00
|
|
|
*next |= 4; /* We have some Gi */
|
2011-12-14 19:43:11 +04:00
|
|
|
} else {
|
2012-12-10 17:42:45 +04:00
|
|
|
*next = 0;
|
2011-12-14 19:43:11 +04:00
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:45 +04:00
|
|
|
arg = kmalloc(sizeof(*arg), GFP_KERNEL);
|
|
|
|
if (!arg) {
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2011-12-14 19:43:11 +04:00
|
|
|
|
2012-12-10 17:42:45 +04:00
|
|
|
*arg = !comm_mode;
|
2011-12-14 19:43:11 +04:00
|
|
|
|
2013-06-26 20:16:21 +04:00
|
|
|
pn533_rf_field(dev->nfc_dev, 0);
|
|
|
|
|
2012-12-10 17:42:45 +04:00
|
|
|
rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb,
|
|
|
|
pn533_in_dep_link_up_complete, arg);
|
|
|
|
|
|
|
|
if (rc < 0) {
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
kfree(arg);
|
|
|
|
}
|
2011-12-14 19:43:11 +04:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
|
|
|
|
{
|
2012-05-30 19:20:25 +04:00
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-12-10 17:42:55 +04:00
|
|
|
|
2012-05-30 19:20:25 +04:00
|
|
|
pn533_poll_reset_mod_list(dev);
|
|
|
|
|
2013-04-03 10:02:14 +04:00
|
|
|
if (dev->tgt_mode || dev->tgt_active_prot)
|
2016-03-25 17:46:53 +03:00
|
|
|
dev->phy_ops->abort_cmd(dev, GFP_KERNEL);
|
2012-05-31 22:01:32 +04:00
|
|
|
|
|
|
|
dev->tgt_active_prot = 0;
|
|
|
|
dev->tgt_mode = 0;
|
|
|
|
|
|
|
|
skb_queue_purge(&dev->resp_q);
|
2011-12-14 19:43:11 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
struct pn533_data_exchange_arg {
|
|
|
|
data_exchange_cb_t cb;
|
|
|
|
void *cb_context;
|
|
|
|
};
|
|
|
|
|
2012-04-10 21:43:18 +04:00
|
|
|
static struct sk_buff *pn533_build_response(struct pn533 *dev)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb, *tmp, *t;
|
|
|
|
unsigned int skb_len = 0, tmp_len = 0;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-04-10 21:43:18 +04:00
|
|
|
|
|
|
|
if (skb_queue_empty(&dev->resp_q))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (skb_queue_len(&dev->resp_q) == 1) {
|
|
|
|
skb = skb_dequeue(&dev->resp_q);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb_queue_walk_safe(&dev->resp_q, tmp, t)
|
|
|
|
skb_len += tmp->len;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s total length %d\n",
|
2013-04-05 23:27:37 +04:00
|
|
|
__func__, skb_len);
|
2012-04-10 21:43:18 +04:00
|
|
|
|
|
|
|
skb = alloc_skb(skb_len, GFP_KERNEL);
|
|
|
|
if (skb == NULL)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
skb_put(skb, skb_len);
|
|
|
|
|
|
|
|
skb_queue_walk_safe(&dev->resp_q, tmp, t) {
|
|
|
|
memcpy(skb->data + tmp_len, tmp->data, tmp->len);
|
|
|
|
tmp_len += tmp->len;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
skb_queue_purge(&dev->resp_q);
|
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
|
2012-12-10 17:42:46 +04:00
|
|
|
struct sk_buff *resp)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
|
|
|
struct pn533_data_exchange_arg *arg = _arg;
|
2012-12-10 17:42:46 +04:00
|
|
|
struct sk_buff *skb;
|
|
|
|
int rc = 0;
|
|
|
|
u8 status, ret, mi;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
if (IS_ERR(resp)) {
|
|
|
|
rc = PTR_ERR(resp);
|
|
|
|
goto _error;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
status = resp->data[0];
|
|
|
|
ret = status & PN533_CMD_RET_MASK;
|
|
|
|
mi = status & PN533_CMD_MI_MASK;
|
|
|
|
|
|
|
|
skb_pull(resp, sizeof(status));
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
if (ret != PN533_CMD_RET_SUCCESS) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Exchanging data failed (error 0x%x)\n", ret);
|
2012-12-10 17:42:46 +04:00
|
|
|
rc = -EIO;
|
2011-07-02 02:31:37 +04:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
skb_queue_tail(&dev->resp_q, resp);
|
2012-04-10 21:43:18 +04:00
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
if (mi) {
|
|
|
|
dev->cmd_complete_mi_arg = arg;
|
2013-06-13 17:43:28 +04:00
|
|
|
queue_work(dev->wq, &dev->mi_rx_work);
|
|
|
|
return -EINPROGRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Prepare for the next round */
|
|
|
|
if (skb_queue_len(&dev->fragment_skb) > 0) {
|
|
|
|
dev->cmd_complete_dep_arg = arg;
|
|
|
|
queue_work(dev->wq, &dev->mi_tx_work);
|
|
|
|
|
2012-04-10 21:43:18 +04:00
|
|
|
return -EINPROGRESS;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2012-04-10 21:43:18 +04:00
|
|
|
skb = pn533_build_response(dev);
|
2015-04-05 15:06:36 +03:00
|
|
|
if (!skb) {
|
|
|
|
rc = -ENOMEM;
|
2012-04-10 21:43:18 +04:00
|
|
|
goto error;
|
2015-04-05 15:06:36 +03:00
|
|
|
}
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-04-10 21:43:18 +04:00
|
|
|
arg->cb(arg->cb_context, skb, 0);
|
2011-07-02 02:31:37 +04:00
|
|
|
kfree(arg);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2012-12-10 17:42:46 +04:00
|
|
|
dev_kfree_skb(resp);
|
|
|
|
_error:
|
2012-04-10 21:43:18 +04:00
|
|
|
skb_queue_purge(&dev->resp_q);
|
2012-12-10 17:42:46 +04:00
|
|
|
arg->cb(arg->cb_context, NULL, rc);
|
2011-07-02 02:31:37 +04:00
|
|
|
kfree(arg);
|
2012-12-10 17:42:46 +04:00
|
|
|
return rc;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
/*
|
|
|
|
* Receive an incoming pn533 frame. skb contains only header and payload.
|
|
|
|
* If skb == NULL, it is a notification that the link below is dead.
|
|
|
|
*/
|
|
|
|
void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status)
|
|
|
|
{
|
2016-04-21 17:43:53 +03:00
|
|
|
if (!dev->cmd)
|
|
|
|
goto sched_wq;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev->cmd->status = status;
|
|
|
|
|
2016-04-21 17:43:53 +03:00
|
|
|
if (status != 0) {
|
|
|
|
dev_dbg(dev->dev, "%s: Error received: %d\n", __func__, status);
|
|
|
|
goto sched_wq;
|
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
if (skb == NULL) {
|
|
|
|
pr_err("NULL Frame -> link is dead\n");
|
|
|
|
goto sched_wq;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pn533_rx_frame_is_ack(skb->data)) {
|
|
|
|
dev_dbg(dev->dev, "%s: Received ACK frame\n", __func__);
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, skb->data,
|
|
|
|
dev->ops->rx_frame_size(skb->data), false);
|
|
|
|
|
|
|
|
if (!dev->ops->rx_is_frame_valid(skb->data, dev)) {
|
|
|
|
nfc_err(dev->dev, "Received an invalid frame\n");
|
|
|
|
dev->cmd->status = -EIO;
|
|
|
|
} else if (!pn533_rx_frame_is_cmd_response(dev, skb->data)) {
|
|
|
|
nfc_err(dev->dev, "It it not the response to the last command\n");
|
|
|
|
dev->cmd->status = -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev->cmd->resp = skb;
|
|
|
|
|
|
|
|
sched_wq:
|
|
|
|
queue_work(dev->wq, &dev->cmd_complete_work);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(pn533_recv_frame);
|
|
|
|
|
2013-06-13 17:43:28 +04:00
|
|
|
/* Split the Tx skb into small chunks */
|
|
|
|
static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct sk_buff *frag;
|
|
|
|
int frag_size;
|
|
|
|
|
|
|
|
do {
|
|
|
|
/* Remaining size */
|
|
|
|
if (skb->len > PN533_CMD_DATAFRAME_MAXLEN)
|
|
|
|
frag_size = PN533_CMD_DATAFRAME_MAXLEN;
|
|
|
|
else
|
|
|
|
frag_size = skb->len;
|
|
|
|
|
|
|
|
/* Allocate and reserve */
|
|
|
|
frag = pn533_alloc_skb(dev, frag_size);
|
|
|
|
if (!frag) {
|
|
|
|
skb_queue_purge(&dev->fragment_skb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-09-23 14:24:37 +04:00
|
|
|
if (!dev->tgt_mode) {
|
|
|
|
/* Reserve the TG/MI byte */
|
|
|
|
skb_reserve(frag, 1);
|
|
|
|
|
|
|
|
/* MI + TG */
|
|
|
|
if (frag_size == PN533_CMD_DATAFRAME_MAXLEN)
|
networking: make skb_push & __skb_push return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions return void * and remove all the casts across
the tree, adding a (u8 *) cast only where the unsigned char pointer
was used directly, all done with the following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
@@
expression SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- fn(SKB, LEN)[0]
+ *(u8 *)fn(SKB, LEN)
Note that the last part there converts from push(...)[0] to the
more idiomatic *(u8 *)push(...).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:23 +03:00
|
|
|
*(u8 *)skb_push(frag, sizeof(u8)) =
|
|
|
|
(PN533_CMD_MI_MASK | 1);
|
2013-09-23 14:24:37 +04:00
|
|
|
else
|
networking: make skb_push & __skb_push return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions return void * and remove all the casts across
the tree, adding a (u8 *) cast only where the unsigned char pointer
was used directly, all done with the following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
@@
expression SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- fn(SKB, LEN)[0]
+ *(u8 *)fn(SKB, LEN)
Note that the last part there converts from push(...)[0] to the
more idiomatic *(u8 *)push(...).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:23 +03:00
|
|
|
*(u8 *)skb_push(frag, sizeof(u8)) = 1; /* TG */
|
2013-09-23 14:24:37 +04:00
|
|
|
}
|
2013-06-13 17:43:28 +04:00
|
|
|
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(frag, skb->data, frag_size);
|
2013-06-13 17:43:28 +04:00
|
|
|
|
|
|
|
/* Reduce the size of incoming buffer */
|
|
|
|
skb_pull(skb, frag_size);
|
|
|
|
|
|
|
|
/* Add this to skb_queue */
|
|
|
|
skb_queue_tail(&dev->fragment_skb, frag);
|
|
|
|
|
|
|
|
} while (skb->len > 0);
|
|
|
|
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
|
|
|
|
return skb_queue_len(&dev->fragment_skb);
|
|
|
|
}
|
|
|
|
|
2012-05-16 17:55:48 +04:00
|
|
|
static int pn533_transceive(struct nfc_dev *nfc_dev,
|
|
|
|
struct nfc_target *target, struct sk_buff *skb,
|
|
|
|
data_exchange_cb_t cb, void *cb_context)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
2012-12-10 17:42:46 +04:00
|
|
|
struct pn533_data_exchange_arg *arg = NULL;
|
2011-07-02 02:31:37 +04:00
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
if (!dev->tgt_active_prot) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Can't exchange data if there is no active target\n");
|
2011-07-02 02:31:37 +04:00
|
|
|
rc = -EINVAL;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
arg = kmalloc(sizeof(*arg), GFP_KERNEL);
|
2011-07-02 02:31:37 +04:00
|
|
|
if (!arg) {
|
|
|
|
rc = -ENOMEM;
|
2012-12-10 17:42:46 +04:00
|
|
|
goto error;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
arg->cb = cb;
|
|
|
|
arg->cb_context = cb_context;
|
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
switch (dev->device_type) {
|
|
|
|
case PN533_DEVICE_PASORI:
|
|
|
|
if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
|
|
|
|
rc = pn533_send_data_async(dev, PN533_CMD_IN_COMM_THRU,
|
|
|
|
skb,
|
|
|
|
pn533_data_exchange_complete,
|
|
|
|
arg);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2020-08-24 01:36:59 +03:00
|
|
|
fallthrough;
|
2012-12-10 17:42:46 +04:00
|
|
|
default:
|
2013-06-13 17:43:28 +04:00
|
|
|
/* jumbo frame ? */
|
|
|
|
if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
|
|
|
|
rc = pn533_fill_fragment_skbs(dev, skb);
|
|
|
|
if (rc <= 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
skb = skb_dequeue(&dev->fragment_skb);
|
|
|
|
if (!skb) {
|
|
|
|
rc = -EIO;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
networking: make skb_push & __skb_push return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions return void * and remove all the casts across
the tree, adding a (u8 *) cast only where the unsigned char pointer
was used directly, all done with the following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
@@
expression SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- fn(SKB, LEN)[0]
+ *(u8 *)fn(SKB, LEN)
Note that the last part there converts from push(...)[0] to the
more idiomatic *(u8 *)push(...).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:23 +03:00
|
|
|
*(u8 *)skb_push(skb, sizeof(u8)) = 1; /* TG */
|
2013-06-13 17:43:28 +04:00
|
|
|
}
|
2012-12-10 17:42:46 +04:00
|
|
|
|
|
|
|
rc = pn533_send_data_async(dev, PN533_CMD_IN_DATA_EXCHANGE,
|
|
|
|
skb, pn533_data_exchange_complete,
|
|
|
|
arg);
|
|
|
|
|
|
|
|
break;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
if (rc < 0) /* rc from send_async */
|
|
|
|
goto error;
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2012-12-10 17:42:46 +04:00
|
|
|
kfree(arg);
|
|
|
|
dev_kfree_skb(skb);
|
2011-07-02 02:31:37 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-05-31 02:09:11 +04:00
|
|
|
static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
|
2012-12-10 17:42:44 +04:00
|
|
|
struct sk_buff *resp)
|
2012-05-31 02:09:11 +04:00
|
|
|
{
|
2012-12-10 17:42:44 +04:00
|
|
|
u8 status;
|
2012-11-15 21:24:28 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-05-31 02:09:11 +04:00
|
|
|
|
2012-12-10 17:42:44 +04:00
|
|
|
if (IS_ERR(resp))
|
|
|
|
return PTR_ERR(resp);
|
2012-11-15 21:24:28 +04:00
|
|
|
|
2012-12-10 17:42:44 +04:00
|
|
|
status = resp->data[0];
|
2012-05-31 02:09:11 +04:00
|
|
|
|
2013-09-23 14:24:39 +04:00
|
|
|
/* Prepare for the next round */
|
|
|
|
if (skb_queue_len(&dev->fragment_skb) > 0) {
|
|
|
|
queue_work(dev->wq, &dev->mi_tm_tx_work);
|
|
|
|
return -EINPROGRESS;
|
|
|
|
}
|
2012-12-10 17:42:44 +04:00
|
|
|
dev_kfree_skb(resp);
|
2012-05-31 02:09:11 +04:00
|
|
|
|
2012-12-10 17:42:44 +04:00
|
|
|
if (status != 0) {
|
2012-05-31 02:09:11 +04:00
|
|
|
nfc_tm_deactivated(dev->nfc_dev);
|
|
|
|
|
2012-05-31 22:01:32 +04:00
|
|
|
dev->tgt_mode = 0;
|
|
|
|
|
2012-05-31 02:09:11 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
queue_work(dev->wq, &dev->tg_work);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-05-31 02:09:11 +04:00
|
|
|
|
2013-09-23 14:24:39 +04:00
|
|
|
/* let's split in multiple chunks if size's too big */
|
2012-12-10 17:42:44 +04:00
|
|
|
if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
|
2013-09-23 14:24:39 +04:00
|
|
|
rc = pn533_fill_fragment_skbs(dev, skb);
|
|
|
|
if (rc <= 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* get the first skb */
|
|
|
|
skb = skb_dequeue(&dev->fragment_skb);
|
|
|
|
if (!skb) {
|
|
|
|
rc = -EIO;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_META_DATA, skb,
|
|
|
|
pn533_tm_send_complete, NULL);
|
|
|
|
} else {
|
|
|
|
/* Send th skb */
|
|
|
|
rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_DATA, skb,
|
|
|
|
pn533_tm_send_complete, NULL);
|
2012-05-31 02:09:11 +04:00
|
|
|
}
|
|
|
|
|
2013-09-23 14:24:39 +04:00
|
|
|
error:
|
|
|
|
if (rc < 0) {
|
2012-12-10 17:42:44 +04:00
|
|
|
dev_kfree_skb(skb);
|
2013-09-23 14:24:39 +04:00
|
|
|
skb_queue_purge(&dev->fragment_skb);
|
|
|
|
}
|
2012-05-31 02:09:11 +04:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-04-10 21:43:18 +04:00
|
|
|
static void pn533_wq_mi_recv(struct work_struct *work)
|
|
|
|
{
|
2013-06-13 17:43:28 +04:00
|
|
|
struct pn533 *dev = container_of(work, struct pn533, mi_rx_work);
|
2012-12-10 17:42:46 +04:00
|
|
|
struct sk_buff *skb;
|
2012-04-10 21:43:18 +04:00
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-04-10 21:43:18 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN);
|
2012-12-10 17:42:46 +04:00
|
|
|
if (!skb)
|
|
|
|
goto error;
|
2012-04-10 21:43:18 +04:00
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
switch (dev->device_type) {
|
|
|
|
case PN533_DEVICE_PASORI:
|
|
|
|
if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
|
|
|
|
rc = pn533_send_cmd_direct_async(dev,
|
|
|
|
PN533_CMD_IN_COMM_THRU,
|
|
|
|
skb,
|
|
|
|
pn533_data_exchange_complete,
|
|
|
|
dev->cmd_complete_mi_arg);
|
2012-04-10 21:43:18 +04:00
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
break;
|
|
|
|
}
|
2020-08-24 01:36:59 +03:00
|
|
|
fallthrough;
|
2012-12-10 17:42:46 +04:00
|
|
|
default:
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, 1); /*TG*/
|
2012-04-10 21:43:18 +04:00
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
rc = pn533_send_cmd_direct_async(dev,
|
|
|
|
PN533_CMD_IN_DATA_EXCHANGE,
|
|
|
|
skb,
|
|
|
|
pn533_data_exchange_complete,
|
|
|
|
dev->cmd_complete_mi_arg);
|
2012-11-26 17:18:32 +04:00
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
break;
|
2012-04-10 21:43:18 +04:00
|
|
|
}
|
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
if (rc == 0) /* success */
|
2012-04-10 21:43:18 +04:00
|
|
|
return;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Error %d when trying to perform data_exchange\n", rc);
|
2012-04-10 21:43:18 +04:00
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
dev_kfree_skb(skb);
|
2013-04-03 10:02:07 +04:00
|
|
|
kfree(dev->cmd_complete_mi_arg);
|
2012-04-10 21:43:18 +04:00
|
|
|
|
2012-12-10 17:42:46 +04:00
|
|
|
error:
|
2016-03-25 17:46:53 +03:00
|
|
|
dev->phy_ops->send_ack(dev, GFP_KERNEL);
|
2012-08-18 01:47:54 +04:00
|
|
|
queue_work(dev->wq, &dev->cmd_work);
|
2012-04-10 21:43:18 +04:00
|
|
|
}
|
|
|
|
|
2013-06-13 17:43:28 +04:00
|
|
|
static void pn533_wq_mi_send(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = container_of(work, struct pn533, mi_tx_work);
|
|
|
|
struct sk_buff *skb;
|
|
|
|
int rc;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2013-06-13 17:43:28 +04:00
|
|
|
|
|
|
|
/* Grab the first skb in the queue */
|
|
|
|
skb = skb_dequeue(&dev->fragment_skb);
|
|
|
|
|
|
|
|
if (skb == NULL) { /* No more data */
|
|
|
|
/* Reset the queue for future use */
|
|
|
|
skb_queue_head_init(&dev->fragment_skb);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (dev->device_type) {
|
|
|
|
case PN533_DEVICE_PASORI:
|
|
|
|
if (dev->tgt_active_prot != NFC_PROTO_FELICA) {
|
|
|
|
rc = -EIO;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = pn533_send_cmd_direct_async(dev, PN533_CMD_IN_COMM_THRU,
|
|
|
|
skb,
|
|
|
|
pn533_data_exchange_complete,
|
|
|
|
dev->cmd_complete_dep_arg);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* Still some fragments? */
|
2016-03-25 17:46:53 +03:00
|
|
|
rc = pn533_send_cmd_direct_async(dev,
|
|
|
|
PN533_CMD_IN_DATA_EXCHANGE,
|
2013-06-13 17:43:28 +04:00
|
|
|
skb,
|
|
|
|
pn533_data_exchange_complete,
|
|
|
|
dev->cmd_complete_dep_arg);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc == 0) /* success */
|
|
|
|
return;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Error %d when trying to perform data_exchange\n", rc);
|
2013-06-13 17:43:28 +04:00
|
|
|
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
kfree(dev->cmd_complete_dep_arg);
|
|
|
|
|
|
|
|
error:
|
2016-03-25 17:46:53 +03:00
|
|
|
dev->phy_ops->send_ack(dev, GFP_KERNEL);
|
2013-06-13 17:43:28 +04:00
|
|
|
queue_work(dev->wq, &dev->cmd_work);
|
|
|
|
}
|
|
|
|
|
2011-07-02 02:31:37 +04:00
|
|
|
static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
|
|
|
|
u8 cfgdata_len)
|
|
|
|
{
|
2012-11-26 17:18:38 +04:00
|
|
|
struct sk_buff *skb;
|
|
|
|
struct sk_buff *resp;
|
|
|
|
int skb_len;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-11-26 17:18:38 +04:00
|
|
|
skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, skb_len);
|
2012-11-26 17:18:38 +04:00
|
|
|
if (!skb)
|
|
|
|
return -ENOMEM;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, cfgitem);
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
|
|
|
skb_put_data(skb, cfgdata, cfgdata_len);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-11-26 17:18:38 +04:00
|
|
|
resp = pn533_send_cmd_sync(dev, PN533_CMD_RF_CONFIGURATION, skb);
|
|
|
|
if (IS_ERR(resp))
|
|
|
|
return PTR_ERR(resp);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2012-11-26 17:18:38 +04:00
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pn533_get_firmware_version(struct pn533 *dev,
|
|
|
|
struct pn533_fw_version *fv)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
struct sk_buff *resp;
|
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, 0);
|
2012-11-26 17:18:38 +04:00
|
|
|
if (!skb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
resp = pn533_send_cmd_sync(dev, PN533_CMD_GET_FIRMWARE_VERSION, skb);
|
|
|
|
if (IS_ERR(resp))
|
|
|
|
return PTR_ERR(resp);
|
|
|
|
|
|
|
|
fv->ic = resp->data[0];
|
|
|
|
fv->ver = resp->data[1];
|
|
|
|
fv->rev = resp->data[2];
|
|
|
|
fv->support = resp->data[3];
|
|
|
|
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return 0;
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
|
|
|
|
2013-04-03 10:02:02 +04:00
|
|
|
static int pn533_pasori_fw_reset(struct pn533 *dev)
|
2012-07-02 22:04:01 +04:00
|
|
|
{
|
2012-11-26 17:18:38 +04:00
|
|
|
struct sk_buff *skb;
|
|
|
|
struct sk_buff *resp;
|
2012-07-02 22:04:01 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
dev_dbg(dev->dev, "%s\n", __func__);
|
2012-07-02 22:04:01 +04:00
|
|
|
|
2012-12-10 17:43:01 +04:00
|
|
|
skb = pn533_alloc_skb(dev, sizeof(u8));
|
2012-11-26 17:18:38 +04:00
|
|
|
if (!skb)
|
|
|
|
return -ENOMEM;
|
2012-07-02 22:04:01 +04:00
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, 0x1);
|
2012-07-02 22:04:01 +04:00
|
|
|
|
2012-11-26 17:18:38 +04:00
|
|
|
resp = pn533_send_cmd_sync(dev, 0x18, skb);
|
|
|
|
if (IS_ERR(resp))
|
|
|
|
return PTR_ERR(resp);
|
2012-07-02 22:04:01 +04:00
|
|
|
|
2012-11-26 17:18:38 +04:00
|
|
|
dev_kfree_skb(resp);
|
2012-07-02 22:04:01 +04:00
|
|
|
|
2012-11-26 17:18:36 +04:00
|
|
|
return 0;
|
2012-07-02 22:04:01 +04:00
|
|
|
}
|
|
|
|
|
2013-04-11 13:45:41 +04:00
|
|
|
static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
|
u8 rf_field = !!rf;
|
|
|
|
int rc;
|
|
|
|
|
2013-07-01 19:26:58 +04:00
|
|
|
rf_field |= PN533_CFGITEM_RF_FIELD_AUTO_RFCA;
|
|
|
|
|
2013-04-11 13:45:41 +04:00
|
|
|
rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD,
|
|
|
|
(u8 *)&rf_field, 1);
|
|
|
|
if (rc) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "Error on setting RF field\n");
|
2013-04-11 13:45:41 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:54 +03:00
|
|
|
static int pn532_sam_configuration(struct nfc_dev *nfc_dev)
|
|
|
|
{
|
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
|
struct sk_buff *skb;
|
|
|
|
struct sk_buff *resp;
|
|
|
|
|
|
|
|
skb = pn533_alloc_skb(dev, 1);
|
|
|
|
if (!skb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
|
|
|
skb_put_u8(skb, 0x01);
|
2016-03-25 17:46:54 +03:00
|
|
|
|
|
|
|
resp = pn533_send_cmd_sync(dev, PN533_CMD_SAM_CONFIGURATION, skb);
|
|
|
|
if (IS_ERR(resp))
|
|
|
|
return PTR_ERR(resp);
|
|
|
|
|
|
|
|
dev_kfree_skb(resp);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-09-20 13:00:41 +04:00
|
|
|
static int pn533_dev_up(struct nfc_dev *nfc_dev)
|
2013-04-11 13:45:41 +04:00
|
|
|
{
|
2016-03-25 17:46:54 +03:00
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
2019-11-13 16:50:22 +03:00
|
|
|
int rc;
|
2016-03-25 17:46:54 +03:00
|
|
|
|
2019-11-13 16:50:22 +03:00
|
|
|
if (dev->phy_ops->dev_up) {
|
|
|
|
rc = dev->phy_ops->dev_up(dev);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
}
|
2019-10-29 17:46:29 +03:00
|
|
|
|
2019-10-29 17:47:43 +03:00
|
|
|
if ((dev->device_type == PN533_DEVICE_PN532) ||
|
|
|
|
(dev->device_type == PN533_DEVICE_PN532_AUTOPOLL)) {
|
2019-11-13 16:50:22 +03:00
|
|
|
rc = pn532_sam_configuration(nfc_dev);
|
2016-03-25 17:46:54 +03:00
|
|
|
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2013-04-11 13:45:41 +04:00
|
|
|
return pn533_rf_field(nfc_dev, 1);
|
|
|
|
}
|
|
|
|
|
2013-09-20 13:00:41 +04:00
|
|
|
static int pn533_dev_down(struct nfc_dev *nfc_dev)
|
2013-04-11 13:45:41 +04:00
|
|
|
{
|
2019-10-29 17:46:29 +03:00
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = pn533_rf_field(nfc_dev, 0);
|
|
|
|
if (dev->phy_ops->dev_down && !ret)
|
2019-11-13 16:50:22 +03:00
|
|
|
ret = dev->phy_ops->dev_down(dev);
|
2019-10-29 17:46:29 +03:00
|
|
|
|
|
|
|
return ret;
|
2013-04-11 13:45:41 +04:00
|
|
|
}
|
|
|
|
|
2012-07-02 22:04:01 +04:00
|
|
|
static struct nfc_ops pn533_nfc_ops = {
|
2013-04-11 13:45:41 +04:00
|
|
|
.dev_up = pn533_dev_up,
|
|
|
|
.dev_down = pn533_dev_down,
|
2011-12-14 19:43:11 +04:00
|
|
|
.dep_link_up = pn533_dep_link_up,
|
|
|
|
.dep_link_down = pn533_dep_link_down,
|
2011-07-02 02:31:37 +04:00
|
|
|
.start_poll = pn533_start_poll,
|
|
|
|
.stop_poll = pn533_stop_poll,
|
|
|
|
.activate_target = pn533_activate_target,
|
|
|
|
.deactivate_target = pn533_deactivate_target,
|
2012-05-16 17:55:48 +04:00
|
|
|
.im_transceive = pn533_transceive,
|
2012-05-31 02:09:11 +04:00
|
|
|
.tm_send = pn533_tm_send,
|
2011-07-02 02:31:37 +04:00
|
|
|
};
|
|
|
|
|
2012-07-02 22:04:01 +04:00
|
|
|
static int pn533_setup(struct pn533 *dev)
|
|
|
|
{
|
|
|
|
struct pn533_config_max_retries max_retries;
|
|
|
|
struct pn533_config_timing timing;
|
|
|
|
u8 pasori_cfg[3] = {0x08, 0x01, 0x08};
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
switch (dev->device_type) {
|
|
|
|
case PN533_DEVICE_STD:
|
|
|
|
case PN533_DEVICE_PASORI:
|
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
|
|
|
case PN533_DEVICE_ACR122U:
|
2016-03-25 17:46:54 +03:00
|
|
|
case PN533_DEVICE_PN532:
|
2019-10-29 17:47:43 +03:00
|
|
|
case PN533_DEVICE_PN532_AUTOPOLL:
|
2012-07-02 22:04:01 +04:00
|
|
|
max_retries.mx_rty_atr = 0x2;
|
|
|
|
max_retries.mx_rty_psl = 0x1;
|
|
|
|
max_retries.mx_rty_passive_act =
|
|
|
|
PN533_CONFIG_MAX_RETRIES_NO_RETRY;
|
|
|
|
|
|
|
|
timing.rfu = PN533_CONFIG_TIMING_102;
|
|
|
|
timing.atr_res_timeout = PN533_CONFIG_TIMING_102;
|
|
|
|
timing.dep_timeout = PN533_CONFIG_TIMING_204;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "Unknown device type %d\n",
|
2013-04-05 23:27:38 +04:00
|
|
|
dev->device_type);
|
2012-07-02 22:04:01 +04:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
|
|
|
|
(u8 *)&max_retries, sizeof(max_retries));
|
|
|
|
if (rc) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Error on setting MAX_RETRIES config\n");
|
2012-07-02 22:04:01 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
|
|
|
|
(u8 *)&timing, sizeof(timing));
|
|
|
|
if (rc) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev, "Error on setting RF timings\n");
|
2012-07-02 22:04:01 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (dev->device_type) {
|
|
|
|
case PN533_DEVICE_STD:
|
2016-03-25 17:46:54 +03:00
|
|
|
case PN533_DEVICE_PN532:
|
2019-10-29 17:47:43 +03:00
|
|
|
case PN533_DEVICE_PN532_AUTOPOLL:
|
2012-07-02 22:04:01 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PN533_DEVICE_PASORI:
|
2013-04-03 10:02:02 +04:00
|
|
|
pn533_pasori_fw_reset(dev);
|
2012-07-02 22:04:01 +04:00
|
|
|
|
|
|
|
rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI,
|
|
|
|
pasori_cfg, 3);
|
|
|
|
if (rc) {
|
2016-03-25 17:46:53 +03:00
|
|
|
nfc_err(dev->dev,
|
2013-04-05 23:27:38 +04:00
|
|
|
"Error while settings PASORI config\n");
|
2012-07-02 22:04:01 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2013-04-03 10:02:02 +04:00
|
|
|
pn533_pasori_fw_reset(dev);
|
2012-07-02 22:04:01 +04:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-12-28 20:10:59 +03:00
|
|
|
int pn533_finalize_setup(struct pn533 *dev)
|
|
|
|
{
|
|
|
|
|
|
|
|
struct pn533_fw_version fw_ver;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
memset(&fw_ver, 0, sizeof(fw_ver));
|
|
|
|
|
|
|
|
rc = pn533_get_firmware_version(dev, &fw_ver);
|
|
|
|
if (rc) {
|
|
|
|
nfc_err(dev->dev, "Unable to get FW version\n");
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
nfc_info(dev->dev, "NXP PN5%02X firmware ver %d.%d now attached\n",
|
|
|
|
fw_ver.ic, fw_ver.ver, fw_ver.rev);
|
|
|
|
|
|
|
|
rc = pn533_setup(dev);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pn533_finalize_setup);
|
|
|
|
|
2019-10-29 17:46:46 +03:00
|
|
|
struct pn533 *pn53x_common_init(u32 device_type,
|
2016-03-25 17:46:53 +03:00
|
|
|
enum pn533_protocol_type protocol_type,
|
|
|
|
void *phy,
|
|
|
|
struct pn533_phy_ops *phy_ops,
|
|
|
|
struct pn533_frame_ops *fops,
|
2019-10-29 17:46:46 +03:00
|
|
|
struct device *dev)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
2016-03-25 17:46:53 +03:00
|
|
|
struct pn533 *priv;
|
2011-07-02 02:31:37 +04:00
|
|
|
int rc = -ENOMEM;
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
|
|
|
if (!priv)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
priv->phy = phy;
|
|
|
|
priv->phy_ops = phy_ops;
|
|
|
|
priv->dev = dev;
|
|
|
|
if (fops != NULL)
|
|
|
|
priv->ops = fops;
|
|
|
|
else
|
|
|
|
priv->ops = &pn533_std_frame_ops;
|
|
|
|
|
|
|
|
priv->protocol_type = protocol_type;
|
|
|
|
priv->device_type = device_type;
|
|
|
|
|
|
|
|
mutex_init(&priv->cmd_lock);
|
|
|
|
|
|
|
|
INIT_WORK(&priv->cmd_work, pn533_wq_cmd);
|
|
|
|
INIT_WORK(&priv->cmd_complete_work, pn533_wq_cmd_complete);
|
|
|
|
INIT_WORK(&priv->mi_rx_work, pn533_wq_mi_recv);
|
|
|
|
INIT_WORK(&priv->mi_tx_work, pn533_wq_mi_send);
|
|
|
|
INIT_WORK(&priv->tg_work, pn533_wq_tg_get_data);
|
|
|
|
INIT_WORK(&priv->mi_tm_rx_work, pn533_wq_tm_mi_recv);
|
|
|
|
INIT_WORK(&priv->mi_tm_tx_work, pn533_wq_tm_mi_send);
|
|
|
|
INIT_DELAYED_WORK(&priv->poll_work, pn533_wq_poll);
|
|
|
|
INIT_WORK(&priv->rf_work, pn533_wq_rf);
|
|
|
|
priv->wq = alloc_ordered_workqueue("pn533", 0);
|
|
|
|
if (priv->wq == NULL)
|
2012-04-10 21:43:17 +04:00
|
|
|
goto error;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
treewide: setup_timer() -> timer_setup()
This converts all remaining cases of the old setup_timer() API into using
timer_setup(), where the callback argument is the structure already
holding the struct timer_list. These should have no behavioral changes,
since they just change which pointer is passed into the callback with
the same available pointers after conversion. It handles the following
examples, in addition to some other variations.
Casting from unsigned long:
void my_callback(unsigned long data)
{
struct something *ptr = (struct something *)data;
...
}
...
setup_timer(&ptr->my_timer, my_callback, ptr);
and forced object casts:
void my_callback(struct something *ptr)
{
...
}
...
setup_timer(&ptr->my_timer, my_callback, (unsigned long)ptr);
become:
void my_callback(struct timer_list *t)
{
struct something *ptr = from_timer(ptr, t, my_timer);
...
}
...
timer_setup(&ptr->my_timer, my_callback, 0);
Direct function assignments:
void my_callback(unsigned long data)
{
struct something *ptr = (struct something *)data;
...
}
...
ptr->my_timer.function = my_callback;
have a temporary cast added, along with converting the args:
void my_callback(struct timer_list *t)
{
struct something *ptr = from_timer(ptr, t, my_timer);
...
}
...
ptr->my_timer.function = (TIMER_FUNC_TYPE)my_callback;
And finally, callbacks without a data assignment:
void my_callback(unsigned long data)
{
...
}
...
setup_timer(&ptr->my_timer, my_callback, 0);
have their argument renamed to verify they're unused during conversion:
void my_callback(struct timer_list *unused)
{
...
}
...
timer_setup(&ptr->my_timer, my_callback, 0);
The conversion is done with the following Coccinelle script:
spatch --very-quiet --all-includes --include-headers \
-I ./arch/x86/include -I ./arch/x86/include/generated \
-I ./include -I ./arch/x86/include/uapi \
-I ./arch/x86/include/generated/uapi -I ./include/uapi \
-I ./include/generated/uapi --include ./include/linux/kconfig.h \
--dir . \
--cocci-file ~/src/data/timer_setup.cocci
@fix_address_of@
expression e;
@@
setup_timer(
-&(e)
+&e
, ...)
// Update any raw setup_timer() usages that have a NULL callback, but
// would otherwise match change_timer_function_usage, since the latter
// will update all function assignments done in the face of a NULL
// function initialization in setup_timer().
@change_timer_function_usage_NULL@
expression _E;
identifier _timer;
type _cast_data;
@@
(
-setup_timer(&_E->_timer, NULL, _E);
+timer_setup(&_E->_timer, NULL, 0);
|
-setup_timer(&_E->_timer, NULL, (_cast_data)_E);
+timer_setup(&_E->_timer, NULL, 0);
|
-setup_timer(&_E._timer, NULL, &_E);
+timer_setup(&_E._timer, NULL, 0);
|
-setup_timer(&_E._timer, NULL, (_cast_data)&_E);
+timer_setup(&_E._timer, NULL, 0);
)
@change_timer_function_usage@
expression _E;
identifier _timer;
struct timer_list _stl;
identifier _callback;
type _cast_func, _cast_data;
@@
(
-setup_timer(&_E->_timer, _callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, &_callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, _callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, &_callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)_callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)&_callback, _E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)_callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, (_cast_func)&_callback, (_cast_data)_E);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, &_callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, &_callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)_E);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)&_E);
+timer_setup(&_E._timer, _callback, 0);
|
_E->_timer@_stl.function = _callback;
|
_E->_timer@_stl.function = &_callback;
|
_E->_timer@_stl.function = (_cast_func)_callback;
|
_E->_timer@_stl.function = (_cast_func)&_callback;
|
_E._timer@_stl.function = _callback;
|
_E._timer@_stl.function = &_callback;
|
_E._timer@_stl.function = (_cast_func)_callback;
|
_E._timer@_stl.function = (_cast_func)&_callback;
)
// callback(unsigned long arg)
@change_callback_handle_cast
depends on change_timer_function_usage@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _origtype;
identifier _origarg;
type _handletype;
identifier _handle;
@@
void _callback(
-_origtype _origarg
+struct timer_list *t
)
{
(
... when != _origarg
_handletype *_handle =
-(_handletype *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
|
... when != _origarg
_handletype *_handle =
-(void *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
|
... when != _origarg
_handletype *_handle;
... when != _handle
_handle =
-(_handletype *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
|
... when != _origarg
_handletype *_handle;
... when != _handle
_handle =
-(void *)_origarg;
+from_timer(_handle, t, _timer);
... when != _origarg
)
}
// callback(unsigned long arg) without existing variable
@change_callback_handle_cast_no_arg
depends on change_timer_function_usage &&
!change_callback_handle_cast@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _origtype;
identifier _origarg;
type _handletype;
@@
void _callback(
-_origtype _origarg
+struct timer_list *t
)
{
+ _handletype *_origarg = from_timer(_origarg, t, _timer);
+
... when != _origarg
- (_handletype *)_origarg
+ _origarg
... when != _origarg
}
// Avoid already converted callbacks.
@match_callback_converted
depends on change_timer_function_usage &&
!change_callback_handle_cast &&
!change_callback_handle_cast_no_arg@
identifier change_timer_function_usage._callback;
identifier t;
@@
void _callback(struct timer_list *t)
{ ... }
// callback(struct something *handle)
@change_callback_handle_arg
depends on change_timer_function_usage &&
!match_callback_converted &&
!change_callback_handle_cast &&
!change_callback_handle_cast_no_arg@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _handletype;
identifier _handle;
@@
void _callback(
-_handletype *_handle
+struct timer_list *t
)
{
+ _handletype *_handle = from_timer(_handle, t, _timer);
...
}
// If change_callback_handle_arg ran on an empty function, remove
// the added handler.
@unchange_callback_handle_arg
depends on change_timer_function_usage &&
change_callback_handle_arg@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _handletype;
identifier _handle;
identifier t;
@@
void _callback(struct timer_list *t)
{
- _handletype *_handle = from_timer(_handle, t, _timer);
}
// We only want to refactor the setup_timer() data argument if we've found
// the matching callback. This undoes changes in change_timer_function_usage.
@unchange_timer_function_usage
depends on change_timer_function_usage &&
!change_callback_handle_cast &&
!change_callback_handle_cast_no_arg &&
!change_callback_handle_arg@
expression change_timer_function_usage._E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type change_timer_function_usage._cast_data;
@@
(
-timer_setup(&_E->_timer, _callback, 0);
+setup_timer(&_E->_timer, _callback, (_cast_data)_E);
|
-timer_setup(&_E._timer, _callback, 0);
+setup_timer(&_E._timer, _callback, (_cast_data)&_E);
)
// If we fixed a callback from a .function assignment, fix the
// assignment cast now.
@change_timer_function_assignment
depends on change_timer_function_usage &&
(change_callback_handle_cast ||
change_callback_handle_cast_no_arg ||
change_callback_handle_arg)@
expression change_timer_function_usage._E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type _cast_func;
typedef TIMER_FUNC_TYPE;
@@
(
_E->_timer.function =
-_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E->_timer.function =
-&_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E->_timer.function =
-(_cast_func)_callback;
+(TIMER_FUNC_TYPE)_callback
;
|
_E->_timer.function =
-(_cast_func)&_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-&_callback;
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-(_cast_func)_callback
+(TIMER_FUNC_TYPE)_callback
;
|
_E._timer.function =
-(_cast_func)&_callback
+(TIMER_FUNC_TYPE)_callback
;
)
// Sometimes timer functions are called directly. Replace matched args.
@change_timer_function_calls
depends on change_timer_function_usage &&
(change_callback_handle_cast ||
change_callback_handle_cast_no_arg ||
change_callback_handle_arg)@
expression _E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type _cast_data;
@@
_callback(
(
-(_cast_data)_E
+&_E->_timer
|
-(_cast_data)&_E
+&_E._timer
|
-_E
+&_E->_timer
)
)
// If a timer has been configured without a data argument, it can be
// converted without regard to the callback argument, since it is unused.
@match_timer_function_unused_data@
expression _E;
identifier _timer;
identifier _callback;
@@
(
-setup_timer(&_E->_timer, _callback, 0);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, _callback, 0L);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E->_timer, _callback, 0UL);
+timer_setup(&_E->_timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, 0);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, 0L);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_E._timer, _callback, 0UL);
+timer_setup(&_E._timer, _callback, 0);
|
-setup_timer(&_timer, _callback, 0);
+timer_setup(&_timer, _callback, 0);
|
-setup_timer(&_timer, _callback, 0L);
+timer_setup(&_timer, _callback, 0);
|
-setup_timer(&_timer, _callback, 0UL);
+timer_setup(&_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0);
+timer_setup(_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0L);
+timer_setup(_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0UL);
+timer_setup(_timer, _callback, 0);
)
@change_callback_unused_data
depends on match_timer_function_unused_data@
identifier match_timer_function_unused_data._callback;
type _origtype;
identifier _origarg;
@@
void _callback(
-_origtype _origarg
+struct timer_list *unused
)
{
... when != _origarg
}
Signed-off-by: Kees Cook <keescook@chromium.org>
2017-10-17 00:43:17 +03:00
|
|
|
timer_setup(&priv->listen_timer, pn533_listen_mode_timer, 0);
|
2012-07-02 22:04:01 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
skb_queue_head_init(&priv->resp_q);
|
|
|
|
skb_queue_head_init(&priv->fragment_skb);
|
NFC: pn533: Add support for ACS ACR122U reader
ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.
Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.
In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.
The frame roughly looks like:
CCID header | APDU header | PN532 header
(pc_to_rdr_escape) | (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)
Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2013-04-03 10:02:13 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
INIT_LIST_HEAD(&priv->cmd_queue);
|
|
|
|
return priv;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
|
|
|
error:
|
2016-03-25 17:46:53 +03:00
|
|
|
kfree(priv);
|
|
|
|
return ERR_PTR(rc);
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
2019-10-29 17:46:46 +03:00
|
|
|
EXPORT_SYMBOL_GPL(pn53x_common_init);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2019-10-29 17:46:46 +03:00
|
|
|
void pn53x_common_clean(struct pn533 *priv)
|
2011-07-02 02:31:37 +04:00
|
|
|
{
|
2012-08-18 01:47:54 +04:00
|
|
|
struct pn533_cmd *cmd, *n;
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
flush_delayed_work(&priv->poll_work);
|
|
|
|
destroy_workqueue(priv->wq);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
skb_queue_purge(&priv->resp_q);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
del_timer(&priv->listen_timer);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
list_for_each_entry_safe(cmd, n, &priv->cmd_queue, queue) {
|
2012-08-18 01:47:54 +04:00
|
|
|
list_del(&cmd->queue);
|
|
|
|
kfree(cmd);
|
|
|
|
}
|
|
|
|
|
2016-03-25 17:46:53 +03:00
|
|
|
kfree(priv);
|
2011-07-02 02:31:37 +04:00
|
|
|
}
|
2019-10-29 17:46:46 +03:00
|
|
|
EXPORT_SYMBOL_GPL(pn53x_common_clean);
|
|
|
|
|
|
|
|
int pn532_i2c_nfc_alloc(struct pn533 *priv, u32 protocols,
|
|
|
|
struct device *parent)
|
|
|
|
{
|
|
|
|
priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
|
|
|
|
priv->ops->tx_header_len +
|
|
|
|
PN533_CMD_DATAEXCH_HEAD_LEN,
|
|
|
|
priv->ops->tx_tail_len);
|
|
|
|
if (!priv->nfc_dev)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
nfc_set_parent_dev(priv->nfc_dev, parent);
|
|
|
|
nfc_set_drvdata(priv->nfc_dev, priv);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pn532_i2c_nfc_alloc);
|
|
|
|
|
|
|
|
int pn53x_register_nfc(struct pn533 *priv, u32 protocols,
|
|
|
|
struct device *parent)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = pn532_i2c_nfc_alloc(priv, protocols, parent);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
rc = nfc_register_device(priv->nfc_dev);
|
|
|
|
if (rc)
|
|
|
|
nfc_free_device(priv->nfc_dev);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pn53x_register_nfc);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2019-10-29 17:46:46 +03:00
|
|
|
void pn53x_unregister_nfc(struct pn533 *priv)
|
|
|
|
{
|
|
|
|
nfc_unregister_device(priv->nfc_dev);
|
|
|
|
nfc_free_device(priv->nfc_dev);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pn53x_unregister_nfc);
|
2011-07-02 02:31:37 +04:00
|
|
|
|
2013-04-03 10:02:01 +04:00
|
|
|
MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
|
|
|
|
MODULE_AUTHOR("Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
|
|
|
|
MODULE_AUTHOR("Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>");
|
2016-03-25 17:46:53 +03:00
|
|
|
MODULE_DESCRIPTION("PN533 driver ver " VERSION);
|
2011-07-02 02:31:37 +04:00
|
|
|
MODULE_VERSION(VERSION);
|
|
|
|
MODULE_LICENSE("GPL");
|