|
@@ -45,6 +45,9 @@ static const struct usb_device_id pn533_table[] = {
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(usb, pn533_table);
|
|
|
|
|
|
+/* How much time we spend listening for initiators */
|
|
|
+#define PN533_LISTEN_TIME 2
|
|
|
+
|
|
|
/* frame definitions */
|
|
|
#define PN533_FRAME_TAIL_SIZE 2
|
|
|
#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_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)
|
|
|
|
|
|
/* PN533 Return codes */
|
|
@@ -81,6 +88,9 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
|
|
|
#define PN533_CMD_MI_MASK 0x40
|
|
|
#define PN533_CMD_RET_SUCCESS 0x00
|
|
|
|
|
|
+/* PN533 status codes */
|
|
|
+#define PN533_STATUS_TARGET_RELEASED 0x29
|
|
|
+
|
|
|
struct pn533;
|
|
|
|
|
|
typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg,
|
|
@@ -97,8 +107,14 @@ struct pn533_fw_version {
|
|
|
};
|
|
|
|
|
|
/* PN533_CMD_RF_CONFIGURATION */
|
|
|
+#define PN533_CFGITEM_TIMING 0x02
|
|
|
#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_ENDLESS 0xFF
|
|
|
|
|
@@ -108,6 +124,12 @@ struct pn533_config_max_retries {
|
|
|
u8 mx_rty_passive_act;
|
|
|
} __packed;
|
|
|
|
|
|
+struct pn533_config_timing {
|
|
|
+ u8 rfu;
|
|
|
+ u8 atr_res_timeout;
|
|
|
+ u8 dep_timeout;
|
|
|
+} __packed;
|
|
|
+
|
|
|
/* PN533_CMD_IN_LIST_PASSIVE_TARGET */
|
|
|
|
|
|
/* felica commands opcode */
|
|
@@ -144,6 +166,7 @@ enum {
|
|
|
PN533_POLL_MOD_424KBPS_FELICA,
|
|
|
PN533_POLL_MOD_106KBPS_JEWEL,
|
|
|
PN533_POLL_MOD_847KBPS_B,
|
|
|
+ PN533_LISTEN_MOD,
|
|
|
|
|
|
__PN533_POLL_MOD_AFTER_LAST,
|
|
|
};
|
|
@@ -211,6 +234,9 @@ const struct pn533_poll_modulations poll_mod[] = {
|
|
|
},
|
|
|
.len = 3,
|
|
|
},
|
|
|
+ [PN533_LISTEN_MOD] = {
|
|
|
+ .len = 0,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
/* PN533_CMD_IN_ATR */
|
|
@@ -237,7 +263,7 @@ struct pn533_cmd_jump_dep {
|
|
|
u8 active;
|
|
|
u8 baud;
|
|
|
u8 next;
|
|
|
- u8 gt[];
|
|
|
+ u8 data[];
|
|
|
} __packed;
|
|
|
|
|
|
struct pn533_cmd_jump_dep_response {
|
|
@@ -253,6 +279,29 @@ struct pn533_cmd_jump_dep_response {
|
|
|
u8 gt[];
|
|
|
} __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 usb_device *udev;
|
|
|
struct usb_interface *interface;
|
|
@@ -270,22 +319,31 @@ struct pn533 {
|
|
|
|
|
|
struct workqueue_struct *wq;
|
|
|
struct work_struct cmd_work;
|
|
|
+ struct work_struct poll_work;
|
|
|
struct work_struct mi_work;
|
|
|
+ struct work_struct tg_work;
|
|
|
+ struct timer_list listen_timer;
|
|
|
struct pn533_frame *wq_in_frame;
|
|
|
int wq_in_error;
|
|
|
+ int cancel_listen;
|
|
|
|
|
|
pn533_cmd_complete_t cmd_complete;
|
|
|
void *cmd_complete_arg;
|
|
|
- struct semaphore cmd_lock;
|
|
|
+ struct mutex cmd_lock;
|
|
|
u8 cmd;
|
|
|
|
|
|
struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
|
|
|
u8 poll_mod_count;
|
|
|
u8 poll_mod_curr;
|
|
|
u32 poll_protocols;
|
|
|
+ u32 listen_protocols;
|
|
|
+
|
|
|
+ u8 *gb;
|
|
|
+ size_t gb_len;
|
|
|
|
|
|
u8 tgt_available_prots;
|
|
|
u8 tgt_active_prot;
|
|
|
+ u8 tgt_mode;
|
|
|
};
|
|
|
|
|
|
struct pn533_frame {
|
|
@@ -405,7 +463,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work)
|
|
|
PN533_FRAME_CMD_PARAMS_LEN(in_frame));
|
|
|
|
|
|
if (rc != -EINPROGRESS)
|
|
|
- up(&dev->cmd_lock);
|
|
|
+ mutex_unlock(&dev->cmd_lock);
|
|
|
}
|
|
|
|
|
|
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__);
|
|
|
|
|
|
- if (down_trylock(&dev->cmd_lock))
|
|
|
+ if (!mutex_trylock(&dev->cmd_lock))
|
|
|
return -EBUSY;
|
|
|
|
|
|
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;
|
|
|
error:
|
|
|
- up(&dev->cmd_lock);
|
|
|
+ mutex_unlock(&dev->cmd_lock);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -963,6 +1021,11 @@ static int pn533_target_found(struct pn533 *dev,
|
|
|
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)
|
|
|
{
|
|
|
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++;
|
|
|
}
|
|
|
|
|
|
-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);
|
|
|
|
|
|
- if (protocols & NFC_PROTO_MIFARE_MASK
|
|
|
- || protocols & NFC_PROTO_ISO14443_MASK
|
|
|
- || protocols & NFC_PROTO_NFC_DEP_MASK)
|
|
|
+ if (im_protocols & NFC_PROTO_MIFARE_MASK
|
|
|
+ || im_protocols & NFC_PROTO_ISO14443_MASK
|
|
|
+ || im_protocols & NFC_PROTO_NFC_DEP_MASK)
|
|
|
pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A);
|
|
|
|
|
|
- if (protocols & NFC_PROTO_FELICA_MASK
|
|
|
- || protocols & NFC_PROTO_NFC_DEP_MASK) {
|
|
|
+ if (im_protocols & NFC_PROTO_FELICA_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_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);
|
|
|
|
|
|
- if (protocols & NFC_PROTO_ISO14443_MASK)
|
|
|
+ if (im_protocols & NFC_PROTO_ISO14443_MASK)
|
|
|
pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
|
|
|
+
|
|
|
+ if (tm_protocols)
|
|
|
+ pn533_poll_add_mod(dev, PN533_LISTEN_MOD);
|
|
|
+}
|
|
|
+
|
|
|
+static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
|
|
|
+ u8 *params, int params_len)
|
|
|
+{
|
|
|
+ struct pn533_poll_response *resp;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
|
|
|
+
|
|
|
+ resp = (struct pn533_poll_response *) params;
|
|
|
+ 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 void pn533_start_poll_frame(struct pn533_frame *frame,
|
|
|
- struct pn533_poll_modulations *mod)
|
|
|
+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);
|
|
|
|
|
|
- pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET);
|
|
|
+ /* MIFARE params */
|
|
|
+ memcpy(cmd->mifare, mifare_params, 6);
|
|
|
|
|
|
- memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
|
|
|
- frame->datalen += mod->len;
|
|
|
+ /* 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);
|
|
|
+
|
|
|
+ kfree(cmd);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
|
|
|
- u8 *params, int params_len)
|
|
|
+#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)
|
|
|
{
|
|
|
- struct pn533_poll_response *resp;
|
|
|
- struct pn533_poll_modulations *next_mod;
|
|
|
- int rc;
|
|
|
+ struct sk_buff *skb_resp = arg;
|
|
|
+ struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data;
|
|
|
|
|
|
nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
|
|
|
|
|
|
- if (params_len == -ENOENT) {
|
|
|
- nfc_dev_dbg(&dev->interface->dev, "Polling operation has been"
|
|
|
- " stopped");
|
|
|
- goto stop_poll;
|
|
|
+ if (params_len < 0) {
|
|
|
+ nfc_dev_err(&dev->interface->dev,
|
|
|
+ "Error %d when starting as a target",
|
|
|
+ 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) {
|
|
|
- nfc_dev_err(&dev->interface->dev, "Error %d when running poll",
|
|
|
- params_len);
|
|
|
- goto stop_poll;
|
|
|
+ nfc_dev_err(&dev->interface->dev,
|
|
|
+ "Error %d when starting as a target",
|
|
|
+ params_len);
|
|
|
+
|
|
|
+ return params_len;
|
|
|
}
|
|
|
|
|
|
- resp = (struct pn533_poll_response *) params;
|
|
|
- if (resp->nbtg) {
|
|
|
- rc = pn533_target_found(dev, resp, params_len);
|
|
|
+ if (params_len < ATR_REQ_GB_OFFSET + 1)
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
- /* We must stop the poll after a valid target found */
|
|
|
- if (rc == 0)
|
|
|
- goto stop_poll;
|
|
|
+ resp = (struct pn533_cmd_init_target_response *) params;
|
|
|
+
|
|
|
+ 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;
|
|
|
|
|
|
- if (rc != -EAGAIN)
|
|
|
- nfc_dev_err(&dev->interface->dev, "The target found is"
|
|
|
- " not valid - continuing to poll");
|
|
|
+ /* Again, only DEP */
|
|
|
+ if ((resp->mode & PN533_INIT_TARGET_RESP_DEP) == 0)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ gb = resp->cmd + ATR_REQ_GB_OFFSET;
|
|
|
+ gb_len = params_len - (ATR_REQ_GB_OFFSET + 1);
|
|
|
+
|
|
|
+ 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)",
|
|
|
- dev->poll_mod_curr);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+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);
|
|
|
+
|
|
|
+ queue_work(dev->wq, &dev->poll_work);
|
|
|
+}
|
|
|
|
|
|
- pn533_start_poll_frame(dev->out_frame, next_mod);
|
|
|
+static int pn533_poll_complete(struct pn533 *dev, void *arg,
|
|
|
+ u8 *params, int params_len)
|
|
|
+{
|
|
|
+ struct pn533_poll_modulations *cur_mod;
|
|
|
+ int rc;
|
|
|
|
|
|
- /* Don't need to down the semaphore again */
|
|
|
- rc = __pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
|
|
|
- dev->in_maxlen, pn533_start_poll_complete,
|
|
|
- NULL, GFP_ATOMIC);
|
|
|
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
|
|
|
+
|
|
|
+ if (params_len == -ENOENT) {
|
|
|
+ if (dev->poll_mod_count != 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ nfc_dev_err(&dev->interface->dev,
|
|
|
+ "Polling operation has been stopped");
|
|
|
|
|
|
- if (rc == -EPERM) {
|
|
|
- nfc_dev_dbg(&dev->interface->dev, "Cannot poll next modulation"
|
|
|
- " because poll has been stopped");
|
|
|
goto stop_poll;
|
|
|
}
|
|
|
|
|
|
- if (rc) {
|
|
|
- nfc_dev_err(&dev->interface->dev, "Error %d when trying to poll"
|
|
|
- " next modulation", rc);
|
|
|
+ if (params_len < 0) {
|
|
|
+ nfc_dev_err(&dev->interface->dev,
|
|
|
+ "Error %d when running poll", params_len);
|
|
|
+
|
|
|
goto stop_poll;
|
|
|
}
|
|
|
|
|
|
- /* Inform caller function to do not up the semaphore */
|
|
|
- return -EINPROGRESS;
|
|
|
+ cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
|
|
|
+
|
|
|
+ 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:
|
|
|
pn533_poll_reset_mod_list(dev);
|
|
@@ -1078,61 +1322,104 @@ stop_poll:
|
|
|
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);
|
|
|
- struct pn533_poll_modulations *start_mod;
|
|
|
- int rc;
|
|
|
+ nfc_dev_dbg(&dev->interface->dev, "mod len %d\n", mod->len);
|
|
|
|
|
|
- nfc_dev_dbg(&dev->interface->dev, "%s - protocols=0x%x", __func__,
|
|
|
- protocols);
|
|
|
+ if (mod->len == 0) {
|
|
|
+ /* 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) {
|
|
|
- nfc_dev_err(&dev->interface->dev, "Polling operation already"
|
|
|
- " active");
|
|
|
- return -EBUSY;
|
|
|
- }
|
|
|
+ memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
|
|
|
+ frame->datalen += mod->len;
|
|
|
|
|
|
- if (dev->tgt_active_prot) {
|
|
|
- nfc_dev_err(&dev->interface->dev, "Cannot poll with a target"
|
|
|
- " already activated");
|
|
|
- return -EBUSY;
|
|
|
+ pn533_tx_frame_finish(frame);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- pn533_poll_create_mod_list(dev, protocols);
|
|
|
+static int pn533_send_poll_frame(struct pn533 *dev)
|
|
|
+{
|
|
|
+ struct pn533_poll_modulations *cur_mod;
|
|
|
+ int rc;
|
|
|
|
|
|
- if (!dev->poll_mod_count) {
|
|
|
- nfc_dev_err(&dev->interface->dev, "No valid protocols"
|
|
|
- " specified");
|
|
|
- rc = -EINVAL;
|
|
|
- goto error;
|
|
|
+ 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;
|
|
|
+}
|
|
|
+
|
|
|
+static void pn533_wq_poll(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct pn533 *dev = container_of(work, struct pn533, poll_work);
|
|
|
+ struct pn533_poll_modulations *cur_mod;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
|
|
|
+
|
|
|
+ nfc_dev_dbg(&dev->interface->dev,
|
|
|
+ "%s cancel_listen %d modulation len %d",
|
|
|
+ __func__, dev->cancel_listen, cur_mod->len);
|
|
|
+
|
|
|
+ if (dev->cancel_listen == 1) {
|
|
|
+ dev->cancel_listen = 0;
|
|
|
+ usb_kill_urb(dev->in_urb);
|
|
|
}
|
|
|
|
|
|
- nfc_dev_dbg(&dev->interface->dev, "It will poll %d modulations types",
|
|
|
- dev->poll_mod_count);
|
|
|
+ rc = pn533_send_poll_frame(dev);
|
|
|
+ if (rc)
|
|
|
+ return;
|
|
|
|
|
|
- dev->poll_mod_curr = 0;
|
|
|
- start_mod = dev->poll_mod_active[dev->poll_mod_curr];
|
|
|
+ if (cur_mod->len == 0 && dev->poll_mod_count > 1)
|
|
|
+ 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,
|
|
|
- dev->in_maxlen, pn533_start_poll_complete,
|
|
|
- NULL, GFP_KERNEL);
|
|
|
+static int pn533_start_poll(struct nfc_dev *nfc_dev,
|
|
|
+ u32 im_protocols, u32 tm_protocols)
|
|
|
+{
|
|
|
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
|
|
|
- if (rc) {
|
|
|
- nfc_dev_err(&dev->interface->dev, "Error %d when trying to"
|
|
|
- " start poll", rc);
|
|
|
- goto error;
|
|
|
+ nfc_dev_dbg(&dev->interface->dev,
|
|
|
+ "%s: im protocols 0x%x tm protocols 0x%x",
|
|
|
+ __func__, im_protocols, tm_protocols);
|
|
|
+
|
|
|
+ if (dev->tgt_active_prot) {
|
|
|
+ nfc_dev_err(&dev->interface->dev,
|
|
|
+ "Cannot poll with a target already activated");
|
|
|
+ return -EBUSY;
|
|
|
}
|
|
|
|
|
|
- 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:
|
|
|
- pn533_poll_reset_mod_list(dev);
|
|
|
- return rc;
|
|
|
+ dev->poll_mod_curr = 0;
|
|
|
+ pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
|
|
|
+ dev->poll_protocols = im_protocols;
|
|
|
+ dev->listen_protocols = tm_protocols;
|
|
|
+
|
|
|
+ return pn533_send_poll_frame(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__);
|
|
|
|
|
|
+ del_timer(&dev->listen_timer);
|
|
|
+
|
|
|
if (!dev->poll_mod_count) {
|
|
|
nfc_dev_dbg(&dev->interface->dev, "Polling operation was not"
|
|
|
" 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 */
|
|
|
usb_kill_urb(dev->in_urb);
|
|
|
+
|
|
|
+ pn533_poll_reset_mod_list(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;
|
|
|
}
|
|
|
|
|
|
+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,
|
|
|
u8 comm_mode, u8* gb, size_t gb_len)
|
|
|
{
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
struct pn533_cmd_jump_dep *cmd;
|
|
|
- u8 cmd_len;
|
|
|
- int rc;
|
|
|
+ u8 cmd_len, *data_ptr;
|
|
|
+ u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
|
|
|
+ int rc, baud;
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
+ 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;
|
|
|
+ if (comm_mode == NFC_COMM_PASSIVE)
|
|
|
+ cmd_len += PASSIVE_DATA_LEN;
|
|
|
+
|
|
|
cmd = kzalloc(cmd_len, GFP_KERNEL);
|
|
|
if (cmd == NULL)
|
|
|
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);
|
|
|
|
|
|
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) {
|
|
|
- cmd->next = 4; /* We have some Gi */
|
|
|
- memcpy(cmd->gt, gb, gb_len);
|
|
|
+ cmd->next |= 4; /* We have some Gi */
|
|
|
+ memcpy(data_ptr, gb, gb_len);
|
|
|
} else {
|
|
|
cmd->next = 0;
|
|
|
}
|
|
@@ -1407,15 +1732,25 @@ out:
|
|
|
|
|
|
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);
|
|
|
+
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ dev->tgt_active_prot = 0;
|
|
|
+ dev->tgt_mode = 0;
|
|
|
+
|
|
|
+ skb_queue_purge(&dev->resp_q);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
|
|
|
-#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
|
|
|
-
|
|
|
-static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
|
|
|
+static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb,
|
|
|
+ bool target)
|
|
|
{
|
|
|
int payload_len = skb->len;
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
- skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
|
|
|
- out_frame = (struct pn533_frame *) skb->data;
|
|
|
+ if (target == true) {
|
|
|
+ skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
|
|
|
+ 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;
|
|
|
+ memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, 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);
|
|
|
+ }
|
|
|
|
|
|
- tg = 1;
|
|
|
- memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
|
|
|
- out_frame->datalen += sizeof(u8);
|
|
|
|
|
|
/* The data is already in the out_frame, just update the datalen */
|
|
|
out_frame->datalen += payload_len;
|
|
@@ -1550,9 +1891,9 @@ error:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int pn533_data_exchange(struct nfc_dev *nfc_dev,
|
|
|
- struct nfc_target *target, struct sk_buff *skb,
|
|
|
- data_exchange_cb_t cb, void *cb_context)
|
|
|
+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)
|
|
|
{
|
|
|
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
|
|
|
struct pn533_frame *out_frame, *in_frame;
|
|
@@ -1570,7 +1911,7 @@ static int pn533_data_exchange(struct nfc_dev *nfc_dev,
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
|
- rc = pn533_data_exchange_tx_frame(dev, skb);
|
|
|
+ rc = pn533_build_tx_frame(dev, skb, true);
|
|
|
if (rc)
|
|
|
goto error;
|
|
|
|
|
@@ -1618,6 +1959,63 @@ error:
|
|
|
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)
|
|
|
{
|
|
|
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);
|
|
|
|
|
|
- rc = pn533_data_exchange_tx_frame(dev, skb_cmd);
|
|
|
+ rc = pn533_build_tx_frame(dev, skb_cmd, true);
|
|
|
if (rc)
|
|
|
goto error_frame;
|
|
|
|
|
@@ -1677,7 +2075,7 @@ error_cmd:
|
|
|
|
|
|
kfree(arg);
|
|
|
|
|
|
- up(&dev->cmd_lock);
|
|
|
+ mutex_unlock(&dev->cmd_lock);
|
|
|
}
|
|
|
|
|
|
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,
|
|
|
.activate_target = pn533_activate_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,
|
|
@@ -1723,6 +2122,7 @@ static int pn533_probe(struct usb_interface *interface,
|
|
|
struct usb_host_interface *iface_desc;
|
|
|
struct usb_endpoint_descriptor *endpoint;
|
|
|
struct pn533_config_max_retries max_retries;
|
|
|
+ struct pn533_config_timing timing;
|
|
|
int in_endpoint = 0;
|
|
|
int out_endpoint = 0;
|
|
|
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->interface = interface;
|
|
|
- sema_init(&dev->cmd_lock, 1);
|
|
|
+ mutex_init(&dev->cmd_lock);
|
|
|
|
|
|
iface_desc = interface->cur_altsetting;
|
|
|
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->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",
|
|
|
WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
|
|
|
1);
|
|
|
if (dev->wq == NULL)
|
|
|
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);
|
|
|
|
|
|
usb_set_intfdata(interface, dev);
|
|
@@ -1830,13 +2236,29 @@ static int pn533_probe(struct usb_interface *interface,
|
|
|
if (rc) {
|
|
|
nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES"
|
|
|
" 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;
|
|
|
|
|
|
+unregister_nfc_dev:
|
|
|
+ nfc_unregister_device(dev->nfc_dev);
|
|
|
+
|
|
|
free_nfc_dev:
|
|
|
nfc_free_device(dev->nfc_dev);
|
|
|
+
|
|
|
destroy_wq:
|
|
|
destroy_workqueue(dev->wq);
|
|
|
error:
|
|
@@ -1865,6 +2287,8 @@ static void pn533_disconnect(struct usb_interface *interface)
|
|
|
|
|
|
skb_queue_purge(&dev->resp_q);
|
|
|
|
|
|
+ del_timer(&dev->listen_timer);
|
|
|
+
|
|
|
kfree(dev->in_frame);
|
|
|
usb_free_urb(dev->in_urb);
|
|
|
kfree(dev->out_frame);
|