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

Commit 2e486868 authored by John W. Linville's avatar John W. Linville
Browse files
parents 934b9d1e 51ad304c
Loading
Loading
Loading
Loading
+543 −119
Original line number Original line Diff line number Diff line
@@ -45,6 +45,9 @@ static const struct usb_device_id pn533_table[] = {
};
};
MODULE_DEVICE_TABLE(usb, pn533_table);
MODULE_DEVICE_TABLE(usb, pn533_table);


/* How much time we spend listening for initiators */
#define PN533_LISTEN_TIME 2

/* frame definitions */
/* frame definitions */
#define PN533_FRAME_TAIL_SIZE 2
#define PN533_FRAME_TAIL_SIZE 2
#define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \
#define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \
@@ -74,6 +77,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
#define PN533_CMD_IN_RELEASE 0x52
#define PN533_CMD_IN_RELEASE 0x52
#define PN533_CMD_IN_JUMP_FOR_DEP 0x56
#define PN533_CMD_IN_JUMP_FOR_DEP 0x56


#define PN533_CMD_TG_INIT_AS_TARGET 0x8c
#define PN533_CMD_TG_GET_DATA 0x86
#define PN533_CMD_TG_SET_DATA 0x8e

#define PN533_CMD_RESPONSE(cmd) (cmd + 1)
#define PN533_CMD_RESPONSE(cmd) (cmd + 1)


/* PN533 Return codes */
/* PN533 Return codes */
@@ -81,6 +88,9 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
#define PN533_CMD_MI_MASK 0x40
#define PN533_CMD_MI_MASK 0x40
#define PN533_CMD_RET_SUCCESS 0x00
#define PN533_CMD_RET_SUCCESS 0x00


/* PN533 status codes */
#define PN533_STATUS_TARGET_RELEASED 0x29

struct pn533;
struct pn533;


typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg,
typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg,
@@ -97,8 +107,14 @@ struct pn533_fw_version {
};
};


/* PN533_CMD_RF_CONFIGURATION */
/* PN533_CMD_RF_CONFIGURATION */
#define PN533_CFGITEM_TIMING 0x02
#define PN533_CFGITEM_MAX_RETRIES 0x05
#define PN533_CFGITEM_MAX_RETRIES 0x05


#define PN533_CONFIG_TIMING_102 0xb
#define PN533_CONFIG_TIMING_204 0xc
#define PN533_CONFIG_TIMING_409 0xd
#define PN533_CONFIG_TIMING_819 0xe

#define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00
#define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00
#define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF
#define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF


@@ -108,6 +124,12 @@ struct pn533_config_max_retries {
	u8 mx_rty_passive_act;
	u8 mx_rty_passive_act;
} __packed;
} __packed;


struct pn533_config_timing {
	u8 rfu;
	u8 atr_res_timeout;
	u8 dep_timeout;
} __packed;

/* PN533_CMD_IN_LIST_PASSIVE_TARGET */
/* PN533_CMD_IN_LIST_PASSIVE_TARGET */


/* felica commands opcode */
/* felica commands opcode */
@@ -144,6 +166,7 @@ enum {
	PN533_POLL_MOD_424KBPS_FELICA,
	PN533_POLL_MOD_424KBPS_FELICA,
	PN533_POLL_MOD_106KBPS_JEWEL,
	PN533_POLL_MOD_106KBPS_JEWEL,
	PN533_POLL_MOD_847KBPS_B,
	PN533_POLL_MOD_847KBPS_B,
	PN533_LISTEN_MOD,


	__PN533_POLL_MOD_AFTER_LAST,
	__PN533_POLL_MOD_AFTER_LAST,
};
};
@@ -211,6 +234,9 @@ const struct pn533_poll_modulations poll_mod[] = {
		},
		},
		.len = 3,
		.len = 3,
	},
	},
	[PN533_LISTEN_MOD] = {
		.len = 0,
	},
};
};


/* PN533_CMD_IN_ATR */
/* PN533_CMD_IN_ATR */
@@ -237,7 +263,7 @@ struct pn533_cmd_jump_dep {
	u8 active;
	u8 active;
	u8 baud;
	u8 baud;
	u8 next;
	u8 next;
	u8 gt[];
	u8 data[];
} __packed;
} __packed;


