forked from Minki/linux
NFC: Implement the pn533 target mode Tx op
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
103b34cf5f
commit
dadb06f270
@ -76,6 +76,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
|
|||||||
|
|
||||||
#define PN533_CMD_TG_INIT_AS_TARGET 0x8c
|
#define PN533_CMD_TG_INIT_AS_TARGET 0x8c
|
||||||
#define PN533_CMD_TG_GET_DATA 0x86
|
#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)
|
||||||
|
|
||||||
@ -1630,7 +1631,8 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
int payload_len = skb->len;
|
||||||
struct pn533_frame *out_frame;
|
struct pn533_frame *out_frame;
|
||||||
@ -1647,14 +1649,20 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
|
|||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
|
if (target == true) {
|
||||||
out_frame = (struct pn533_frame *) skb->data;
|
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 */
|
/* The data is already in the out_frame, just update the datalen */
|
||||||
out_frame->datalen += payload_len;
|
out_frame->datalen += payload_len;
|
||||||
@ -1785,7 +1793,7 @@ static int pn533_transceive(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;
|
||||||
|
|
||||||
@ -1833,6 +1841,61 @@ error:
|
|||||||
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);
|
||||||
|
|
||||||
|
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);
|
||||||
@ -1853,7 +1916,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;
|
||||||
|
|
||||||
@ -1928,6 +1991,7 @@ struct nfc_ops pn533_nfc_ops = {
|
|||||||
.activate_target = pn533_activate_target,
|
.activate_target = pn533_activate_target,
|
||||||
.deactivate_target = pn533_deactivate_target,
|
.deactivate_target = pn533_deactivate_target,
|
||||||
.im_transceive = pn533_transceive,
|
.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,
|
||||||
|
Loading…
Reference in New Issue
Block a user