Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74ea1f45 authored by John W. Linville's avatar John W. Linville
Browse files


Samuel Ortiz <sameo@linux.intel.com> says:

"This is the first NFC pull request for the 3.12 release.

With this one we have:

- A few pn533 improvements and minor fixes. Testing our pn533 driver
  against Google's NCI stack triggered a few issues that we fixed now.
  We also added Tx fragmentation support to this driver.

- More NFC secure element handling. We added a GET_SE netlink command
  for getting all the discovered secure elements, and we defined 2
  additional secure element netlink event (transaction and connectivity).
  We also fixed a couple of typos and copy-paste bugs from the secure
  element handling code.

- Firmware download support for the pn544 driver. This chipset can enter a
  special mode where it's waiting for firmware blobs to replace the
  already flashed one. We now support that mode."

Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parents 946951e1 39525ee1
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -5791,7 +5791,7 @@ M: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
M:	Samuel Ortiz <sameo@linux.intel.com>
M:	Samuel Ortiz <sameo@linux.intel.com>
L:	linux-wireless@vger.kernel.org
L:	linux-wireless@vger.kernel.org
L:	linux-nfc@lists.01.org (moderated for non-subscribers)
L:	linux-nfc@lists.01.org (moderated for non-subscribers)
S:	Maintained
S:	Supported
F:	net/nfc/
F:	net/nfc/
F:	include/net/nfc/
F:	include/net/nfc/
F:	include/uapi/linux/nfc.h
F:	include/uapi/linux/nfc.h
+3 −3
Original line number Original line Diff line number Diff line
@@ -60,7 +60,7 @@ struct nfcsim {
static struct nfcsim *dev0;
static struct nfcsim *dev0;
static struct nfcsim *dev1;
static struct nfcsim *dev1;


struct workqueue_struct *wq;
static struct workqueue_struct *wq;


static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown)
static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown)
{
{
@@ -481,7 +481,7 @@ static void nfcsim_free_device(struct nfcsim *dev)
	kfree(dev);
	kfree(dev);
}
}


int __init nfcsim_init(void)
static int __init nfcsim_init(void)
{
{
	int rc;
	int rc;


@@ -522,7 +522,7 @@ exit:
	return rc;
	return rc;
}
}


void __exit nfcsim_exit(void)
static void __exit nfcsim_exit(void)
{
{
	nfcsim_cleanup_dev(dev0, 1);
	nfcsim_cleanup_dev(dev0, 1);
	nfcsim_cleanup_dev(dev1, 1);
	nfcsim_cleanup_dev(dev1, 1);
+301 −88
Original line number Original line Diff line number Diff line
@@ -83,12 +83,20 @@ MODULE_DEVICE_TABLE(usb, pn533_table);


/* How much time we spend listening for initiators */
/* How much time we spend listening for initiators */
#define PN533_LISTEN_TIME 2
#define PN533_LISTEN_TIME 2
/* Delay between each poll frame (ms) */
#define PN533_POLL_INTERVAL 10


/* Standard pn533 frame definitions */
/* Standard pn533 frame definitions (standard and extended)*/
#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \
#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \
					+ 2) /* data[0] TFI, data[1] CC */
					+ 2) /* data[0] TFI, data[1] CC */
#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/
#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/


#define PN533_EXT_FRAME_HEADER_LEN (sizeof(struct pn533_ext_frame) \
					+ 2) /* data[0] TFI, data[1] CC */

#define PN533_CMD_DATAEXCH_DATA_MAXLEN	262
#define PN533_CMD_DATAFRAME_MAXLEN	240	/* max data length (send) */

/*
/*
 * Max extended frame payload len, excluding TFI and CC
 * Max extended frame payload len, excluding TFI and CC
 * which are already in PN533_FRAME_HEADER_LEN.
 * which are already in PN533_FRAME_HEADER_LEN.
@@ -99,6 +107,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
				  Postamble (1) */
				  Postamble (1) */