struct pn533_cmd_jump_dep_response {
struct pn533_cmd_jump_dep_response {
@@ -253,6 +279,29 @@ struct pn533_cmd_jump_dep_response {
	u8 gt[];
	u8 gt[];
} __packed;
} __packed;



/* PN533_TG_INIT_AS_TARGET */
#define PN533_INIT_TARGET_PASSIVE 0x1
#define PN533_INIT_TARGET_DEP 0x2

#define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3
#define PN533_INIT_TARGET_RESP_ACTIVE     0x1
#define PN533_INIT_TARGET_RESP_DEP        0x4

struct pn533_cmd_init_target {
	u8 mode;
	u8 mifare[6];
	u8 felica[18];
	u8 nfcid3[10];
	u8 gb_len;
	u8 gb[];
} __packed;

struct pn533_cmd_init_target_response {
	u8 mode;
	u8 cmd[];
} __packed;

struct pn533 {
struct pn533 {
	struct usb_device *udev;
	struct usb_device *udev;
	struct usb_interface *interface;
	struct usb_interface *interface;
@@ -270,22 +319,31 @@ struct pn533 {


	struct workqueue_struct	*wq;
	struct workqueue_struct	*wq;
	struct work_struct cmd_work;
	struct work_struct cmd_work;
	struct work_struct poll_work;
	struct work_struct mi_work;
	struct work_struct mi_work;
	struct work_struct tg_work;
	struct timer_list listen_timer;
	struct pn533_frame *wq_in_frame;
	struct pn533_frame *wq_in_frame;
	int wq_in_error;
	int wq_in_error;
	int cancel_listen;


	pn533_cmd_complete_t cmd_complete;
	pn533_cmd_complete_t cmd_complete;
	void *cmd_complete_arg;
	void *cmd_complete_arg;
	struct semaphore cmd_lock;
	struct mutex cmd_lock;
	u8 cmd;
	u8 cmd;


	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;
	u8 poll_mod_curr;
	u8 poll_mod_curr;
	u32 poll_protocols;
	u32 poll_protocols;
	u32 listen_protocols;

	u8 *gb;
	size_t gb_len;


	u8 tgt_available_prots;
	u8 tgt_available_prots;
	u8 tgt_active_prot;
	u8 tgt_active_prot;
	u8 tgt_mode;
};
};


struct pn533_frame {
struct pn533_frame {
@@ -405,7 +463,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work)
					PN533_FRAME_CMD_PARAMS_LEN(in_frame));
					PN533_FRAME_CMD_PARAMS_LEN(in_frame));


	if (rc != -EINPROGRESS)
	if (rc != -EINPROGRESS)
		up(&dev->cmd_lock);
		mutex_unlock(&dev->cmd_lock);
}
}


static void pn533_recv_response(struct urb *urb)
static void pn533_recv_response(struct urb *urb)
@@ -583,7 +641,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,


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


	if (down_trylock(&dev->cmd_lock))
	if (!mutex_trylock(&dev->cmd_lock))
		return -EBUSY;
		return -EBUSY;


	rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame,
	rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame,
@@ -593,7 +651,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,


	return 0;
	return 0;
error:
error:
	up(&dev->cmd_lock);
	mutex_unlock(&dev->cmd_lock);
	return rc;
	return rc;
}
}


@@ -963,6 +1021,11 @@ static int pn533_target_found(struct pn533 *dev,
	return 0;
	return 0;
}
}


static inline void pn533_poll_next_mod(struct pn533 *dev)
{
	dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
}

static void pn533_poll_reset_mod_list(struct pn533 *dev)
static void pn533_poll_reset_mod_list(struct pn533 *dev)
{
{
	dev->poll_mod_count = 0;
	dev->poll_mod_count = 0;
@@ -975,102 +1038,283 @@ static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index)
	dev->poll_mod_count++;
	dev->poll_mod_count++;
}
}


