#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_RESPONSE(cmd) (cmd + 1)
/* PN533 Return codes */
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;
struct pn533_frame *in_frame;
int rc;
- if (dev == NULL)
- return;
-
in_frame = dev->wq_in_frame;
if (dev->wq_in_error)
return 0;
}
-static int pn533_start_poll(struct nfc_dev *nfc_dev, u32 protocols)
+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;
+
+ 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;
+ get_random_bytes(cmd->nfcid3, 10);
+ 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);
+
+ return 0;
+}
+
+#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;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ 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 < ATR_REQ_GB_OFFSET + 1)
+ return -EINVAL;
+
+ 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;
+
+ /* 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);
+
+ return nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
+ comm_mode, gb, gb_len);
+}
+
+static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
- struct pn533_poll_modulations *start_mod;
+ u8 *gb;
+ size_t gb_len;
int rc;
- nfc_dev_dbg(&dev->interface->dev, "%s - protocols=0x%x", __func__,
- protocols);
+ pn533_poll_reset_mod_list(dev);
+
+ gb = nfc_get_local_general_bytes(nfc_dev, &gb_len);
+ if (gb == NULL)
+ return -ENOMEM;
+
+ rc = pn533_init_target_frame(dev->out_frame, gb, gb_len);
+ if (rc < 0)
+ return rc;
+
+ rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
+ dev->in_maxlen,
+ pn533_init_target_complete,
+ NULL, GFP_KERNEL);
+
+ if (rc)
+ nfc_dev_err(&dev->interface->dev,
+ "Error %d when trying to initiate as a target", rc);
+
+ dev->poll_mod_count++;
+
+ return rc;
+}
+
+static int pn533_start_im_poll(struct nfc_dev *nfc_dev, u32 protocols)
+{
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+ struct pn533_poll_modulations *start_mod;
+ int rc;
if (dev->poll_mod_count) {
nfc_dev_err(&dev->interface->dev, "Polling operation already"
return -EBUSY;
}
- if (dev->tgt_active_prot) {
- nfc_dev_err(&dev->interface->dev, "Cannot poll with a target"
- " already activated");
- return -EBUSY;
- }
-
pn533_poll_create_mod_list(dev, protocols);
if (!dev->poll_mod_count) {
return rc;
}
+static int pn533_start_poll(struct nfc_dev *nfc_dev,
+ u32 im_protocols, u32 tm_protocols)
+{
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+
+ 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;
+ }
+
+ if (im_protocols)
+ return pn533_start_im_poll(nfc_dev, im_protocols);
+
+ if (tm_protocols)
+ return pn533_init_target(nfc_dev, tm_protocols);
+
+ return -EINVAL;
+}
+
static void pn533_stop_poll(struct nfc_dev *nfc_dev)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
return rc;
}
-static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx,
- u32 protocol)
+static int pn533_activate_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target, u32 protocol)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
int rc;
return 0;
}
-static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx)
+static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
u8 tg;
return 0;
}
-static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx,
+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);
return 0;
}
-static int pn533_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx,
- 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;
.stop_poll = pn533_stop_poll,
.activate_target = pn533_activate_target,
.deactivate_target = pn533_deactivate_target,
- .data_exchange = pn533_data_exchange,
+ .im_transceive = pn533_transceive,
};
static int pn533_probe(struct usb_interface *interface,