#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen])
#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen])
#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
/* Half start code (3), LEN (4) should be 0xffff for extended frame */
#define PN533_STD_IS_EXTENDED(hdr) ((hdr)->datalen == 0xFF \
					&& (hdr)->datalen_checksum == 0xFF)
#define PN533_EXT_FRAME_CHECKSUM(f) (f->data[be16_to_cpu(f->datalen)])


/* start of frame */
/* start of frame */
#define PN533_STD_FRAME_SOF 0x00FF
#define PN533_STD_FRAME_SOF 0x00FF
@@ -124,7 +136,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83
#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83


/* PN533 Commands */
/* PN533 Commands */
#define PN533_STD_FRAME_CMD(f) (f->data[1])
#define PN533_FRAME_CMD(f) (f->data[1])


#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
#define PN533_CMD_RF_CONFIGURATION 0x32
#define PN533_CMD_RF_CONFIGURATION 0x32
@@ -168,6 +180,7 @@ struct pn533_fw_version {
#define PN533_CFGITEM_MAX_RETRIES 0x05
#define PN533_CFGITEM_MAX_RETRIES 0x05
#define PN533_CFGITEM_PASORI      0x82
#define PN533_CFGITEM_PASORI      0x82


#define PN533_CFGITEM_RF_FIELD_AUTO_RFCA 0x2
#define PN533_CFGITEM_RF_FIELD_ON        0x1
#define PN533_CFGITEM_RF_FIELD_ON        0x1
#define PN533_CFGITEM_RF_FIELD_OFF       0x0
#define PN533_CFGITEM_RF_FIELD_OFF       0x0


@@ -257,7 +270,7 @@ static const struct pn533_poll_modulations poll_mod[] = {
			.initiator_data.felica = {
			.initiator_data.felica = {
				.opcode = PN533_FELICA_OPC_SENSF_REQ,
				.opcode = PN533_FELICA_OPC_SENSF_REQ,
				.sc = PN533_FELICA_SENSF_SC_ALL,
				.sc = PN533_FELICA_SENSF_SC_ALL,
				.rc = PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE,
				.rc = PN533_FELICA_SENSF_RC_SYSTEM_CODE,
				.tsn = 0x03,
				.tsn = 0x03,
			},
			},
		},
		},
@@ -270,7 +283,7 @@ static const struct pn533_poll_modulations poll_mod[] = {
			.initiator_data.felica = {
			.initiator_data.felica = {
				.opcode = PN533_FELICA_OPC_SENSF_REQ,
				.opcode = PN533_FELICA_OPC_SENSF_REQ,
				.sc = PN533_FELICA_SENSF_SC_ALL,
				.sc = PN533_FELICA_SENSF_SC_ALL,
				.rc = PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE,
				.rc = PN533_FELICA_SENSF_RC_SYSTEM_CODE,
				.tsn = 0x03,
				.tsn = 0x03,
			},
			},
		 },
		 },