static void pn533_poll_create_mod_list(struct pn533 *dev, u32 protocols)
static void pn533_poll_create_mod_list(struct pn533 *dev,
				       u32 im_protocols, u32 tm_protocols)
{
{
	pn533_poll_reset_mod_list(dev);
	pn533_poll_reset_mod_list(dev);


	if (protocols & NFC_PROTO_MIFARE_MASK
	if (im_protocols & NFC_PROTO_MIFARE_MASK
					|| protocols & NFC_PROTO_ISO14443_MASK
	    || im_protocols & NFC_PROTO_ISO14443_MASK
					|| protocols & NFC_PROTO_NFC_DEP_MASK)
	    || im_protocols & NFC_PROTO_NFC_DEP_MASK)
		pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A);
		pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A);


	if (protocols & NFC_PROTO_FELICA_MASK
	if (im_protocols & NFC_PROTO_FELICA_MASK
					|| protocols & NFC_PROTO_NFC_DEP_MASK) {
	    || im_protocols & NFC_PROTO_NFC_DEP_MASK) {
		pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA);
		pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA);
		pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA);
		pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA);
	}
	}


	if (protocols & NFC_PROTO_JEWEL_MASK)
	if (im_protocols & NFC_PROTO_JEWEL_MASK)
		pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);
		pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);


	if (protocols & NFC_PROTO_ISO14443_MASK)
	if (im_protocols & NFC_PROTO_ISO14443_MASK)
		pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
		pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);

	if (tm_protocols)
		pn533_poll_add_mod(dev, PN533_LISTEN_MOD);
}
}


static void pn533_start_poll_frame(struct pn533_frame *frame,
static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
					struct pn533_poll_modulations *mod)
				     u8 *params, int params_len)
{
{
	struct pn533_poll_response *resp;
	int rc;


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


	memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
	resp = (struct pn533_poll_response *) params;
	frame->datalen += mod->len;
	if (resp->nbtg) {
		rc = pn533_target_found(dev, resp, params_len);

		/* We must stop the poll after a valid target found */
		if (rc == 0) {
			pn533_poll_reset_mod_list(dev);
			return 0;
		}
	}

	return -EAGAIN;
}

static int pn533_init_target_frame(struct pn533_frame *frame,
				   u8 *gb, size_t gb_len)
{
	struct pn533_cmd_init_target *cmd;
	size_t cmd_len;
	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 */
	u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */
			       0x0, 0x0, 0x0,
			       0x40}; /* SEL_RES for DEP */

	cmd_len = sizeof(struct pn533_cmd_init_target) + gb_len + 1;
	cmd = kzalloc(cmd_len, GFP_KERNEL);
	if (cmd == NULL)
		return -ENOMEM;

	pn533_tx_frame_init(frame, PN533_CMD_TG_INIT_AS_TARGET);

	/* DEP support only */
	cmd->mode |= PN533_INIT_TARGET_DEP;

	/* Felica params */
	memcpy(cmd->felica, felica_params, 18);
	get_random_bytes(cmd->felica + 2, 6);

	/* NFCID3 */
	memset(cmd->nfcid3, 0, 10);
	memcpy(cmd->nfcid3, cmd->felica, 8);

	/* MIFARE params */
	memcpy(cmd->mifare, mifare_params, 6);

	/* General bytes */
	cmd->gb_len = gb_len;
	memcpy(cmd->gb, gb, gb_len);

	/* Len Tk */
	cmd->gb[gb_len] = 0;

	memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), cmd, cmd_len);

	frame->datalen += cmd_len;


	pn533_tx_frame_finish(frame);
	pn533_tx_frame_finish(frame);

	kfree(cmd);

	return 0;
}
}


static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg,
				      u8 *params, int params_len)
				      u8 *params, int params_len)
{
{
	struct pn533_poll_response *resp;
	struct sk_buff *skb_resp = arg;
	struct pn533_poll_modulations *next_mod;
	struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data;
	int rc;


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


	if (params_len == -ENOENT) {
	if (params_len < 0) {
		nfc_dev_dbg(&dev->interface->dev, "Polling operation has been"
		nfc_dev_err(&dev->interface->dev,
								" stopped");
			    "Error %d when starting as a target",
		goto stop_poll;
			    params_len);

		return params_len;
	}

	if (params_len > 0 && params[0] != 0) {
		nfc_tm_deactivated(dev->nfc_dev);

		dev->tgt_mode = 0;

		kfree_skb(skb_resp);
		return 0;
	}
	}


	skb_put(skb_resp, PN533_FRAME_SIZE(in_frame));
	skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN);
	skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE);

	return nfc_tm_data_received(dev->nfc_dev, skb_resp);
}

static void pn533_wq_tg_get_data(struct work_struct *work)
{
	struct pn533 *dev = container_of(work, struct pn533, tg_work);
	struct pn533_frame *in_frame;
	struct sk_buff *skb_resp;
	size_t skb_resp_len;

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

	skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN +
		PN533_CMD_DATAEXCH_DATA_MAXLEN +
		PN533_FRAME_TAIL_SIZE;

	skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL);
	if (!skb_resp)
		return;

	in_frame = (struct pn533_frame *)skb_resp->data;

	pn533_tx_frame_init(dev->out_frame, PN533_CMD_TG_GET_DATA);
	pn533_tx_frame_finish(dev->out_frame);

	pn533_send_cmd_frame_async(dev, dev->out_frame, in_frame,
				   skb_resp_len,
				   pn533_tm_get_data_complete,
				   skb_resp, GFP_KERNEL);

	return;
}

#define ATR_REQ_GB_OFFSET 17
static int pn533_init_target_complete(struct pn533 *dev, void *arg,
				      u8 *params, int params_len)
{
	struct pn533_cmd_init_target_response *resp;
	u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb;
	size_t gb_len;
	int rc;

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

	if (params_len < 0) {
	if (params_len < 0) {
		nfc_dev_err(&dev->interface->dev, "Error %d when running poll",
		nfc_dev_err(&dev->interface->dev,
			    "Error %d when starting as a target",
			    params_len);
			    params_len);
		goto stop_poll;

		return params_len;
	}
	}


	resp = (struct pn533_poll_response *) params;
	if (params_len < ATR_REQ_GB_OFFSET + 1)
	if (resp->nbtg) {
		return -EINVAL;
		rc = pn533_target_found(dev, resp, params_len);


		/* We must stop the poll after a valid target found */
	resp = (struct pn533_cmd_init_target_response *) params;
		if (rc == 0)

			goto stop_poll;
	nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x param len %d\n",
		    resp->mode, params_len);

	frame = resp->mode & PN533_INIT_TARGET_RESP_FRAME_MASK;
	if (frame == PN533_INIT_TARGET_RESP_ACTIVE)
		comm_mode = NFC_COMM_ACTIVE;

	/* Again, only DEP */
	if ((resp->mode & PN533_INIT_TARGET_RESP_DEP) == 0)
		return -EOPNOTSUPP;


		if (rc != -EAGAIN)
	gb = resp->cmd + ATR_REQ_GB_OFFSET;
			nfc_dev_err(&dev->interface->dev, "The target found is"
	gb_len = params_len - (ATR_REQ_GB_OFFSET + 1);
					" not valid - continuing to poll");

	rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
			      comm_mode, gb, gb_len);
	if (rc < 0) {
		nfc_dev_err(&dev->interface->dev,
			    "Error when signaling target activation");
		return rc;
	}
	}


	dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
	dev->tgt_mode = 1;


	next_mod = dev->poll_mod_active[dev->poll_mod_curr];
	queue_work(dev->wq, &dev->tg_work);


	nfc_dev_dbg(&dev->interface->dev, "Polling next modulation (0x%x)",
	return 0;
							dev->poll_mod_curr);
}

static void pn533_listen_mode_timer(unsigned long data)
{
	struct pn533 *dev = (struct pn533 *) data;

	nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout");

	/* An ack will cancel the last issued command (poll) */
	pn533_send_ack(dev, GFP_ATOMIC);

	dev->cancel_listen = 1;

	mutex_unlock(&dev->cmd_lock);

	pn533_poll_next_mod(dev);


	pn533_start_poll_frame(dev->out_frame, next_mod);
	queue_work(dev->wq, &dev->poll_work);
}

static int pn533_poll_complete(struct pn533 *dev, void *arg,
			       u8 *params, int params_len)
{
	struct pn533_poll_modulations *cur_mod;
	int rc;

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

	if (params_len == -ENOENT) {
		if (dev->poll_mod_count != 0)
			return 0;


	/* Don't need to down the semaphore again */
		nfc_dev_err(&dev->interface->dev,
	rc = __pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
			    "Polling operation has been stopped");
				dev->in_maxlen, pn533_start_poll_complete,
				NULL, GFP_ATOMIC);


	if (rc == -EPERM) {
		nfc_dev_dbg(&dev->interface->dev, "Cannot poll next modulation"
					" because poll has been stopped");
		goto stop_poll;
		goto stop_poll;
	}
	}


	if (rc) {
	if (params_len < 0) {
		nfc_dev_err(&dev->interface->dev, "Error %d when trying to poll"
		nfc_dev_err(&dev->interface->dev,
							" next modulation", rc);
			    "Error %d when running poll", params_len);

		goto stop_poll;
		goto stop_poll;
	}
	}


	/* Inform caller function to do not up the semaphore */
	cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
	return -EINPROGRESS;

	if (cur_mod->len == 0) {
		del_timer(&dev->listen_timer);

		return pn533_init_target_complete(dev, arg, params, params_len);
	} else {
		rc = pn533_start_poll_complete(dev, arg, params, params_len);
		if (!rc)
			return rc;
	}

	pn533_poll_next_mod(dev);

	queue_work(dev->wq, &dev->poll_work);

	return 0;