@@ -352,13 +365,16 @@ struct pn533 {
	struct urb *in_urb;
	struct urb *in_urb;


	struct sk_buff_head resp_q;
	struct sk_buff_head resp_q;
	struct sk_buff_head fragment_skb;


	struct workqueue_struct	*wq;
	struct workqueue_struct	*wq;
	struct work_struct cmd_work;
	struct work_struct cmd_work;
	struct work_struct cmd_complete_work;
	struct work_struct cmd_complete_work;
	struct work_struct poll_work;
	struct delayed_work poll_work;
	struct work_struct mi_work;
	struct work_struct mi_rx_work;
	struct work_struct mi_tx_work;
	struct work_struct tg_work;
	struct work_struct tg_work;
	struct work_struct rf_work;


	struct list_head cmd_queue;
	struct list_head cmd_queue;
	struct pn533_cmd *cmd;
	struct pn533_cmd *cmd;
@@ -366,6 +382,7 @@ struct pn533 {
	struct mutex cmd_lock;  /* protects cmd queue */
	struct mutex cmd_lock;  /* protects cmd queue */


	void *cmd_complete_mi_arg;
	void *cmd_complete_mi_arg;
	void *cmd_complete_dep_arg;


	struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
	struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
	u8 poll_mod_count;
	u8 poll_mod_count;
@@ -404,6 +421,15 @@ struct pn533_std_frame {
	u8 data[];
	u8 data[];
} __packed;
} __packed;


struct pn533_ext_frame {	/* Extended Information frame */
	u8 preamble;
	__be16 start_frame;
	__be16 eif_flag;	/* fixed to 0xFFFF */
	__be16 datalen;
	u8 datalen_checksum;
	u8 data[];
} __packed;

struct pn533_frame_ops {
struct pn533_frame_ops {
	void (*tx_frame_init)(void *frame, u8 cmd_code);
	void (*tx_frame_init)(void *frame, u8 cmd_code);
	void (*tx_frame_finish)(void *frame);
	void (*tx_frame_finish)(void *frame);
@@ -411,7 +437,7 @@ struct pn533_frame_ops {
	int tx_header_len;
	int tx_header_len;
	int tx_tail_len;
	int tx_tail_len;


	bool (*rx_is_frame_valid)(void *frame);
	bool (*rx_is_frame_valid)(void *frame, struct pn533 *dev);
	int (*rx_frame_size)(void *frame);
	int (*rx_frame_size)(void *frame);
	int rx_header_len;
	int rx_header_len;
	int rx_tail_len;
	int rx_tail_len;
@@ -486,7 +512,7 @@ static void pn533_acr122_tx_update_payload_len(void *_frame, int len)
	frame->datalen += len;
	frame->datalen += len;
}
}


static bool pn533_acr122_is_rx_frame_valid(void *_frame)
static bool pn533_acr122_is_rx_frame_valid(void *_frame, struct pn533 *dev)
{
{
	struct pn533_acr122_rx_frame *frame = _frame;
	struct pn533_acr122_rx_frame *frame = _frame;


@@ -511,7 +537,7 @@ static u8 pn533_acr122_get_cmd_code(void *frame)
{
{
	struct pn533_acr122_rx_frame *f = frame;
	struct pn533_acr122_rx_frame *f = frame;


	return PN533_STD_FRAME_CMD(f);
	return PN533_FRAME_CMD(f);
}
}


static struct pn533_frame_ops pn533_acr122_frame_ops = {
static struct pn533_frame_ops pn533_acr122_frame_ops = {
@@ -530,6 +556,12 @@ static struct pn533_frame_ops pn533_acr122_frame_ops = {
	.get_cmd_code = pn533_acr122_get_cmd_code,
	.get_cmd_code = pn533_acr122_get_cmd_code,
};
};


/* The rule: value(high byte) + value(low byte) + checksum = 0 */
static inline u8 pn533_ext_checksum(u16 value)
{
	return ~(u8)(((value & 0xFF00) >> 8) + (u8)(value & 0xFF)) + 1;
}

/* The rule: value + checksum = 0 */
/* The rule: value + checksum = 0 */
static inline u8 pn533_std_checksum(u8 value)
static inline u8 pn533_std_checksum(u8 value)
{
{
@@ -555,7 +587,7 @@ static void pn533_std_tx_frame_init(void *_frame, u8 cmd_code)
	frame->preamble = 0;
	frame->preamble = 0;
	frame->start_frame = cpu_to_be16(PN533_STD_FRAME_SOF);
	frame->start_frame = cpu_to_be16(PN533_STD_FRAME_SOF);
	PN533_STD_FRAME_IDENTIFIER(frame) = PN533_STD_FRAME_DIR_OUT;
	PN533_STD_FRAME_IDENTIFIER(frame) = PN533_STD_FRAME_DIR_OUT;
	PN533_STD_FRAME_CMD(frame) = cmd_code;
	PN533_FRAME_CMD(frame) = cmd_code;
	frame->datalen = 2;
	frame->datalen = 2;
}
}


@@ -578,21 +610,41 @@ static void pn533_std_tx_update_payload_len(void *_frame, int len)
	frame->datalen += len;
	frame->datalen += len;
}
}


static bool pn533_std_rx_frame_is_valid(void *_frame)
static bool pn533_std_rx_frame_is_valid(void *_frame, struct pn533 *dev)
{
{
	u8 checksum;
	u8 checksum;
	struct pn533_std_frame *frame = _frame;
	struct pn533_std_frame *stdf = _frame;


	if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
	if (stdf->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
		return false;
		return false;


	checksum = pn533_std_checksum(frame->datalen);
	if (likely(!PN533_STD_IS_EXTENDED(stdf))) {
	if (checksum != frame->datalen_checksum)
		/* Standard frame code */
		dev->ops->rx_header_len = PN533_STD_FRAME_HEADER_LEN;

		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;

		dev->ops->rx_header_len = PN533_EXT_FRAME_HEADER_LEN;

		checksum = pn533_ext_checksum(be16_to_cpu(eif->datalen));
		if (checksum != eif->datalen_checksum)
			return false;
			return false;


	checksum = pn533_std_data_checksum(frame->data, frame->datalen);
		/* check data checksum */
	if (checksum != PN533_STD_FRAME_CHECKSUM(frame))
		checksum = pn533_std_data_checksum(eif->data,
						   be16_to_cpu(eif->datalen));
		if (checksum != PN533_EXT_FRAME_CHECKSUM(eif))
			return false;
			return false;
	}


	return true;
	return true;
}
}
@@ -612,6 +664,14 @@ static inline int pn533_std_rx_frame_size(void *frame)
{
{
	struct pn533_std_frame *f = frame;
	struct pn533_std_frame *f = frame;


	/* 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;
	}

	return sizeof(struct pn533_std_frame) + f->datalen +
	return sizeof(struct pn533_std_frame) + f->datalen +
	       PN533_STD_FRAME_TAIL_LEN;
	       PN533_STD_FRAME_TAIL_LEN;
}
}
@@ -619,8 +679,12 @@ static inline int pn533_std_rx_frame_size(void *frame)
static u8 pn533_std_get_cmd_code(void *frame)
static u8 pn533_std_get_cmd_code(void *frame)
{
{
	struct pn533_std_frame *f = frame;
	struct pn533_std_frame *f = frame;
	struct pn533_ext_frame *eif = frame;


	return PN533_STD_FRAME_CMD(f);
	if (PN533_STD_IS_EXTENDED(f))
		return PN533_FRAME_CMD(eif);
	else
		return PN533_FRAME_CMD(f);
}
}


static struct pn533_frame_ops pn533_std_frame_ops = {
static struct pn533_frame_ops pn533_std_frame_ops = {
@@ -675,7 +739,7 @@ static void pn533_recv_response(struct urb *urb)
	print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame,
	print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame,
			     dev->ops->rx_frame_size(in_frame), false);
			     dev->ops->rx_frame_size(in_frame), false);


	if (!dev->ops->rx_is_frame_valid(in_frame)) {
	if (!dev->ops->rx_is_frame_valid(in_frame, dev)) {
		nfc_dev_err(&dev->interface->dev, "Received an invalid frame");
		nfc_dev_err(&dev->interface->dev, "Received an invalid frame");
		cmd->status = -EIO;
		cmd->status = -EIO;
		goto sched_wq;
		goto sched_wq;
@@ -1657,7 +1721,56 @@ static void pn533_listen_mode_timer(unsigned long data)


	pn533_poll_next_mod(dev);
	pn533_poll_next_mod(dev);


	queue_work(dev->wq, &dev->poll_work);
	queue_delayed_work(dev->wq, &dev->poll_work,
			   msecs_to_jiffies(PN533_POLL_INTERVAL));
}

static int pn533_rf_complete(struct pn533 *dev, void *arg,
			     struct sk_buff *resp)
{
	int rc = 0;

	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);

	if (IS_ERR(resp)) {
		rc = PTR_ERR(resp);

		nfc_dev_err(&dev->interface->dev, "%s RF setting error %d",
			    __func__, rc);

		return rc;
	}

	queue_delayed_work(dev->wq, &dev->poll_work,
			   msecs_to_jiffies(PN533_POLL_INTERVAL));

	dev_kfree_skb(resp);
	return rc;
}

static void pn533_wq_rf(struct work_struct *work)
{
	struct pn533 *dev = container_of(work, struct pn533, rf_work);
	struct sk_buff *skb;
	int rc;

	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);

	skb = pn533_alloc_skb(dev, 2);
	if (!skb)
		return;

	*skb_put(skb, 1) = PN533_CFGITEM_RF_FIELD;
	*skb_put(skb, 1) = PN533_CFGITEM_RF_FIELD_AUTO_RFCA;

	rc = pn533_send_cmd_async(dev, PN533_CMD_RF_CONFIGURATION, skb,
				  pn533_rf_complete, NULL);
	if (rc < 0) {
		dev_kfree_skb(skb);
		nfc_dev_err(&dev->interface->dev, "RF setting error %d", rc);
	}

	return;
}
}


static int pn533_poll_complete(struct pn533 *dev, void *arg,
static int pn533_poll_complete(struct pn533 *dev, void *arg,
@@ -1705,7 +1818,8 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg,
	}
	}


	pn533_poll_next_mod(dev);
	pn533_poll_next_mod(dev);
	queue_work(dev->wq, &dev->poll_work);
	/* Not target found, turn radio off */
	queue_work(dev->wq, &dev->rf_work);


done:
done:
	dev_kfree_skb(resp);
	dev_kfree_skb(resp);
@@ -1770,7 +1884,7 @@ static int pn533_send_poll_frame(struct pn533 *dev)


static void pn533_wq_poll(struct work_struct *work)
static void pn533_wq_poll(struct work_struct *work)
{
{
	struct pn533 *dev = container_of(work, struct pn533, poll_work);
	struct pn533 *dev = container_of(work, struct pn533, poll_work.work);
	struct pn533_poll_modulations *cur_mod;
	struct pn533_poll_modulations *cur_mod;
	int rc;
	int rc;


@@ -1799,6 +1913,7 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
			    u32 im_protocols, u32 tm_protocols)
			    u32 im_protocols, u32 tm_protocols)
{
{
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
	u8 rand_mod;


	nfc_dev_dbg(&dev->interface->dev,
	nfc_dev_dbg(&dev->interface->dev,
		    "%s: im protocols 0x%x tm protocols 0x%x",
		    "%s: im protocols 0x%x tm protocols 0x%x",
@@ -1822,11 +1937,15 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
			tm_protocols = 0;
			tm_protocols = 0;
	}
	}


	dev->poll_mod_curr = 0;
	pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
	pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
	dev->poll_protocols = im_protocols;
	dev->poll_protocols = im_protocols;
	dev->listen_protocols = tm_protocols;
	dev->listen_protocols = tm_protocols;


	/* 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;

	return pn533_send_poll_frame(dev);
	return pn533_send_poll_frame(dev);
}
}


@@ -1845,6 +1964,7 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)
	}
	}


	pn533_abort_cmd(dev, GFP_KERNEL);
	pn533_abort_cmd(dev, GFP_KERNEL);
	flush_delayed_work(&dev->poll_work);
	pn533_poll_reset_mod_list(dev);
	pn533_poll_reset_mod_list(dev);
}
}


@@ -2037,28 +2157,15 @@ error:
	return rc;
	return rc;
}
}


static int pn533_mod_to_baud(struct pn533 *dev)
static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf);
{
	switch (dev->poll_mod_curr) {
	case PN533_POLL_MOD_106KBPS_A:
		return 0;
	case PN533_POLL_MOD_212KBPS_FELICA:
		return 1;
	case PN533_POLL_MOD_424KBPS_FELICA:
		return 2;
	default:
		return -EINVAL;
	}
}

#define PASSIVE_DATA_LEN 5
#define PASSIVE_DATA_LEN 5
static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
			     u8 comm_mode, u8 *gb, size_t gb_len)
			     u8 comm_mode, u8 *gb, size_t gb_len)
{
{
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
	struct sk_buff *skb;
	struct sk_buff *skb;
	int rc, baud, skb_len;
	int rc, skb_len;
	u8 *next, *arg;
	u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE];


	u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
	u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};


@@ -2076,41 +2183,39 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
		return -EBUSY;
		return -EBUSY;
	}
	}


	baud = pn533_mod_to_baud(dev);
	if (baud < 0) {
		nfc_dev_err(&dev->interface->dev,
			    "Invalid curr modulation %d", dev->poll_mod_curr);
		return baud;
	}

	skb_len = 3 + gb_len; /* ActPass + BR + Next */
	skb_len = 3 + gb_len; /* ActPass + BR + Next */
	if (comm_mode == NFC_COMM_PASSIVE)
	skb_len += PASSIVE_DATA_LEN;
	skb_len += PASSIVE_DATA_LEN;


	if (target && target->nfcid2_len)
	/* NFCID3 */
	skb_len += NFC_NFCID3_MAXSIZE;
	skb_len += NFC_NFCID3_MAXSIZE;
	if (target && !target->nfcid2_len) {
		nfcid3[0] = 0x1;
		nfcid3[1] = 0xfe;
		get_random_bytes(nfcid3 + 2, 6);
	}


	skb = pn533_alloc_skb(dev, skb_len);
	skb = pn533_alloc_skb(dev, skb_len);
	if (!skb)
	if (!skb)
		return -ENOMEM;
		return -ENOMEM;


	*skb_put(skb, 1) = !comm_mode;  /* ActPass */
	*skb_put(skb, 1) = !comm_mode;  /* ActPass */
	*skb_put(skb, 1) = baud;  /* Baud rate */
	*skb_put(skb, 1) = 0x02;  /* 424 kbps */


	next = skb_put(skb, 1);  /* Next */
	next = skb_put(skb, 1);  /* Next */
	*next = 0;
	*next = 0;


	if (comm_mode == NFC_COMM_PASSIVE && baud > 0) {
	/* Copy passive data */
		memcpy(skb_put(skb, PASSIVE_DATA_LEN), passive_data,
	memcpy(skb_put(skb, PASSIVE_DATA_LEN), passive_data, PASSIVE_DATA_LEN);
		       PASSIVE_DATA_LEN);
	*next |= 1;
	*next |= 1;
	}


	if (target && target->nfcid2_len) {
	/* Copy NFCID3 (which is NFCID2 from SENSF_RES) */
	if (target && target->nfcid2_len)
		memcpy(skb_put(skb, NFC_NFCID3_MAXSIZE), target->nfcid2,
		memcpy(skb_put(skb, NFC_NFCID3_MAXSIZE), target->nfcid2,
		       target->nfcid2_len);
		       target->nfcid2_len);
	else
		memcpy(skb_put(skb, NFC_NFCID3_MAXSIZE), nfcid3,
		       NFC_NFCID3_MAXSIZE);
	*next |= 2;
	*next |= 2;
	}


	if (gb != NULL && gb_len > 0) {
	if (gb != NULL && gb_len > 0) {
		memcpy(skb_put(skb, gb_len), gb, gb_len);
		memcpy(skb_put(skb, gb_len), gb, gb_len);
@@ -2127,6 +2232,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,


	*arg = !comm_mode;
	*arg = !comm_mode;


	pn533_rf_field(dev->nfc_dev, 0);

	rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb,
	rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb,
				  pn533_in_dep_link_up_complete, arg);
				  pn533_in_dep_link_up_complete, arg);


@@ -2232,7 +2339,15 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,


	if (mi) {
	if (mi) {
		dev->cmd_complete_mi_arg = arg;
		dev->cmd_complete_mi_arg = arg;
		queue_work(dev->wq, &dev->mi_work);
		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);

		return -EINPROGRESS;
		return -EINPROGRESS;
	}
	}


@@ -2253,6 +2368,50 @@ _error:
	return rc;
	return rc;
}
}


/* 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;
		}

		/* Reserve the TG/MI byte */
		skb_reserve(frag, 1);

		/* MI + TG */
		if (frag_size  == PN533_CMD_DATAFRAME_MAXLEN)
			*skb_push(frag, sizeof(u8)) = (PN533_CMD_MI_MASK | 1);
		else
			*skb_push(frag, sizeof(u8)) =  1; /* TG */

		memcpy(skb_put(frag, frag_size), skb->data, frag_size);

		/* 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);
}

static int pn533_transceive(struct nfc_dev *nfc_dev,
static int pn533_transceive(struct nfc_dev *nfc_dev,
			    struct nfc_target *target, struct sk_buff *skb,
			    struct nfc_target *target, struct sk_buff *skb,
			    data_exchange_cb_t cb, void *cb_context)
			    data_exchange_cb_t cb, void *cb_context)
@@ -2263,15 +2422,6 @@ static int pn533_transceive(struct nfc_dev *nfc_dev,


	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);


	if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
		/* TODO: Implement support to multi-part data exchange */
		nfc_dev_err(&dev->interface->dev,
			    "Data length greater than the max allowed: %d",
			    PN533_CMD_DATAEXCH_DATA_MAXLEN);
		rc = -ENOSYS;
		goto error;
	}

	if (!dev->tgt_active_prot) {
	if (!dev->tgt_active_prot) {
		nfc_dev_err(&dev->interface->dev,
		nfc_dev_err(&dev->interface->dev,
			    "Can't exchange data if there is no active target");
			    "Can't exchange data if there is no active target");
@@ -2299,7 +2449,20 @@ static int pn533_transceive(struct nfc_dev *nfc_dev,
			break;
			break;
		}
		}
	default:
	default:
		/* 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 {
			*skb_push(skb, sizeof(u8)) =  1; /* TG */
			*skb_push(skb, sizeof(u8)) =  1; /* TG */
		}


		rc = pn533_send_data_async(dev, PN533_CMD_IN_DATA_EXCHANGE,
		rc = pn533_send_data_async(dev, PN533_CMD_IN_DATA_EXCHANGE,
					   skb, pn533_data_exchange_complete,
					   skb, pn533_data_exchange_complete,
@@ -2370,7 +2533,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)


static void pn533_wq_mi_recv(struct work_struct *work)
static void pn533_wq_mi_recv(struct work_struct *work)
{
{
	struct pn533 *dev = container_of(work, struct pn533, mi_work);
	struct pn533 *dev = container_of(work, struct pn533, mi_rx_work);


	struct sk_buff *skb;
	struct sk_buff *skb;
	int rc;
	int rc;
@@ -2418,6 +2581,61 @@ error:
	queue_work(dev->wq, &dev->cmd_work);
	queue_work(dev->wq, &dev->cmd_work);
}
}


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;

	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);

	/* 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? */
		rc = pn533_send_cmd_direct_async(dev,PN533_CMD_IN_DATA_EXCHANGE,
						 skb,
						 pn533_data_exchange_complete,
						 dev->cmd_complete_dep_arg);

		break;
	}

	if (rc == 0) /* success */
		return;

	nfc_dev_err(&dev->interface->dev,
		    "Error %d when trying to perform data_exchange", rc);

	dev_kfree_skb(skb);
	kfree(dev->cmd_complete_dep_arg);

error:
	pn533_send_ack(dev, GFP_KERNEL);
	queue_work(dev->wq, &dev->cmd_work);
}

static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
								u8 cfgdata_len)
								u8 cfgdata_len)
{
{
@@ -2562,6 +2780,8 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf)
	u8 rf_field = !!rf;
	u8 rf_field = !!rf;
	int rc;
	int rc;


	rf_field |= PN533_CFGITEM_RF_FIELD_AUTO_RFCA;

	rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD,
	rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD,
				     (u8 *)&rf_field, 1);
				     (u8 *)&rf_field, 1);
	if (rc) {
	if (rc) {
@@ -2605,17 +2825,6 @@ static int pn533_setup(struct pn533 *dev)


	switch (dev->device_type) {
	switch (dev->device_type) {
	case PN533_DEVICE_STD:
	case PN533_DEVICE_STD:
		max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS;
		max_retries.mx_rty_psl = 2;
		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_204;
		timing.dep_timeout = PN533_CONFIG_TIMING_409;

		break;

	case PN533_DEVICE_PASORI:
	case PN533_DEVICE_PASORI:
	case PN533_DEVICE_ACR122U:
	case PN533_DEVICE_ACR122U:
		max_retries.mx_rty_atr = 0x2;
		max_retries.mx_rty_atr = 0x2;
@@ -2729,9 +2938,11 @@ static int pn533_probe(struct usb_interface *interface,


	INIT_WORK(&dev->cmd_work, pn533_wq_cmd);
	INIT_WORK(&dev->cmd_work, pn533_wq_cmd);
	INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete);
	INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete);
	INIT_WORK(&dev->mi_work, pn533_wq_mi_recv);
	INIT_WORK(&dev->mi_rx_work, pn533_wq_mi_recv);
	INIT_WORK(&dev->mi_tx_work, pn533_wq_mi_send);
	INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
	INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
	INIT_WORK(&dev->poll_work, pn533_wq_poll);
	INIT_DELAYED_WORK(&dev->poll_work, pn533_wq_poll);
	INIT_WORK(&dev->rf_work, pn533_wq_rf);
	dev->wq = alloc_ordered_workqueue("pn533", 0);
	dev->wq = alloc_ordered_workqueue("pn533", 0);
	if (dev->wq == NULL)
	if (dev->wq == NULL)
		goto error;
		goto error;
@@ -2741,6 +2952,7 @@ static int pn533_probe(struct usb_interface *interface,
	dev->listen_timer.function = pn533_listen_mode_timer;
	dev->listen_timer.function = pn533_listen_mode_timer;


	skb_queue_head_init(&dev->resp_q);
	skb_queue_head_init(&dev->resp_q);
	skb_queue_head_init(&dev->fragment_skb);


	INIT_LIST_HEAD(&dev->cmd_queue);
	INIT_LIST_HEAD(&dev->cmd_queue);


@@ -2842,6 +3054,7 @@ static void pn533_disconnect(struct usb_interface *interface)
	usb_kill_urb(dev->in_urb);
	usb_kill_urb(dev->in_urb);
	usb_kill_urb(dev->out_urb);
	usb_kill_urb(dev->out_urb);


	flush_delayed_work(&dev->poll_work);
	destroy_workqueue(dev->wq);
	destroy_workqueue(dev->wq);


	skb_queue_purge(&dev->resp_q);
	skb_queue_purge(&dev->resp_q);
+345 −15

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Original line Diff line number Diff line
@@ -45,7 +45,7 @@ static int pn544_mei_probe(struct mei_cl_device *device,


	r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
	r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
			    MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
			    MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
			    &phy->hdev);
			    NULL, &phy->hdev);
	if (r < 0) {
	if (r < 0) {
		nfc_mei_phy_free(phy);
		nfc_mei_phy_free(phy);


Loading