stop_poll:
stop_poll:
	pn533_poll_reset_mod_list(dev);
	pn533_poll_reset_mod_list(dev);
@@ -1078,61 +1322,104 @@ static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
	return 0;
	return 0;
}
}


static int pn533_start_poll(struct nfc_dev *nfc_dev, u32 protocols)
static void pn533_build_poll_frame(struct pn533 *dev,
				   struct pn533_frame *frame,
				   struct pn533_poll_modulations *mod)
{
{
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
	nfc_dev_dbg(&dev->interface->dev, "mod len %d\n", mod->len);
	struct pn533_poll_modulations *start_mod;
	int rc;


	nfc_dev_dbg(&dev->interface->dev, "%s - protocols=0x%x", __func__,
	if (mod->len == 0) {
								protocols);
		/* Listen mode */
		pn533_init_target_frame(frame, dev->gb, dev->gb_len);
	} else {
		/* Polling mode */
		pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET);


	if (dev->poll_mod_count) {
		memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
		nfc_dev_err(&dev->interface->dev, "Polling operation already"
		frame->datalen += mod->len;
								" active");

		return -EBUSY;
		pn533_tx_frame_finish(frame);
	}
}
}


	if (dev->tgt_active_prot) {
static int pn533_send_poll_frame(struct pn533 *dev)
		nfc_dev_err(&dev->interface->dev, "Cannot poll with a target"
{
							" already activated");
	struct pn533_poll_modulations *cur_mod;
		return -EBUSY;
	int rc;

	cur_mod = dev->poll_mod_active[dev->poll_mod_curr];

	pn533_build_poll_frame(dev, dev->out_frame, cur_mod);

	rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
				dev->in_maxlen,	pn533_poll_complete,
				NULL, GFP_KERNEL);
	if (rc)
		nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc);

	return rc;
}
}


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

	cur_mod = dev->poll_mod_active[dev->poll_mod_curr];


	if (!dev->poll_mod_count) {
	nfc_dev_dbg(&dev->interface->dev,
		nfc_dev_err(&dev->interface->dev, "No valid protocols"
		    "%s cancel_listen %d modulation len %d",
								" specified");
		    __func__, dev->cancel_listen, cur_mod->len);
		rc = -EINVAL;

		goto error;
	if (dev->cancel_listen == 1) {
		dev->cancel_listen = 0;
		usb_kill_urb(dev->in_urb);
	}
	}


	nfc_dev_dbg(&dev->interface->dev, "It will poll %d modulations types",
	rc = pn533_send_poll_frame(dev);
							dev->poll_mod_count);
	if (rc)
		return;


	dev->poll_mod_curr = 0;
	if (cur_mod->len == 0 && dev->poll_mod_count > 1)
	start_mod = dev->poll_mod_active[dev->poll_mod_curr];
		mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ);


	pn533_start_poll_frame(dev->out_frame, start_mod);
	return;
}


	rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
static int pn533_start_poll(struct nfc_dev *nfc_dev,
				dev->in_maxlen,	pn533_start_poll_complete,
			    u32 im_protocols, u32 tm_protocols)
				NULL, GFP_KERNEL);
{
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);


	if (rc) {
	nfc_dev_dbg(&dev->interface->dev,
		nfc_dev_err(&dev->interface->dev, "Error %d when trying to"
		    "%s: im protocols 0x%x tm protocols 0x%x",
							" start poll", rc);
		    __func__, im_protocols, tm_protocols);
		goto error;

	if (dev->tgt_active_prot) {
		nfc_dev_err(&dev->interface->dev,
			    "Cannot poll with a target already activated");
		return -EBUSY;
	}
	}


	dev->poll_protocols = protocols;
	if (dev->tgt_mode) {
		nfc_dev_err(&dev->interface->dev,
			    "Cannot poll while already being activated");
		return -EBUSY;
	}


	return 0;
	if (tm_protocols) {
		dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len);
		if (dev->gb == NULL)
			tm_protocols = 0;
	}


error:
	dev->poll_mod_curr = 0;
	pn533_poll_reset_mod_list(dev);
	pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
	return rc;
	dev->poll_protocols = im_protocols;
	dev->listen_protocols = tm_protocols;

	return pn533_send_poll_frame(dev);
}
}


static void pn533_stop_poll(struct nfc_dev *nfc_dev)
static void pn533_stop_poll(struct nfc_dev *nfc_dev)
@@ -1141,6 +1428,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)


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


	del_timer(&dev->listen_timer);

	if (!dev->poll_mod_count) {
	if (!dev->poll_mod_count) {
		nfc_dev_dbg(&dev->interface->dev, "Polling operation was not"
		nfc_dev_dbg(&dev->interface->dev, "Polling operation was not"
								" running");
								" running");
@@ -1152,6 +1441,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)


	/* prevent pn533_start_poll_complete to issue a new poll meanwhile */
	/* prevent pn533_start_poll_complete to issue a new poll meanwhile */
	usb_kill_urb(dev->in_urb);
	usb_kill_urb(dev->in_urb);

	pn533_poll_reset_mod_list(dev);
}
}


static int pn533_activate_target_nfcdep(struct pn533 *dev)
static int pn533_activate_target_nfcdep(struct pn533 *dev)
@@ -1349,13 +1640,29 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
	return 0;
	return 0;
}
}


static int pn533_mod_to_baud(struct pn533 *dev)
{
	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
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 pn533_cmd_jump_dep *cmd;
	struct pn533_cmd_jump_dep *cmd;
	u8 cmd_len;
	u8 cmd_len, *data_ptr;
	int rc;
	u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
	int rc, baud;


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


@@ -1371,7 +1678,17 @@ 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;
	}

	cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len;
	cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len;
	if (comm_mode == NFC_COMM_PASSIVE)
		cmd_len += PASSIVE_DATA_LEN;

	cmd = kzalloc(cmd_len, GFP_KERNEL);
	cmd = kzalloc(cmd_len, GFP_KERNEL);
	if (cmd == NULL)
	if (cmd == NULL)
		return -ENOMEM;
		return -ENOMEM;
@@ -1379,10 +1696,18 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
	pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP);
	pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP);


	cmd->active = !comm_mode;
	cmd->active = !comm_mode;
	cmd->baud = 0;
	cmd->next = 0;
	cmd->baud = baud;
	data_ptr = cmd->data;
	if (comm_mode == NFC_COMM_PASSIVE && cmd->baud > 0) {
		memcpy(data_ptr, passive_data, PASSIVE_DATA_LEN);
		cmd->next |= 1;
		data_ptr += PASSIVE_DATA_LEN;
	}

	if (gb != NULL && gb_len > 0) {
	if (gb != NULL && gb_len > 0) {
		cmd->next = 4; /* We have some Gi */
		cmd->next |= 4; /* We have some Gi */
		memcpy(cmd->gt, gb, gb_len);
		memcpy(data_ptr, gb, gb_len);
	} else {
	} else {
		cmd->next = 0;
		cmd->next = 0;
	}
	}
@@ -1407,15 +1732,25 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,


static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
{
{
	pn533_deactivate_target(nfc_dev, 0);
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);


	return 0;
	pn533_poll_reset_mod_list(dev);

	if (dev->tgt_mode || dev->tgt_active_prot) {
		pn533_send_ack(dev, GFP_KERNEL);
		usb_kill_urb(dev->in_urb);
	}
	}


#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
	dev->tgt_active_prot = 0;
#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
	dev->tgt_mode = 0;

	skb_queue_purge(&dev->resp_q);


static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
	return 0;
}

static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb,
				bool target)
{
{
	int payload_len = skb->len;
	int payload_len = skb->len;
	struct pn533_frame *out_frame;
	struct pn533_frame *out_frame;
@@ -1432,14 +1767,20 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
		return -ENOSYS;
		return -ENOSYS;
	}
	}


	if (target == true) {
		skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
		skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
		out_frame = (struct pn533_frame *) skb->data;
		out_frame = (struct pn533_frame *) skb->data;


		pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE);
		pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE);

		tg = 1;
		tg = 1;
		memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
		memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
		out_frame->datalen += sizeof(u8);
		out_frame->datalen += sizeof(u8);
	} else {
		skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1);
		out_frame = (struct pn533_frame *) skb->data;
		pn533_tx_frame_init(out_frame, PN533_CMD_TG_SET_DATA);
	}



	/* The data is already in the out_frame, just update the datalen */
	/* The data is already in the out_frame, just update the datalen */
	out_frame->datalen += payload_len;
	out_frame->datalen += payload_len;
@@ -1550,7 +1891,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
	return 0;
	return 0;
}
}


static int pn533_data_exchange(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)
{
{
@@ -1570,7 +1911,7 @@ static int pn533_data_exchange(struct nfc_dev *nfc_dev,
		goto error;
		goto error;
	}
	}


	rc = pn533_data_exchange_tx_frame(dev, skb);
	rc = pn533_build_tx_frame(dev, skb, true);
	if (rc)
	if (rc)
		goto error;
		goto error;


@@ -1618,6 +1959,63 @@ static int pn533_data_exchange(struct nfc_dev *nfc_dev,
	return rc;
	return rc;
}
}


static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
				  u8 *params, int params_len)
{
	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);

	if (params_len < 0) {
		nfc_dev_err(&dev->interface->dev,
			    "Error %d when sending data",
			    params_len);

		return params_len;
	}

	if (params_len > 0 && params[0] != 0) {
		nfc_tm_deactivated(dev->nfc_dev);

		dev->tgt_mode = 0;

		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);
	struct pn533_frame *out_frame;
	int rc;

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

	rc = pn533_build_tx_frame(dev, skb, false);
	if (rc)
		goto error;

	out_frame = (struct pn533_frame *) skb->data;

	rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame,
					dev->in_maxlen, pn533_tm_send_complete,
					NULL, GFP_KERNEL);
	if (rc) {
		nfc_dev_err(&dev->interface->dev,
			    "Error %d when trying to send data", rc);
		goto error;
	}

	return 0;

error:
	kfree_skb(skb);

	return rc;
}

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_work);
@@ -1638,7 +2036,7 @@ static void pn533_wq_mi_recv(struct work_struct *work)


	skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN);
	skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN);


	rc = pn533_data_exchange_tx_frame(dev, skb_cmd);
	rc = pn533_build_tx_frame(dev, skb_cmd, true);
	if (rc)
	if (rc)
		goto error_frame;
		goto error_frame;


@@ -1677,7 +2075,7 @@ static void pn533_wq_mi_recv(struct work_struct *work)


	kfree(arg);
	kfree(arg);


	up(&dev->cmd_lock);
	mutex_unlock(&dev->cmd_lock);
}
}


static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
@@ -1712,7 +2110,8 @@ struct nfc_ops pn533_nfc_ops = {
	.stop_poll = pn533_stop_poll,
	.stop_poll = pn533_stop_poll,
	.activate_target = pn533_activate_target,
	.activate_target = pn533_activate_target,
	.deactivate_target = pn533_deactivate_target,
	.deactivate_target = pn533_deactivate_target,
	.data_exchange = pn533_data_exchange,
	.im_transceive = pn533_transceive,
	.tm_send = pn533_tm_send,
};
};


static int pn533_probe(struct usb_interface *interface,
static int pn533_probe(struct usb_interface *interface,
@@ -1723,6 +2122,7 @@ static int pn533_probe(struct usb_interface *interface,
	struct usb_host_interface *iface_desc;
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;
	struct usb_endpoint_descriptor *endpoint;
	struct pn533_config_max_retries max_retries;
	struct pn533_config_max_retries max_retries;
	struct pn533_config_timing timing;
	int in_endpoint = 0;
	int in_endpoint = 0;
	int out_endpoint = 0;
	int out_endpoint = 0;
	int rc = -ENOMEM;
	int rc = -ENOMEM;
@@ -1735,7 +2135,7 @@ static int pn533_probe(struct usb_interface *interface,


	dev->udev = usb_get_dev(interface_to_usbdev(interface));
	dev->udev = usb_get_dev(interface_to_usbdev(interface));
	dev->interface = interface;
	dev->interface = interface;
	sema_init(&dev->cmd_lock, 1);
	mutex_init(&dev->cmd_lock);


	iface_desc = interface->cur_altsetting;
	iface_desc = interface->cur_altsetting;
	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
@@ -1779,12 +2179,18 @@ static int pn533_probe(struct usb_interface *interface,


	INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete);
	INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete);
	INIT_WORK(&dev->mi_work, pn533_wq_mi_recv);
	INIT_WORK(&dev->mi_work, pn533_wq_mi_recv);
	INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
	INIT_WORK(&dev->poll_work, pn533_wq_poll);
	dev->wq = alloc_workqueue("pn533",
	dev->wq = alloc_workqueue("pn533",
				  WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
				  WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
				  1);
				  1);
	if (dev->wq == NULL)
	if (dev->wq == NULL)
		goto error;
		goto error;


	init_timer(&dev->listen_timer);
	dev->listen_timer.data = (unsigned long) dev;
	dev->listen_timer.function = pn533_listen_mode_timer;

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


	usb_set_intfdata(interface, dev);
	usb_set_intfdata(interface, dev);
@@ -1830,13 +2236,29 @@ static int pn533_probe(struct usb_interface *interface,
	if (rc) {
	if (rc) {
		nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES"
		nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES"
								" config");
								" config");
		goto free_nfc_dev;
		goto unregister_nfc_dev;
	}

	timing.rfu = PN533_CONFIG_TIMING_102;
	timing.atr_res_timeout = PN533_CONFIG_TIMING_204;
	timing.dep_timeout = PN533_CONFIG_TIMING_409;

	rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
				(u8 *) &timing, sizeof(timing));
	if (rc) {
		nfc_dev_err(&dev->interface->dev,
			    "Error on setting RF timings");
		goto unregister_nfc_dev;
	}
	}


	return 0;
	return 0;


unregister_nfc_dev:
	nfc_unregister_device(dev->nfc_dev);

free_nfc_dev:
free_nfc_dev:
	nfc_free_device(dev->nfc_dev);
	nfc_free_device(dev->nfc_dev);

destroy_wq:
destroy_wq:
	destroy_workqueue(dev->wq);
	destroy_workqueue(dev->wq);
error:
error:
@@ -1865,6 +2287,8 @@ static void pn533_disconnect(struct usb_interface *interface)


	skb_queue_purge(&dev->resp_q);
	skb_queue_purge(&dev->resp_q);


	del_timer(&dev->listen_timer);

	kfree(dev->in_frame);
	kfree(dev->in_frame);
	usb_free_urb(dev->in_urb);
	usb_free_urb(dev->in_urb);
	kfree(dev->out_frame);
	kfree(dev->out_frame);
+6 −4
Original line number Original line Diff line number Diff line
@@ -576,7 +576,8 @@ static int pn544_hci_xmit(struct nfc_shdlc *shdlc, struct sk_buff *skb)
	return pn544_hci_i2c_write(client, skb->data, skb->len);
	return pn544_hci_i2c_write(client, skb->data, skb->len);
}
}


static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols)
static int pn544_hci_start_poll(struct nfc_shdlc *shdlc,
				u32 im_protocols, u32 tm_protocols)
{
{
	struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc);
	struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc);
	u8 phases = 0;
	u8 phases = 0;
@@ -584,7 +585,8 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols)
	u8 duration[2];
	u8 duration[2];
	u8 activated;
	u8 activated;


	pr_info(DRIVER_DESC ": %s protocols = %d\n", __func__, protocols);
	pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",
		__func__, im_protocols, tm_protocols);


	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
@@ -604,10 +606,10 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols)
	if (r < 0)
	if (r < 0)
		return r;
		return r;


	if (protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK |
	if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK |
			 NFC_PROTO_JEWEL_MASK))
			 NFC_PROTO_JEWEL_MASK))
		phases |= 1;		/* Type A */
		phases |= 1;		/* Type A */
	if (protocols & NFC_PROTO_FELICA_MASK) {
	if (im_protocols & NFC_PROTO_FELICA_MASK) {
		phases |= (1 << 2);	/* Type F 212 */
		phases |= (1 << 2);	/* Type F 212 */
		phases |= (1 << 3);	/* Type F 424 */
		phases |= (1 << 3);	/* Type F 424 */
	}
	}
+12 −0

File changed.

Preview size limit exceeded, changes collapsed.

+2 −1

File changed.

Preview size limit exceeded, changes collapsed.

+11 −3

File changed.

Preview size limit exceeded, changes collapsed.

Loading