From 2c2d45bdcb7063ef58dc2c27d72026c394a8f584 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Tue, 27 Nov 2012 15:44:24 +0100 Subject: NFC: Add support for SO_TIMESTAMP LLCP socket option Set timestamp in sent and received sk_buffs. timestamp is then put in msghdr structure in llcp_sock_recvmsg(). Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index df24be4..c6bc3bd 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c @@ -304,6 +304,8 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); + __net_timestamp(skb); + nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); return nfc_data_exchange(dev, local->target_idx, skb, diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index ec43914..6c59714 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -668,6 +668,8 @@ static void nfc_llcp_tx_work(struct work_struct *work) if (ptype == LLCP_PDU_I) copy_skb = skb_copy(skb, GFP_ATOMIC); + __net_timestamp(skb); + nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); @@ -1245,6 +1247,8 @@ static void nfc_llcp_rx_work(struct work_struct *work) print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, true); + __net_timestamp(skb); + nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX); switch (ptype) { diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index fea22eb..ba19007 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -678,6 +678,8 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, return -EFAULT; } + sock_recv_timestamp(msg, sk, skb); + if (sk->sk_type == SOCK_DGRAM && msg->msg_name) { struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb); struct sockaddr_nfc_llcp sockaddr; -- cgit v0.10.2 From 8d25ca799783788742bc7d9647eec44b6754766e Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 26 Nov 2012 14:18:30 +0100 Subject: NFC: pn533: Remove in/out_maxlen as it is not used in_maxlen and out_maxlen was replaced with PN533_NORMAL_FRAME_MAX_LEN Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index ada681b..cf94113 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -349,11 +349,9 @@ struct pn533 { struct nfc_dev *nfc_dev; struct urb *out_urb; - int out_maxlen; struct pn533_frame *out_frame; struct urb *in_urb; - int in_maxlen; struct pn533_frame *in_frame; struct sk_buff_head resp_q; @@ -1454,8 +1452,9 @@ static int pn533_send_poll_frame(struct pn533 *dev) 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); + PN533_NORMAL_FRAME_MAX_LEN, + pn533_poll_complete, + NULL, GFP_KERNEL); if (rc) nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); @@ -1567,7 +1566,7 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) pn533_tx_frame_finish(dev->out_frame); rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - dev->in_maxlen); + PN533_NORMAL_FRAME_MAX_LEN); if (rc) return rc; @@ -1661,7 +1660,7 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, pn533_tx_frame_finish(dev->out_frame); rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - dev->in_maxlen); + PN533_NORMAL_FRAME_MAX_LEN); if (rc) { nfc_dev_err(&dev->interface->dev, "Error when sending release" " command to the controller"); @@ -1822,8 +1821,9 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, pn533_tx_frame_finish(dev->out_frame); rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, - dev->in_maxlen, pn533_in_dep_link_up_complete, - cmd, GFP_KERNEL); + PN533_NORMAL_FRAME_MAX_LEN, + pn533_in_dep_link_up_complete, cmd, + GFP_KERNEL); if (rc < 0) kfree(cmd); @@ -2121,8 +2121,9 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) 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, - skb, GFP_KERNEL); + PN533_NORMAL_FRAME_MAX_LEN, + pn533_tm_send_complete, skb, + GFP_KERNEL); if (rc) { nfc_dev_err(&dev->interface->dev, "Error %d when trying to send data", rc); @@ -2217,7 +2218,7 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, pn533_tx_frame_finish(dev->out_frame); rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - dev->in_maxlen); + PN533_NORMAL_FRAME_MAX_LEN); return rc; } @@ -2238,7 +2239,7 @@ static int pn533_fw_reset(struct pn533 *dev) pn533_tx_frame_finish(dev->out_frame); rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - dev->in_maxlen); + PN533_NORMAL_FRAME_MAX_LEN); return rc; } @@ -2359,16 +2360,11 @@ static int pn533_probe(struct usb_interface *interface, for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) { - dev->in_maxlen = le16_to_cpu(endpoint->wMaxPacketSize); + if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) in_endpoint = endpoint->bEndpointAddress; - } - if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) { - dev->out_maxlen = - le16_to_cpu(endpoint->wMaxPacketSize); + if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) out_endpoint = endpoint->bEndpointAddress; - } } if (!in_endpoint || !out_endpoint) { @@ -2418,7 +2414,7 @@ static int pn533_probe(struct usb_interface *interface, pn533_tx_frame_finish(dev->out_frame); rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - dev->in_maxlen); + PN533_NORMAL_FRAME_MAX_LEN); if (rc) goto destroy_wq; -- cgit v0.10.2 From a449ae1cbdcb5ab45c894362602b239e1d8d96c3 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 26 Nov 2012 14:18:31 +0100 Subject: NFC: pn533: Remove unused definitions Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index cf94113..ed8ecb3 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -41,11 +41,6 @@ #define SONY_VENDOR_ID 0x054c #define PASORI_PRODUCT_ID 0x02e1 -#define PN533_QUIRKS_TYPE_A BIT(0) -#define PN533_QUIRKS_TYPE_F BIT(1) -#define PN533_QUIRKS_DEP BIT(2) -#define PN533_QUIRKS_RAW_EXCHANGE BIT(3) - #define PN533_DEVICE_STD 0x1 #define PN533_DEVICE_PASORI 0x2 @@ -128,9 +123,6 @@ 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, -- cgit v0.10.2 From b1bb290ac2308616b24c5986665d7199ff7b9df3 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 26 Nov 2012 14:18:32 +0100 Subject: NFC: pn533: Add frame header length define PN533_CMD_DATAEXCH_HEAD_LEN includes a frame header length which is not seen at a glance. It can be missleading, so split it and define the frame header length explicitly. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index ed8ecb3..7040106 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -82,10 +82,12 @@ MODULE_DEVICE_TABLE(usb, pn533_table); #define PN533_NORMAL_FRAME_MAX_LEN 262 /* 6 (PREAMBLE, SOF, LEN, LCS, TFI) 254 (DATA) 2 (DCS, postamble) */ +#define PN533_FRAME_HEADER_LEN (sizeof(struct pn533_frame) \ + + 2) /* data[0] TFI, data[1] CC */ +#define PN533_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/ -#define PN533_FRAME_TAIL_SIZE 2 #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ - PN533_FRAME_TAIL_SIZE) + PN533_FRAME_TAIL_LEN) #define PN533_FRAME_ACK_SIZE (sizeof(struct pn533_frame) + 1) #define PN533_FRAME_CHECKSUM(f) (f->data[f->datalen]) #define PN533_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1]) @@ -1233,7 +1235,7 @@ static int pn533_init_target_frame(struct pn533_frame *frame, return 0; } -#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) +#define PN533_CMD_DATAEXCH_HEAD_LEN 1 #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) @@ -1261,8 +1263,9 @@ static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, } 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); + skb_pull(skb_resp, + PN533_FRAME_HEADER_LEN + PN533_CMD_DATAEXCH_HEAD_LEN); + skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_LEN); return nfc_tm_data_received(dev->nfc_dev, skb_resp); } @@ -1276,9 +1279,10 @@ static void pn533_wq_tg_get_data(struct work_struct *work) 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_len = PN533_FRAME_HEADER_LEN + + PN533_CMD_DATAEXCH_HEAD_LEN + + PN533_CMD_DATAEXCH_DATA_MAXLEN + + PN533_FRAME_TAIL_LEN; skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); if (!skb_resp) @@ -1859,11 +1863,12 @@ static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, return -ENOSYS; } + skb_push(skb, PN533_FRAME_HEADER_LEN); + if (target == true) { switch (dev->device_type) { case PN533_DEVICE_PASORI: if (dev->tgt_active_prot == NFC_PROTO_FELICA) { - skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); out_frame = (struct pn533_frame *) skb->data; pn533_tx_frame_init(out_frame, PN533_CMD_IN_COMM_THRU); @@ -1895,7 +1900,7 @@ static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, out_frame->datalen += payload_len; pn533_tx_frame_finish(out_frame); - skb_put(skb, PN533_FRAME_TAIL_SIZE); + skb_put(skb, PN533_FRAME_TAIL_LEN); return 0; } @@ -1975,8 +1980,9 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, } skb_put(skb_resp, PN533_FRAME_SIZE(in_frame)); + skb_pull(skb_resp, PN533_FRAME_HEADER_LEN); skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN); - skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE); + skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_LEN); skb_queue_tail(&dev->resp_q, skb_resp); if (status & PN533_CMD_MI_MASK) { @@ -2024,9 +2030,10 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, if (rc) goto error; - skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN + - PN533_CMD_DATAEXCH_DATA_MAXLEN + - PN533_FRAME_TAIL_SIZE; + skb_resp_len = PN533_FRAME_HEADER_LEN + + PN533_CMD_DATAEXCH_HEAD_LEN + + PN533_CMD_DATAEXCH_DATA_MAXLEN + + PN533_FRAME_TAIL_LEN; skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); if (!skb_resp) { @@ -2143,20 +2150,25 @@ static void pn533_wq_mi_recv(struct work_struct *work) nfc_dev_dbg(&dev->interface->dev, "%s", __func__); /* This is a zero payload size skb */ - skb_cmd = alloc_skb(PN533_CMD_DATAEXCH_HEAD_LEN + PN533_FRAME_TAIL_SIZE, + skb_cmd = alloc_skb(PN533_FRAME_HEADER_LEN + + PN533_CMD_DATAEXCH_HEAD_LEN + + PN533_FRAME_TAIL_LEN, GFP_KERNEL); if (skb_cmd == NULL) goto error_cmd; - skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); + skb_reserve(skb_cmd, + PN533_FRAME_HEADER_LEN + PN533_CMD_DATAEXCH_HEAD_LEN); rc = pn533_build_tx_frame(dev, skb_cmd, true); if (rc) goto error_frame; - skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN + - PN533_CMD_DATAEXCH_DATA_MAXLEN + - PN533_FRAME_TAIL_SIZE; + skb_resp_len = PN533_FRAME_HEADER_LEN + + PN533_CMD_DATAEXCH_HEAD_LEN + + PN533_CMD_DATAEXCH_DATA_MAXLEN + + PN533_FRAME_TAIL_LEN; + skb_resp = alloc_skb(skb_resp_len, GFP_KERNEL); if (!skb_resp) { rc = -ENOMEM; @@ -2433,8 +2445,9 @@ static int pn533_probe(struct usb_interface *interface, } dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, + PN533_FRAME_HEADER_LEN + PN533_CMD_DATAEXCH_HEAD_LEN, - PN533_FRAME_TAIL_SIZE); + PN533_FRAME_TAIL_LEN); if (!dev->nfc_dev) goto destroy_wq; -- cgit v0.10.2 From d94ea4f54516b32affeda7ef097b93bca6e6fd32 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 26 Nov 2012 14:18:33 +0100 Subject: NFC: pn533: Remove pointless flags param __pn533_send_cmd_frame_async() is called when lock is held so GFP_KERNEL flag will be always used. Thus, having extra param does not optimise the code. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 7040106..5f3459d 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -392,7 +392,6 @@ struct pn533_cmd { int in_frame_len; pn533_cmd_complete_t cmd_complete; void *arg; - gfp_t flags; }; struct pn533_frame { @@ -646,7 +645,7 @@ static int __pn533_send_cmd_frame_async(struct pn533 *dev, struct pn533_frame *in_frame, int in_frame_len, pn533_cmd_complete_t cmd_complete, - void *arg, gfp_t flags) + void *arg) { int rc; @@ -664,11 +663,11 @@ static int __pn533_send_cmd_frame_async(struct pn533 *dev, dev->in_urb->transfer_buffer = in_frame; dev->in_urb->transfer_buffer_length = in_frame_len; - rc = usb_submit_urb(dev->out_urb, flags); + rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); if (rc) return rc; - rc = pn533_submit_urb_for_ack(dev, flags); + rc = pn533_submit_urb_for_ack(dev, GFP_KERNEL); if (rc) goto error; @@ -700,7 +699,7 @@ static void pn533_wq_cmd(struct work_struct *work) __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, cmd->in_frame_len, cmd->cmd_complete, - cmd->arg, cmd->flags); + cmd->arg); kfree(cmd); } @@ -710,7 +709,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, struct pn533_frame *in_frame, int in_frame_len, pn533_cmd_complete_t cmd_complete, - void *arg, gfp_t flags) + void *arg) { struct pn533_cmd *cmd; int rc = 0; @@ -722,7 +721,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, if (!dev->cmd_pending) { rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, in_frame_len, cmd_complete, - arg, flags); + arg); if (!rc) dev->cmd_pending = 1; @@ -731,7 +730,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, nfc_dev_dbg(&dev->interface->dev, "%s Queueing command", __func__); - cmd = kzalloc(sizeof(struct pn533_cmd), flags); + cmd = kzalloc(sizeof(struct pn533_cmd), GFP_KERNEL); if (!cmd) { rc = -ENOMEM; goto unlock; @@ -743,7 +742,6 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, cmd->in_frame_len = in_frame_len; cmd->cmd_complete = cmd_complete; cmd->arg = arg; - cmd->flags = flags; list_add_tail(&cmd->queue, &dev->cmd_queue); @@ -788,7 +786,7 @@ static int pn533_send_cmd_frame_sync(struct pn533 *dev, init_completion(&arg.done); rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, in_frame_len, - pn533_sync_cmd_complete, &arg, GFP_KERNEL); + pn533_sync_cmd_complete, &arg); if (rc) return rc; @@ -1296,7 +1294,7 @@ static void pn533_wq_tg_get_data(struct work_struct *work) pn533_send_cmd_frame_async(dev, dev->out_frame, in_frame, skb_resp_len, pn533_tm_get_data_complete, - skb_resp, GFP_KERNEL); + skb_resp); return; } @@ -1450,7 +1448,7 @@ static int pn533_send_poll_frame(struct pn533 *dev) rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, PN533_NORMAL_FRAME_MAX_LEN, pn533_poll_complete, - NULL, GFP_KERNEL); + NULL); if (rc) nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); @@ -1818,8 +1816,7 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, PN533_NORMAL_FRAME_MAX_LEN, - pn533_in_dep_link_up_complete, cmd, - GFP_KERNEL); + pn533_in_dep_link_up_complete, cmd); if (rc < 0) kfree(cmd); @@ -2056,8 +2053,7 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, arg->cb_context = cb_context; rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, skb_resp_len, - pn533_data_exchange_complete, arg, - GFP_KERNEL); + pn533_data_exchange_complete, arg); if (rc) { nfc_dev_err(&dev->interface->dev, "Error %d when trying to" " perform data_exchange", rc); @@ -2121,8 +2117,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, PN533_NORMAL_FRAME_MAX_LEN, - pn533_tm_send_complete, skb, - GFP_KERNEL); + pn533_tm_send_complete, skb); if (rc) { nfc_dev_err(&dev->interface->dev, "Error %d when trying to send data", rc); @@ -2184,7 +2179,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, skb_resp_len, pn533_data_exchange_complete, - dev->cmd_complete_arg, GFP_KERNEL); + dev->cmd_complete_arg); if (!rc) return; -- cgit v0.10.2 From aada17ac70e33b127c8f8dd425fc735cc0d30e25 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 26 Nov 2012 14:18:34 +0100 Subject: NFC: pn533: Add a new pn533_send_cmd_async iface This is intendend to replace pn533_send_cmd_frame_async() which requires from the caller to create a complete frame. The new function constructs a frame and sends it out which hides the frame logic and avoid code duplication. The caller has to allocate skb and put its payload there, and finally provide the skb together with a complete cb to pn533_send_cmd_async(). Response skb is allocated by the core part and pass to the caller cb. Next, the caller has to free it when is not needed anymore or pass it up to the stack. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 5f3459d..89f7474 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -117,6 +117,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table); #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_UNDEF 0xff #define PN533_CMD_RESPONSE(cmd) (cmd + 1) @@ -130,6 +131,9 @@ struct pn533; typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, u8 *params, int params_len); +typedef int (*pn533_send_async_complete_t) (struct pn533 *dev, void *arg, + struct sk_buff *resp); + /* structs for pn533 commands */ /* PN533_CMD_GET_FIRMWARE_VERSION */ @@ -390,6 +394,9 @@ struct pn533_cmd { struct pn533_frame *out_frame; struct pn533_frame *in_frame; int in_frame_len; + u8 cmd_code; + struct sk_buff *req; + struct sk_buff *resp; pn533_cmd_complete_t cmd_complete; void *arg; }; @@ -678,6 +685,151 @@ error: return rc; } +static void pn533_build_cmd_frame(u8 cmd_code, struct sk_buff *skb) +{ + struct pn533_frame *frame; + /* payload is already there, just update datalen */ + int payload_len = skb->len; + + skb_push(skb, PN533_FRAME_HEADER_LEN); + skb_put(skb, PN533_FRAME_TAIL_LEN); + + frame = (struct pn533_frame *)skb->data; + + pn533_tx_frame_init(frame, cmd_code); + frame->datalen += payload_len; + pn533_tx_frame_finish(frame); +} + +struct pn533_send_async_complete_arg { + pn533_send_async_complete_t complete_cb; + void *complete_cb_context; + struct sk_buff *resp; + struct sk_buff *req; +}; + +static int pn533_send_async_complete(struct pn533 *dev, void *_arg, u8 *params, + int params_len) +{ + struct pn533_send_async_complete_arg *arg = _arg; + + struct sk_buff *req = arg->req; + struct sk_buff *resp = arg->resp; + + struct pn533_frame *frame = (struct pn533_frame *)resp->data; + int rc; + + dev_kfree_skb(req); + + if (params_len < 0) { + nfc_dev_err(&dev->interface->dev, + "Error %d when starting as a target", + params_len); + + arg->complete_cb(dev, arg->complete_cb_context, + ERR_PTR(params_len)); + rc = params_len; + dev_kfree_skb(resp); + goto out; + } + + skb_put(resp, PN533_FRAME_SIZE(frame)); + skb_pull(resp, PN533_FRAME_HEADER_LEN); + skb_trim(resp, resp->len - PN533_FRAME_TAIL_LEN); + + rc = arg->complete_cb(dev, arg->complete_cb_context, resp); + +out: + kfree(arg); + return rc; +} + +static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, + struct sk_buff *req, struct sk_buff *resp, + int resp_len, + pn533_send_async_complete_t complete_cb, + void *complete_cb_context) +{ + struct pn533_cmd *cmd; + struct pn533_send_async_complete_arg *arg; + int rc = 0; + + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + + arg = kzalloc(sizeof(arg), GFP_KERNEL); + if (!arg) + return -ENOMEM; + + arg->complete_cb = complete_cb; + arg->complete_cb_context = complete_cb_context; + arg->resp = resp; + arg->req = req; + + pn533_build_cmd_frame(cmd_code, req); + + mutex_lock(&dev->cmd_lock); + + if (!dev->cmd_pending) { + rc = __pn533_send_cmd_frame_async(dev, + (struct pn533_frame *)req->data, + (struct pn533_frame *)resp->data, + resp_len, pn533_send_async_complete, + arg); + if (rc) + goto error; + + dev->cmd_pending = 1; + goto unlock; + } + + nfc_dev_dbg(&dev->interface->dev, "%s Queueing command", __func__); + + cmd = kzalloc(sizeof(struct pn533_cmd), GFP_KERNEL); + if (!cmd) { + rc = -ENOMEM; + goto error; + } + + INIT_LIST_HEAD(&cmd->queue); + cmd->cmd_code = cmd_code; + cmd->req = req; + cmd->resp = resp; + cmd->arg = arg; + + list_add_tail(&cmd->queue, &dev->cmd_queue); + + goto unlock; + +error: + kfree(arg); +unlock: + mutex_unlock(&dev->cmd_lock); + return rc; +} + +static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, + struct sk_buff *req, + pn533_send_async_complete_t complete_cb, + void *complete_cb_context) +{ + struct sk_buff *resp; + int rc; + + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + + resp = alloc_skb(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); + if (!resp) + return -ENOMEM; + + rc = __pn533_send_async(dev, cmd_code, req, resp, + PN533_NORMAL_FRAME_MAX_LEN, + complete_cb, complete_cb_context); + if (rc) + dev_kfree_skb(resp); + + return rc; +} + static void pn533_wq_cmd(struct work_struct *work) { struct pn533 *dev = container_of(work, struct pn533, cmd_work); @@ -697,9 +849,17 @@ static void pn533_wq_cmd(struct work_struct *work) mutex_unlock(&dev->cmd_lock); - __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, - cmd->in_frame_len, cmd->cmd_complete, - cmd->arg); + if (cmd->cmd_code != PN533_CMD_UNDEF) + __pn533_send_cmd_frame_async(dev, + (struct pn533_frame *)cmd->req->data, + (struct pn533_frame *)cmd->resp->data, + PN533_NORMAL_FRAME_MAX_LEN, + pn533_send_async_complete, + cmd->arg); + else + __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, + cmd->in_frame_len, + cmd->cmd_complete, cmd->arg); kfree(cmd); } @@ -740,6 +900,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, cmd->out_frame = out_frame; cmd->in_frame = in_frame; cmd->in_frame_len = in_frame_len; + cmd->cmd_code = PN533_CMD_UNDEF; cmd->cmd_complete = cmd_complete; cmd->arg = arg; -- cgit v0.10.2 From 15461aeb53ae2d3bbde6b374de913e3df81d1ad0 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 26 Nov 2012 14:18:35 +0100 Subject: NFC: pn533: Add a new pn533_send_data_async iface This iface is intended to be used with DEP transfers. It differs from pn533_send_cmd_async() in the way the response skb is allocated. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 89f7474..0e9bf9d 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -86,6 +86,12 @@ MODULE_DEVICE_TABLE(usb, pn533_table); + 2) /* data[0] TFI, data[1] CC */ #define PN533_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/ +/* + * Max extended frame payload len, excluding TFI and CC + * which are already in PN533_FRAME_HEADER_LEN. + */ +#define PN533_FRAME_MAX_PAYLOAD_LEN 263 + #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ PN533_FRAME_TAIL_LEN) #define PN533_FRAME_ACK_SIZE (sizeof(struct pn533_frame) + 1) @@ -807,6 +813,31 @@ unlock: return rc; } +static int pn533_send_data_async(struct pn533 *dev, u8 cmd_code, + struct sk_buff *req, + pn533_send_async_complete_t complete_cb, + void *complete_cb_context) +{ + struct sk_buff *resp; + int rc; + int resp_len = PN533_FRAME_HEADER_LEN + + PN533_FRAME_MAX_PAYLOAD_LEN + + PN533_FRAME_TAIL_LEN; + + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + + resp = nfc_alloc_recv_skb(resp_len, GFP_KERNEL); + if (!resp) + return -ENOMEM; + + rc = __pn533_send_async(dev, cmd_code, req, resp, resp_len, complete_cb, + complete_cb_context); + if (rc) + dev_kfree_skb(resp); + + return rc; +} + static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, struct sk_buff *req, pn533_send_async_complete_t complete_cb, -- cgit v0.10.2 From 94c5c1561dde894766b1a9135e47b056fdbe13a4 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 26 Nov 2012 14:18:36 +0100 Subject: NFC: pn533: Add a new pn533_send_sync iface It is intended to replace pn533_send_cmd_frame_sync() iface which requires from the caller to create complete frame. The new function constructs a complete frame itself and sends it out in sync manner. This way frame logic is hidden from the caller. pn533_send_cmd_sync() returns ERR_PTR in case of an error or a pointer to valid response sk_buff otherwise. The pointer must be freed by the caller when it's been consumed. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 0e9bf9d..94c88bb 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -945,6 +945,7 @@ unlock: struct pn533_sync_cmd_response { int rc; + struct sk_buff *resp; struct completion done; }; @@ -965,6 +966,58 @@ static int pn533_sync_cmd_complete(struct pn533 *dev, void *_arg, return 0; } +static int pn533_send_sync_complete(struct pn533 *dev, void *_arg, + struct sk_buff *resp) +{ + struct pn533_sync_cmd_response *arg = _arg; + + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + + arg->resp = resp; + complete(&arg->done); + + return 0; +} + +/* pn533_send_cmd_sync + * + * Please note the req parameter is freed inside the function to + * limit a number of return value interpretations by the caller. + * + * 1. negative in case of error during TX path -> req should be freed + * + * 2. negative in case of error during RX path -> req should not be freed + * as it's been already freed at the begining of RX path by + * async_complete_cb. + * + * 3. valid pointer in case of succesfult RX path + * + * A caller has to check a return value with IS_ERR macro. If the test pass, + * the returned pointer is valid. + * + * */ +static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code, + struct sk_buff *req) +{ + int rc; + struct pn533_sync_cmd_response arg; + + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + + init_completion(&arg.done); + + rc = pn533_send_cmd_async(dev, cmd_code, req, + pn533_send_sync_complete, &arg); + if (rc) { + dev_kfree_skb(req); + return ERR_PTR(rc); + } + + wait_for_completion(&arg.done); + + return arg.resp; +} + static int pn533_send_cmd_frame_sync(struct pn533 *dev, struct pn533_frame *out_frame, struct pn533_frame *in_frame, @@ -2432,7 +2485,7 @@ static int pn533_fw_reset(struct pn533 *dev) rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, PN533_NORMAL_FRAME_MAX_LEN); - return rc; + return 0; } static struct nfc_ops pn533_nfc_ops = { -- cgit v0.10.2 From d22b2db69035ae3b8f71a58dfe0bd10ae1ee58d5 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 26 Nov 2012 14:18:37 +0100 Subject: NFC: pn533: Add pn533_alloc_skb for req allocation Allocate sk_buff for the request. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 94c88bb..c34acd0 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1062,6 +1062,20 @@ static void pn533_send_complete(struct urb *urb) } } +static struct sk_buff *pn533_alloc_skb(unsigned int size) +{ + struct sk_buff *skb; + + skb = alloc_skb(PN533_FRAME_HEADER_LEN + + size + + PN533_FRAME_TAIL_LEN, GFP_KERNEL); + + if (skb) + skb_reserve(skb, PN533_FRAME_HEADER_LEN); + + return skb; +} + struct pn533_target_type_a { __be16 sens_res; u8 sel_res; @@ -2390,15 +2404,11 @@ static void pn533_wq_mi_recv(struct work_struct *work) nfc_dev_dbg(&dev->interface->dev, "%s", __func__); /* This is a zero payload size skb */ - skb_cmd = alloc_skb(PN533_FRAME_HEADER_LEN + - PN533_CMD_DATAEXCH_HEAD_LEN + - PN533_FRAME_TAIL_LEN, - GFP_KERNEL); + skb_cmd = pn533_alloc_skb(PN533_CMD_DATAEXCH_HEAD_LEN); if (skb_cmd == NULL) goto error_cmd; - skb_reserve(skb_cmd, - PN533_FRAME_HEADER_LEN + PN533_CMD_DATAEXCH_HEAD_LEN); + skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); rc = pn533_build_tx_frame(dev, skb_cmd, true); if (rc) -- cgit v0.10.2 From cb950d9304b2965bef07e26d6c0eb34a0b1f75fe Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 26 Nov 2012 14:18:38 +0100 Subject: NFC: pn533: Remove pn533_send_cmd_frame_sync Remove obsolate pn533_send_cmd_frame_sync() and use previously added new iface for sync send. The new interface require the use of individual skb for each cmd which removes some memcpy calls and hides frame logic. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index c34acd0..e5615f5 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -286,11 +286,6 @@ const struct pn533_poll_modulations poll_mod[] = { /* PN533_CMD_IN_ATR */ -struct pn533_cmd_activate_param { - u8 tg; - u8 next; -} __packed; - struct pn533_cmd_activate_response { u8 status; u8 nfcid3t[10]; @@ -944,28 +939,10 @@ unlock: } struct pn533_sync_cmd_response { - int rc; struct sk_buff *resp; struct completion done; }; -static int pn533_sync_cmd_complete(struct pn533 *dev, void *_arg, - u8 *params, int params_len) -{ - struct pn533_sync_cmd_response *arg = _arg; - - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - - arg->rc = 0; - - if (params_len < 0) /* error */ - arg->rc = params_len; - - complete(&arg->done); - - return 0; -} - static int pn533_send_sync_complete(struct pn533 *dev, void *_arg, struct sk_buff *resp) { @@ -1018,28 +995,6 @@ static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code, return arg.resp; } -static int pn533_send_cmd_frame_sync(struct pn533 *dev, - struct pn533_frame *out_frame, - struct pn533_frame *in_frame, - int in_frame_len) -{ - int rc; - struct pn533_sync_cmd_response arg; - - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - - init_completion(&arg.done); - - rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, in_frame_len, - pn533_sync_cmd_complete, &arg); - if (rc) - return rc; - - wait_for_completion(&arg.done); - - return arg.rc; -} - static void pn533_send_complete(struct urb *urb) { struct pn533 *dev = urb->context; @@ -1801,38 +1756,37 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) static int pn533_activate_target_nfcdep(struct pn533 *dev) { - struct pn533_cmd_activate_param param; - struct pn533_cmd_activate_response *resp; + struct pn533_cmd_activate_response *rsp; u16 gt_len; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + struct sk_buff *skb; + struct sk_buff *resp; - pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_ATR); + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - param.tg = 1; - param.next = 0; - memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), ¶m, - sizeof(struct pn533_cmd_activate_param)); - dev->out_frame->datalen += sizeof(struct pn533_cmd_activate_param); + skb = pn533_alloc_skb(sizeof(u8) * 2); /*TG + Next*/ + if (!skb) + return -ENOMEM; - pn533_tx_frame_finish(dev->out_frame); + *skb_put(skb, sizeof(u8)) = 1; /* TG */ + *skb_put(skb, sizeof(u8)) = 0; /* Next */ - rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - PN533_NORMAL_FRAME_MAX_LEN); - if (rc) - return rc; + resp = pn533_send_cmd_sync(dev, PN533_CMD_IN_ATR, skb); + if (IS_ERR(resp)) + return PTR_ERR(resp); - resp = (struct pn533_cmd_activate_response *) - PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame); - rc = resp->status & PN533_CMD_RET_MASK; + rsp = (struct pn533_cmd_activate_response *) resp->data; + rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) + dev_kfree_skb(resp); return -EIO; /* ATR_RES general bytes are located at offset 16 */ - gt_len = PN533_FRAME_CMD_PARAMS_LEN(dev->in_frame) - 16; - rc = nfc_set_remote_general_bytes(dev->nfc_dev, resp->gt, gt_len); + gt_len = resp->len - 16; + rc = nfc_set_remote_general_bytes(dev->nfc_dev, rsp->gt, gt_len); + dev_kfree_skb(resp); return rc; } @@ -1889,8 +1843,10 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, struct nfc_target *target) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - u8 tg; - u8 status; + + struct sk_buff *skb; + struct sk_buff *resp; + int rc; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); @@ -1901,31 +1857,24 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, } dev->tgt_active_prot = 0; - skb_queue_purge(&dev->resp_q); - pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_RELEASE); - - tg = 1; - memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), &tg, sizeof(u8)); - dev->out_frame->datalen += sizeof(u8); + skb = pn533_alloc_skb(sizeof(u8)); + if (!skb) + return; - pn533_tx_frame_finish(dev->out_frame); + *skb_put(skb, 1) = 1; /* TG*/ - rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - PN533_NORMAL_FRAME_MAX_LEN); - if (rc) { - nfc_dev_err(&dev->interface->dev, "Error when sending release" - " command to the controller"); + resp = pn533_send_cmd_sync(dev, PN533_CMD_IN_RELEASE, skb); + if (IS_ERR(resp)) return; - } - status = PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame)[0]; - rc = status & PN533_CMD_RET_MASK; + rc = resp->data[0] & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) nfc_dev_err(&dev->interface->dev, "Error 0x%x when releasing" " the target", rc); + dev_kfree_skb(resp); return; } @@ -2457,43 +2406,71 @@ error_cmd: static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, u8 cfgdata_len) { - int rc; - u8 *params; + struct sk_buff *skb; + struct sk_buff *resp; + + int skb_len; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - pn533_tx_frame_init(dev->out_frame, PN533_CMD_RF_CONFIGURATION); + skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ - params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame); - params[0] = cfgitem; - memcpy(¶ms[1], cfgdata, cfgdata_len); - dev->out_frame->datalen += (1 + cfgdata_len); + skb = pn533_alloc_skb(skb_len); + if (!skb) + return -ENOMEM; - pn533_tx_frame_finish(dev->out_frame); + *skb_put(skb, sizeof(cfgitem)) = cfgitem; + memcpy(skb_put(skb, cfgdata_len), cfgdata, cfgdata_len); - rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - PN533_NORMAL_FRAME_MAX_LEN); + resp = pn533_send_cmd_sync(dev, PN533_CMD_RF_CONFIGURATION, skb); + if (IS_ERR(resp)) + return PTR_ERR(resp); - return rc; + dev_kfree_skb(resp); + return 0; +} + +static int pn533_get_firmware_version(struct pn533 *dev, + struct pn533_fw_version *fv) +{ + struct sk_buff *skb; + struct sk_buff *resp; + + skb = pn533_alloc_skb(0); + if (!skb) + return -ENOMEM; + + resp = pn533_send_cmd_sync(dev, PN533_CMD_GET_FIRMWARE_VERSION, skb); + if (IS_ERR(resp)) + return PTR_ERR(resp); + + fv->ic = resp->data[0]; + fv->ver = resp->data[1]; + fv->rev = resp->data[2]; + fv->support = resp->data[3]; + + dev_kfree_skb(resp); + return 0; } static int pn533_fw_reset(struct pn533 *dev) { - int rc; - u8 *params; + struct sk_buff *skb; + struct sk_buff *resp; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - pn533_tx_frame_init(dev->out_frame, 0x18); + skb = pn533_alloc_skb(sizeof(u8)); + if (!skb) + return -ENOMEM; - params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame); - params[0] = 0x1; - dev->out_frame->datalen += 1; + *skb_put(skb, sizeof(u8)) = 0x1; - pn533_tx_frame_finish(dev->out_frame); + resp = pn533_send_cmd_sync(dev, 0x18, skb); + if (IS_ERR(resp)) + return PTR_ERR(resp); - rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - PN533_NORMAL_FRAME_MAX_LEN); + dev_kfree_skb(resp); return 0; } @@ -2592,7 +2569,7 @@ static int pn533_setup(struct pn533 *dev) static int pn533_probe(struct usb_interface *interface, const struct usb_device_id *id) { - struct pn533_fw_version *fw_ver; + struct pn533_fw_version fw_ver; struct pn533 *dev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; @@ -2664,18 +2641,14 @@ static int pn533_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); - pn533_tx_frame_init(dev->out_frame, PN533_CMD_GET_FIRMWARE_VERSION); - pn533_tx_frame_finish(dev->out_frame); - - rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, - PN533_NORMAL_FRAME_MAX_LEN); - if (rc) + memset(&fw_ver, 0, sizeof(fw_ver)); + rc = pn533_get_firmware_version(dev, &fw_ver); + if (rc < 0) goto destroy_wq; - fw_ver = (struct pn533_fw_version *) - PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame); - nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now" - " attached", fw_ver->ver, fw_ver->rev); + nfc_dev_info(&dev->interface->dev, + "NXP PN533 firmware ver %d.%d now attached", + fw_ver.ver, fw_ver.rev); dev->device_type = id->driver_info; switch (dev->device_type) { -- cgit v0.10.2 From 2593c2c6ec236c6aedbb8182d103185ab6580285 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 7 Dec 2012 15:55:19 +0100 Subject: NFC: llcp: Remove the tx backlog queue Not only it was improperly use to queue backlogged RX skbuffs, but it was also not processed at all. If the socket receive queue is full we simply drop the incoming packets. Signed-off-by: Samuel Ortiz diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 6c59714..003c82f 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -54,7 +54,6 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock) skb_queue_purge(&sock->tx_queue); skb_queue_purge(&sock->tx_pending_queue); - skb_queue_purge(&sock->tx_backlog_queue); if (local == NULL) return; @@ -785,7 +784,7 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, skb_pull(skb, LLCP_HEADER_SIZE); if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { pr_err("receive queue is full\n"); - skb_queue_head(&llcp_sock->tx_backlog_queue, skb); + kfree_skb(skb); } nfc_llcp_sock_put(llcp_sock); @@ -980,7 +979,7 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE); if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { pr_err("receive queue is full\n"); - skb_queue_head(&llcp_sock->tx_backlog_queue, skb); + kfree_skb(skb); } } diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 0d62366..0eae5c5 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h @@ -121,7 +121,6 @@ struct nfc_llcp_sock { struct sk_buff_head tx_queue; struct sk_buff_head tx_pending_queue; - struct sk_buff_head tx_backlog_queue; struct list_head accept_queue; struct sock *parent; diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index ba19007..12ec487 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -808,7 +808,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) llcp_sock->reserved_ssap = LLCP_SAP_MAX; skb_queue_head_init(&llcp_sock->tx_queue); skb_queue_head_init(&llcp_sock->tx_pending_queue); - skb_queue_head_init(&llcp_sock->tx_backlog_queue); INIT_LIST_HEAD(&llcp_sock->accept_queue); if (sock != NULL) @@ -823,7 +822,6 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) skb_queue_purge(&sock->tx_queue); skb_queue_purge(&sock->tx_pending_queue); - skb_queue_purge(&sock->tx_backlog_queue); list_del_init(&sock->accept_queue); -- cgit v0.10.2 From 1727cf937401945a590ebf25c7fa65a4853fe9bb Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 7 Dec 2012 16:37:30 +0100 Subject: NFC: llcp: Fix Rx memory leak The reference count bump on the llcp Rx path is leading to a memory leak whenever we're not receiving an I frame. We fix that by removing the refcount bump (drivers must not free their received skb) and using it only in the I frame path, when the frame is actually queued. In that case, the skb will only be freed when someone fetches it from userspace. in all other cases, LLCP received frames will be freed when leaving the Rx work queue. Reported-by: Eric Lapuyade Signed-off-by: Samuel Ortiz diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 003c82f..85bc75c 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -782,8 +782,14 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, /* There is no sequence with UI frames */ skb_pull(skb, LLCP_HEADER_SIZE); - if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { - pr_err("receive queue is full\n"); + if (!sock_queue_rcv_skb(&llcp_sock->sk, skb)) { + /* + * UI frames will be freed from the socket layer, so we + * need to keep them alive until someone receives them. + */ + skb_get(skb); + } else { + pr_err("Receive queue is full\n"); kfree_skb(skb); } @@ -977,8 +983,14 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, pr_err("Received out of sequence I PDU\n"); skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE); - if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { - pr_err("receive queue is full\n"); + if (!sock_queue_rcv_skb(&llcp_sock->sk, skb)) { + /* + * I frames will be freed from the socket layer, so we + * need to keep them alive until someone receives them. + */ + skb_get(skb); + } else { + pr_err("Receive queue is full\n"); kfree_skb(skb); } } @@ -1299,6 +1311,13 @@ static void nfc_llcp_rx_work(struct work_struct *work) local->rx_pending = NULL; } +static void __nfc_llcp_recv(struct nfc_llcp_local *local, struct sk_buff *skb) +{ + local->rx_pending = skb; + del_timer(&local->link_timer); + schedule_work(&local->rx_work); +} + void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) { struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; @@ -1309,9 +1328,7 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) return; } - local->rx_pending = skb_get(skb); - del_timer(&local->link_timer); - schedule_work(&local->rx_work); + __nfc_llcp_recv(local, skb); } int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) @@ -1322,9 +1339,7 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) if (local == NULL) return -ENODEV; - local->rx_pending = skb_get(skb); - del_timer(&local->link_timer); - schedule_work(&local->rx_work); + __nfc_llcp_recv(local, skb); return 0; } -- cgit v0.10.2 From e487882345a80a17b534182ab1f259f2321e4fed Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:44 +0100 Subject: NFC: pn533: Del frame logic from TgGet/SetData cmd Remove frame logic from TgSetData and TgGetData commands using the new iface for async send. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index e5615f5..9912824 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1450,65 +1450,46 @@ static int pn533_init_target_frame(struct pn533_frame *frame, #define PN533_CMD_DATAEXCH_HEAD_LEN 1 #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 sk_buff *resp) { - struct sk_buff *skb_resp = arg; - struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data; + u8 status; 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); + if (IS_ERR(resp)) + return PTR_ERR(resp); - return params_len; - } + status = resp->data[0]; + skb_pull(resp, sizeof(status)); - if (params_len > 0 && params[0] != 0) { + if (status != 0) { nfc_tm_deactivated(dev->nfc_dev); - dev->tgt_mode = 0; - - kfree_skb(skb_resp); + dev_kfree_skb(resp); return 0; } - skb_put(skb_resp, PN533_FRAME_SIZE(in_frame)); - skb_pull(skb_resp, - PN533_FRAME_HEADER_LEN + PN533_CMD_DATAEXCH_HEAD_LEN); - skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_LEN); - - return nfc_tm_data_received(dev->nfc_dev, skb_resp); + return nfc_tm_data_received(dev->nfc_dev, 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__); + struct sk_buff *skb; + int rc; - skb_resp_len = PN533_FRAME_HEADER_LEN + - PN533_CMD_DATAEXCH_HEAD_LEN + - PN533_CMD_DATAEXCH_DATA_MAXLEN + - PN533_FRAME_TAIL_LEN; + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); - if (!skb_resp) + skb = pn533_alloc_skb(0); + if (!skb) 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); + rc = pn533_send_data_async(dev, PN533_CMD_TG_GET_DATA, skb, + pn533_tm_get_data_complete, NULL); - pn533_send_cmd_frame_async(dev, dev->out_frame, in_frame, - skb_resp_len, - pn533_tm_get_data_complete, - skb_resp); + if (rc < 0) + dev_kfree_skb(skb); return; } @@ -2280,23 +2261,20 @@ error: } static int pn533_tm_send_complete(struct pn533 *dev, void *arg, - u8 *params, int params_len) + struct sk_buff *resp) { - struct sk_buff *skb_out = arg; + u8 status; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - dev_kfree_skb(skb_out); + if (IS_ERR(resp)) + return PTR_ERR(resp); - if (params_len < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when sending data", - params_len); + status = resp->data[0]; - return params_len; - } + dev_kfree_skb(resp); - if (params_len > 0 && params[0] != 0) { + if (status != 0) { nfc_tm_deactivated(dev->nfc_dev); dev->tgt_mode = 0; @@ -2312,30 +2290,21 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg, 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, - PN533_NORMAL_FRAME_MAX_LEN, - pn533_tm_send_complete, skb); - if (rc) { + if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { nfc_dev_err(&dev->interface->dev, - "Error %d when trying to send data", rc); - goto error; + "Data length greater than the max allowed: %d", + PN533_CMD_DATAEXCH_DATA_MAXLEN); + return -ENOSYS; } - return 0; - -error: - kfree_skb(skb); + rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_DATA, skb, + pn533_tm_send_complete, NULL); + if (rc < 0) + dev_kfree_skb(skb); return rc; } -- cgit v0.10.2 From 13003649b1ebb4ea51341a9405a2ec5b10cf4f7e Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:45 +0100 Subject: NFC: pn533: Del frame logic from InJumForDep cmd Remove frame logic from InJmumpForDEP command using the new iface for async send. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 9912824..aa7803f 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -298,14 +298,6 @@ struct pn533_cmd_activate_response { u8 gt[]; } __packed; -/* PN533_CMD_IN_JUMP_FOR_DEP */ -struct pn533_cmd_jump_dep { - u8 active; - u8 baud; - u8 next; - u8 data[]; -} __packed; - struct pn533_cmd_jump_dep_response { u8 status; u8 tg; @@ -1861,53 +1853,46 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, - u8 *params, int params_len) + struct sk_buff *resp) { - struct pn533_cmd_jump_dep_response *resp; - struct nfc_target nfc_target; + struct pn533_cmd_jump_dep_response *rsp; u8 target_gt_len; int rc; - struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg; - u8 active = cmd->active; + u8 active = *(u8 *)arg; kfree(arg); - if (params_len == -ENOENT) { - nfc_dev_dbg(&dev->interface->dev, ""); - return 0; - } - - if (params_len < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when bringing DEP link up", - params_len); - return 0; - } + if (IS_ERR(resp)) + return PTR_ERR(resp); if (dev->tgt_available_prots && !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { nfc_dev_err(&dev->interface->dev, "The target does not support DEP"); - return -EINVAL; + rc = -EINVAL; + goto error; } - resp = (struct pn533_cmd_jump_dep_response *) params; - rc = resp->status & PN533_CMD_RET_MASK; + rsp = (struct pn533_cmd_jump_dep_response *)resp->data; + + rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { nfc_dev_err(&dev->interface->dev, "Bringing DEP link up failed %d", rc); - return 0; + goto error; } if (!dev->tgt_available_prots) { + struct nfc_target nfc_target; + nfc_dev_dbg(&dev->interface->dev, "Creating new target"); nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; nfc_target.nfcid1_len = 10; - memcpy(nfc_target.nfcid1, resp->nfcid3t, nfc_target.nfcid1_len); + memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len); rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1); if (rc) - return 0; + goto error; dev->tgt_available_prots = 0; } @@ -1915,15 +1900,17 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, dev->tgt_active_prot = NFC_PROTO_NFC_DEP; /* ATR_RES general bytes are located at offset 17 */ - target_gt_len = PN533_FRAME_CMD_PARAMS_LEN(dev->in_frame) - 17; + target_gt_len = resp->len - 17; rc = nfc_set_remote_general_bytes(dev->nfc_dev, - resp->gt, target_gt_len); + rsp->gt, target_gt_len); if (rc == 0) rc = nfc_dep_link_is_up(dev->nfc_dev, - dev->nfc_dev->targets[0].idx, - !active, NFC_RF_INITIATOR); + dev->nfc_dev->targets[0].idx, + !active, NFC_RF_INITIATOR); - return 0; +error: + dev_kfree_skb(resp); + return rc; } static int pn533_mod_to_baud(struct pn533 *dev) @@ -1945,10 +1932,11 @@ 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, *data_ptr; + struct sk_buff *skb; + int rc, baud, skb_len; + u8 *next, *arg; + u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - int rc, baud; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); @@ -1971,43 +1959,48 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, return baud; } - cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len; + skb_len = 3 + gb_len; /* ActPass + BR + Next */ if (comm_mode == NFC_COMM_PASSIVE) - cmd_len += PASSIVE_DATA_LEN; + skb_len += PASSIVE_DATA_LEN; - cmd = kzalloc(cmd_len, GFP_KERNEL); - if (cmd == NULL) + skb = pn533_alloc_skb(skb_len); + if (!skb) return -ENOMEM; - pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP); + *skb_put(skb, 1) = !comm_mode; /* ActPass */ + *skb_put(skb, 1) = baud; /* Baud rate */ + + next = skb_put(skb, 1); /* Next */ + *next = 0; - cmd->active = !comm_mode; - 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 (comm_mode == NFC_COMM_PASSIVE && baud > 0) { + memcpy(skb_put(skb, PASSIVE_DATA_LEN), passive_data, + PASSIVE_DATA_LEN); + *next |= 1; } if (gb != NULL && gb_len > 0) { - cmd->next |= 4; /* We have some Gi */ - memcpy(data_ptr, gb, gb_len); + memcpy(skb_put(skb, gb_len), gb, gb_len); + *next |= 4; /* We have some Gi */ } else { - cmd->next = 0; + *next = 0; } - memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), cmd, cmd_len); - dev->out_frame->datalen += cmd_len; + arg = kmalloc(sizeof(*arg), GFP_KERNEL); + if (!arg) { + dev_kfree_skb(skb); + return -ENOMEM; + } - pn533_tx_frame_finish(dev->out_frame); + *arg = !comm_mode; - rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, - PN533_NORMAL_FRAME_MAX_LEN, - pn533_in_dep_link_up_complete, cmd); - if (rc < 0) - kfree(cmd); + rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb, + pn533_in_dep_link_up_complete, arg); + + if (rc < 0) { + dev_kfree_skb(skb); + kfree(arg); + } return rc; } -- cgit v0.10.2 From b1e666f503b5479efe9adf79fb46f09fe4f04af5 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:46 +0100 Subject: NFC: pn533: Del frame logic from Data Exchange cmd Remove frame logic from transceive cb using new iface for async send. For pn533_wq_mi_recv() use pn533_send_cmd_direct_async which sends the cmd directly to the hardware, skipping cmd queue. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index aa7803f..91e1594 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -360,6 +360,7 @@ struct pn533 { pn533_cmd_complete_t cmd_complete; void *cmd_complete_arg; + void *cmd_complete_mi_arg; struct mutex cmd_lock; u8 cmd; @@ -848,6 +849,57 @@ static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, return rc; } +/* + * pn533_send_cmd_direct_async + * + * The function sends a piority cmd directly to the chip omiting the cmd + * queue. It's intended to be used by chaining mechanism of received responses + * where the host has to request every single chunk of data before scheduling + * next cmd from the queue. + */ +static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, + struct sk_buff *req, + pn533_send_async_complete_t complete_cb, + void *complete_cb_context) +{ + struct pn533_send_async_complete_arg *arg; + struct sk_buff *resp; + int rc; + int resp_len = PN533_FRAME_HEADER_LEN + + PN533_FRAME_MAX_PAYLOAD_LEN + + PN533_FRAME_TAIL_LEN; + + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + + resp = alloc_skb(resp_len, GFP_KERNEL); + if (!resp) + return -ENOMEM; + + arg = kzalloc(sizeof(arg), GFP_KERNEL); + if (!arg) { + dev_kfree_skb(resp); + return -ENOMEM; + } + + arg->complete_cb = complete_cb; + arg->complete_cb_context = complete_cb_context; + arg->resp = resp; + arg->req = req; + + pn533_build_cmd_frame(cmd_code, req); + + rc = __pn533_send_cmd_frame_async(dev, (struct pn533_frame *)req->data, + (struct pn533_frame *)resp->data, + resp_len, pn533_send_async_complete, + arg); + if (rc < 0) { + dev_kfree_skb(resp); + kfree(arg); + } + + return rc; +} + static void pn533_wq_cmd(struct work_struct *work) { struct pn533 *dev = container_of(work, struct pn533, cmd_work); @@ -2024,69 +2076,7 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) return 0; } -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; - u8 tg; - - nfc_dev_dbg(&dev->interface->dev, "%s - Sending %d bytes", __func__, - payload_len); - - if (payload_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); - return -ENOSYS; - } - - skb_push(skb, PN533_FRAME_HEADER_LEN); - - if (target == true) { - switch (dev->device_type) { - case PN533_DEVICE_PASORI: - if (dev->tgt_active_prot == NFC_PROTO_FELICA) { - out_frame = (struct pn533_frame *) skb->data; - pn533_tx_frame_init(out_frame, - PN533_CMD_IN_COMM_THRU); - - break; - } - - default: - 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); - tg = 1; - memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), - &tg, sizeof(u8)); - out_frame->datalen += sizeof(u8); - - break; - } - - } 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 */ - out_frame->datalen += payload_len; - - pn533_tx_frame_finish(out_frame); - skb_put(skb, PN533_FRAME_TAIL_LEN); - - return 0; -} - struct pn533_data_exchange_arg { - struct sk_buff *skb_resp; - struct sk_buff *skb_out; data_exchange_cb_t cb; void *cb_context; }; @@ -2130,47 +2120,44 @@ out: } static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, - u8 *params, int params_len) + struct sk_buff *resp) { struct pn533_data_exchange_arg *arg = _arg; - struct sk_buff *skb = NULL, *skb_resp = arg->skb_resp; - struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data; - int err = 0; - u8 status; - u8 cmd_ret; + struct sk_buff *skb; + int rc = 0; + u8 status, ret, mi; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - dev_kfree_skb(arg->skb_out); - - if (params_len < 0) { /* error */ - err = params_len; - goto error; + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + goto _error; } - status = params[0]; + status = resp->data[0]; + ret = status & PN533_CMD_RET_MASK; + mi = status & PN533_CMD_MI_MASK; + + skb_pull(resp, sizeof(status)); - cmd_ret = status & PN533_CMD_RET_MASK; - if (cmd_ret != PN533_CMD_RET_SUCCESS) { - nfc_dev_err(&dev->interface->dev, "PN533 reported error %d when" - " exchanging data", cmd_ret); - err = -EIO; + if (ret != PN533_CMD_RET_SUCCESS) { + nfc_dev_err(&dev->interface->dev, + "PN533 reported error %d when exchanging data", + ret); + rc = -EIO; goto error; } - skb_put(skb_resp, PN533_FRAME_SIZE(in_frame)); - skb_pull(skb_resp, PN533_FRAME_HEADER_LEN); - skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN); - skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_LEN); - skb_queue_tail(&dev->resp_q, skb_resp); + skb_queue_tail(&dev->resp_q, resp); - if (status & PN533_CMD_MI_MASK) { + if (mi) { + dev->cmd_complete_mi_arg = arg; queue_work(dev->wq, &dev->mi_work); return -EINPROGRESS; } skb = pn533_build_response(dev); - if (skb == NULL) + if (!skb) goto error; arg->cb(arg->cb_context, skb, 0); @@ -2178,11 +2165,12 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, return 0; error: + dev_kfree_skb(resp); +_error: skb_queue_purge(&dev->resp_q); - dev_kfree_skb(skb_resp); - arg->cb(arg->cb_context, NULL, err); + arg->cb(arg->cb_context, NULL, rc); kfree(arg); - return 0; + return rc; } static int pn533_transceive(struct nfc_dev *nfc_dev, @@ -2190,14 +2178,20 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, data_exchange_cb_t cb, void *cb_context) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - struct pn533_frame *out_frame, *in_frame; - struct pn533_data_exchange_arg *arg; - struct sk_buff *skb_resp; - int skb_resp_len; + struct pn533_data_exchange_arg *arg = NULL; int rc; 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) { nfc_dev_err(&dev->interface->dev, "Cannot exchange data if" " there is no active target"); @@ -2205,51 +2199,43 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, goto error; } - rc = pn533_build_tx_frame(dev, skb, true); - if (rc) - goto error; - - skb_resp_len = PN533_FRAME_HEADER_LEN + - PN533_CMD_DATAEXCH_HEAD_LEN + - PN533_CMD_DATAEXCH_DATA_MAXLEN + - PN533_FRAME_TAIL_LEN; - - skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); - if (!skb_resp) { - rc = -ENOMEM; - goto error; - } - - in_frame = (struct pn533_frame *) skb_resp->data; - out_frame = (struct pn533_frame *) skb->data; - - arg = kmalloc(sizeof(struct pn533_data_exchange_arg), GFP_KERNEL); + arg = kmalloc(sizeof(*arg), GFP_KERNEL); if (!arg) { rc = -ENOMEM; - goto free_skb_resp; + goto error; } - arg->skb_resp = skb_resp; - arg->skb_out = skb; arg->cb = cb; arg->cb_context = cb_context; - rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, skb_resp_len, - pn533_data_exchange_complete, arg); - if (rc) { - nfc_dev_err(&dev->interface->dev, "Error %d when trying to" - " perform data_exchange", rc); - goto free_arg; + switch (dev->device_type) { + case PN533_DEVICE_PASORI: + if (dev->tgt_active_prot == NFC_PROTO_FELICA) { + rc = pn533_send_data_async(dev, PN533_CMD_IN_COMM_THRU, + skb, + pn533_data_exchange_complete, + arg); + + break; + } + default: + *skb_push(skb, sizeof(u8)) = 1; /*TG*/ + + rc = pn533_send_data_async(dev, PN533_CMD_IN_DATA_EXCHANGE, + skb, pn533_data_exchange_complete, + arg); + + break; } + if (rc < 0) /* rc from send_async */ + goto error; + return 0; -free_arg: - kfree(arg); -free_skb_resp: - kfree_skb(skb_resp); error: - kfree_skb(skb); + kfree(arg); + dev_kfree_skb(skb); return rc; } @@ -2305,63 +2291,50 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) static void pn533_wq_mi_recv(struct work_struct *work) { struct pn533 *dev = container_of(work, struct pn533, mi_work); - struct sk_buff *skb_cmd; - struct pn533_data_exchange_arg *arg = dev->cmd_complete_arg; - struct pn533_frame *out_frame, *in_frame; - struct sk_buff *skb_resp; - int skb_resp_len; + + struct sk_buff *skb; int rc; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - /* This is a zero payload size skb */ - skb_cmd = pn533_alloc_skb(PN533_CMD_DATAEXCH_HEAD_LEN); - if (skb_cmd == NULL) - goto error_cmd; + skb = pn533_alloc_skb(PN533_CMD_DATAEXCH_HEAD_LEN); + if (!skb) + goto error; - skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); + switch (dev->device_type) { + case PN533_DEVICE_PASORI: + if (dev->tgt_active_prot == NFC_PROTO_FELICA) { + rc = pn533_send_cmd_direct_async(dev, + PN533_CMD_IN_COMM_THRU, + skb, + pn533_data_exchange_complete, + dev->cmd_complete_mi_arg); - rc = pn533_build_tx_frame(dev, skb_cmd, true); - if (rc) - goto error_frame; + break; + } + default: + *skb_put(skb, sizeof(u8)) = 1; /*TG*/ - skb_resp_len = PN533_FRAME_HEADER_LEN + - PN533_CMD_DATAEXCH_HEAD_LEN + - PN533_CMD_DATAEXCH_DATA_MAXLEN + - PN533_FRAME_TAIL_LEN; + rc = pn533_send_cmd_direct_async(dev, + PN533_CMD_IN_DATA_EXCHANGE, + skb, + pn533_data_exchange_complete, + dev->cmd_complete_mi_arg); - skb_resp = alloc_skb(skb_resp_len, GFP_KERNEL); - if (!skb_resp) { - rc = -ENOMEM; - goto error_frame; + break; } - in_frame = (struct pn533_frame *) skb_resp->data; - out_frame = (struct pn533_frame *) skb_cmd->data; - - arg->skb_resp = skb_resp; - arg->skb_out = skb_cmd; - - rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, - skb_resp_len, - pn533_data_exchange_complete, - dev->cmd_complete_arg); - if (!rc) + if (rc == 0) /* success */ return; - nfc_dev_err(&dev->interface->dev, "Error %d when trying to" - " perform data_exchange", rc); - - kfree_skb(skb_resp); + nfc_dev_err(&dev->interface->dev, + "Error %d when trying to perform data_exchange", rc); -error_frame: - kfree_skb(skb_cmd); + dev_kfree_skb(skb); + kfree(dev->cmd_complete_arg); -error_cmd: +error: pn533_send_ack(dev, GFP_KERNEL); - - kfree(arg); - queue_work(dev->wq, &dev->cmd_work); } -- cgit v0.10.2 From 99e591be3d95e55412585729624b05862bb5463c Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:47 +0100 Subject: NFC: pn533: Dump tx and rx data in debug mode Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 91e1594..b445f03 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -542,6 +542,9 @@ static void pn533_recv_response(struct urb *urb) in_frame = dev->in_urb->transfer_buffer; + print_hex_dump(KERN_DEBUG, "PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, + in_frame, PN533_FRAME_SIZE(in_frame), false); + if (!pn533_rx_frame_is_valid(in_frame)) { nfc_dev_err(&dev->interface->dev, "Received an invalid frame"); dev->wq_in_error = -EIO; @@ -664,6 +667,9 @@ static int __pn533_send_cmd_frame_async(struct pn533 *dev, dev->in_urb->transfer_buffer = in_frame; dev->in_urb->transfer_buffer_length = in_frame_len; + print_hex_dump(KERN_DEBUG, "PN533 TX: ", DUMP_PREFIX_NONE, 16, 1, + out_frame, PN533_FRAME_SIZE(out_frame), false); + rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); if (rc) return rc; -- cgit v0.10.2 From b5193e5da24fb278c68fc0493c0a1073a1b27ab9 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:48 +0100 Subject: NFC: pn533: Remove frame logic from poll cmds Remove frame logic from start_pool cb using the new iface for async send. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index b445f03..1016e09 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -320,20 +320,6 @@ struct pn533_cmd_jump_dep_response { #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; @@ -1315,50 +1301,37 @@ static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data, return 0; } -struct pn533_poll_response { - u8 nbtg; - u8 tg; - u8 target_data[]; -} __packed; - -static int pn533_target_found(struct pn533 *dev, - struct pn533_poll_response *resp, int resp_len) +static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, + int tgdata_len) { - int target_data_len; struct nfc_target nfc_tgt; int rc; nfc_dev_dbg(&dev->interface->dev, "%s - modulation=%d", __func__, - dev->poll_mod_curr); + dev->poll_mod_curr); - if (resp->tg != 1) + if (tg != 1) return -EPROTO; memset(&nfc_tgt, 0, sizeof(struct nfc_target)); - target_data_len = resp_len - sizeof(struct pn533_poll_response); - switch (dev->poll_mod_curr) { case PN533_POLL_MOD_106KBPS_A: - rc = pn533_target_found_type_a(&nfc_tgt, resp->target_data, - target_data_len); + rc = pn533_target_found_type_a(&nfc_tgt, tgdata, tgdata_len); break; case PN533_POLL_MOD_212KBPS_FELICA: case PN533_POLL_MOD_424KBPS_FELICA: - rc = pn533_target_found_felica(&nfc_tgt, resp->target_data, - target_data_len); + rc = pn533_target_found_felica(&nfc_tgt, tgdata, tgdata_len); break; case PN533_POLL_MOD_106KBPS_JEWEL: - rc = pn533_target_found_jewel(&nfc_tgt, resp->target_data, - target_data_len); + rc = pn533_target_found_jewel(&nfc_tgt, tgdata, tgdata_len); break; case PN533_POLL_MOD_847KBPS_B: - rc = pn533_target_found_type_b(&nfc_tgt, resp->target_data, - target_data_len); + rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len); break; default: - nfc_dev_err(&dev->interface->dev, "Unknown current poll" - " modulation"); + nfc_dev_err(&dev->interface->dev, + "Unknown current poll modulation"); return -EPROTO; } @@ -1366,13 +1339,14 @@ static int pn533_target_found(struct pn533 *dev, return rc; if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { - nfc_dev_dbg(&dev->interface->dev, "The target found does not" - " have the desired protocol"); + nfc_dev_dbg(&dev->interface->dev, + "The Tg found doesn't have the desired protocol"); return -EAGAIN; } - nfc_dev_dbg(&dev->interface->dev, "Target found - supported protocols: " - "0x%x", nfc_tgt.supported_protocols); + nfc_dev_dbg(&dev->interface->dev, + "Target found - supported protocols: 0x%x", + nfc_tgt.supported_protocols); dev->tgt_available_prots = nfc_tgt.supported_protocols; @@ -1424,16 +1398,20 @@ static void pn533_poll_create_mod_list(struct pn533 *dev, pn533_poll_add_mod(dev, PN533_LISTEN_MOD); } -static int pn533_start_poll_complete(struct pn533 *dev, u8 *params, int params_len) +static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) { - struct pn533_poll_response *resp; - int rc; + u8 nbtg, tg, *tgdata; + int rc, tgdata_len; 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); + nbtg = resp->data[0]; + tg = resp->data[1]; + tgdata = &resp->data[2]; + tgdata_len = resp->len - 2; /* nbtg + tg */ + + if (nbtg) { + rc = pn533_target_found(dev, tg, tgdata, tgdata_len); /* We must stop the poll after a valid target found */ if (rc == 0) { @@ -1445,56 +1423,55 @@ static int pn533_start_poll_complete(struct pn533 *dev, u8 *params, int params_l return -EAGAIN; } -static int pn533_init_target_frame(struct pn533_frame *frame, - u8 *gb, size_t gb_len) +static struct sk_buff *pn533_alloc_poll_tg_frame(u8 *gbytes, size_t gbytes_len) { - struct pn533_cmd_init_target *cmd; - size_t cmd_len; + struct sk_buff *skb; + u8 *felica, *nfcid3, *gb; + 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; + unsigned int skb_len = 36 + /* mode (1), mifare (6), + felica (18), nfcid3 (10), gb_len (1) */ + gbytes_len + + 1; /* len Tk*/ - pn533_tx_frame_init(frame, PN533_CMD_TG_INIT_AS_TARGET); + skb = pn533_alloc_skb(skb_len); + if (!skb) + return NULL; /* DEP support only */ - cmd->mode |= PN533_INIT_TARGET_DEP; + *skb_put(skb, 1) |= PN533_INIT_TARGET_DEP; + + /* MIFARE params */ + memcpy(skb_put(skb, 6), mifare_params, 6); /* Felica params */ - memcpy(cmd->felica, felica_params, 18); - get_random_bytes(cmd->felica + 2, 6); + felica = skb_put(skb, 18); + memcpy(felica, felica_params, 18); + get_random_bytes(felica + 2, 6); /* NFCID3 */ - memset(cmd->nfcid3, 0, 10); - memcpy(cmd->nfcid3, cmd->felica, 8); - - /* MIFARE params */ - memcpy(cmd->mifare, mifare_params, 6); + nfcid3 = skb_put(skb, 10); + memset(nfcid3, 0, 10); + memcpy(nfcid3, felica, 8); /* 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); + *skb_put(skb, 1) = gbytes_len; - frame->datalen += cmd_len; + gb = skb_put(skb, gbytes_len); + memcpy(gb, gbytes, gbytes_len); - pn533_tx_frame_finish(frame); - - kfree(cmd); + /* Len Tk */ + *skb_put(skb, 1) = 0; - return 0; + return skb; } #define PN533_CMD_DATAEXCH_HEAD_LEN 1 @@ -1545,41 +1522,32 @@ static void pn533_wq_tg_get_data(struct work_struct *work) } #define ATR_REQ_GB_OFFSET 17 -static int pn533_init_target_complete(struct pn533 *dev, u8 *params, int params_len) +static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) { - struct pn533_cmd_init_target_response *resp; - u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb; + u8 mode, *cmd, 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 starting as a target", - params_len); - - return params_len; - } - - if (params_len < ATR_REQ_GB_OFFSET + 1) + if (resp->len < ATR_REQ_GB_OFFSET + 1) return -EINVAL; - resp = (struct pn533_cmd_init_target_response *) params; + mode = resp->data[0]; + cmd = &resp->data[1]; - nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x param len %d\n", - resp->mode, params_len); + nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", + mode, resp->len); - frame = resp->mode & PN533_INIT_TARGET_RESP_FRAME_MASK; - if (frame == PN533_INIT_TARGET_RESP_ACTIVE) + if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) == + PN533_INIT_TARGET_RESP_ACTIVE) comm_mode = NFC_COMM_ACTIVE; - /* Again, only DEP */ - if ((resp->mode & PN533_INIT_TARGET_RESP_DEP) == 0) + if ((mode & PN533_INIT_TARGET_RESP_DEP) == 0) /* Only DEP supported */ return -EOPNOTSUPP; - gb = resp->cmd + ATR_REQ_GB_OFFSET; - gb_len = params_len - (ATR_REQ_GB_OFFSET + 1); + gb = cmd + ATR_REQ_GB_OFFSET; + gb_len = resp->len - (ATR_REQ_GB_OFFSET + 1); rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, comm_mode, gb, gb_len); @@ -1590,7 +1558,6 @@ static int pn533_init_target_complete(struct pn533 *dev, u8 *params, int params_ } dev->tgt_mode = 1; - queue_work(dev->wq, &dev->tg_work); return 0; @@ -1613,89 +1580,104 @@ static void pn533_listen_mode_timer(unsigned long data) } static int pn533_poll_complete(struct pn533 *dev, void *arg, - u8 *params, int params_len) + struct sk_buff *resp) { 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; - - nfc_dev_err(&dev->interface->dev, - "Polling operation has been stopped"); + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); - goto stop_poll; - } + nfc_dev_err(&dev->interface->dev, "%s Poll complete error %d", + __func__, rc); - if (params_len < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when running poll", params_len); - - goto stop_poll; + if (rc == -ENOENT) { + if (dev->poll_mod_count != 0) + return rc; + else + goto stop_poll; + } else if (rc < 0) { + nfc_dev_err(&dev->interface->dev, + "Error %d when running poll", rc); + goto stop_poll; + } } cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; - if (cur_mod->len == 0) { + if (cur_mod->len == 0) { /* Target mode */ del_timer(&dev->listen_timer); - - return pn533_init_target_complete(dev, params, params_len); - } else { - rc = pn533_start_poll_complete(dev, params, params_len); - if (!rc) - return rc; + rc = pn533_init_target_complete(dev, resp); + goto done; } - pn533_poll_next_mod(dev); + /* Initiator mode */ + rc = pn533_start_poll_complete(dev, resp); + if (!rc) + goto done; + pn533_poll_next_mod(dev); queue_work(dev->wq, &dev->poll_work); - return 0; +done: + dev_kfree_skb(resp); + return rc; stop_poll: + nfc_dev_err(&dev->interface->dev, "Polling operation has been stopped"); + pn533_poll_reset_mod_list(dev); dev->poll_protocols = 0; - return 0; + return rc; } -static void pn533_build_poll_frame(struct pn533 *dev, - struct pn533_frame *frame, - struct pn533_poll_modulations *mod) +static struct sk_buff *pn533_alloc_poll_in_frame(struct pn533_poll_modulations + *mod) { - nfc_dev_dbg(&dev->interface->dev, "mod len %d\n", mod->len); + struct sk_buff *skb; - 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); + skb = pn533_alloc_skb(mod->len); + if (!skb) + return NULL; - memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len); - frame->datalen += mod->len; + memcpy(skb_put(skb, mod->len), &mod->data, mod->len); - pn533_tx_frame_finish(frame); - } + return skb; } static int pn533_send_poll_frame(struct pn533 *dev) { - struct pn533_poll_modulations *cur_mod; + struct pn533_poll_modulations *mod; + struct sk_buff *skb; int rc; + u8 cmd_code; - cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; + mod = dev->poll_mod_active[dev->poll_mod_curr]; - pn533_build_poll_frame(dev, dev->out_frame, cur_mod); + nfc_dev_dbg(&dev->interface->dev, "%s mod len %d\n", + __func__, mod->len); - rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, - PN533_NORMAL_FRAME_MAX_LEN, - pn533_poll_complete, - NULL); - if (rc) + if (mod->len == 0) { /* Listen mode */ + cmd_code = PN533_CMD_TG_INIT_AS_TARGET; + skb = pn533_alloc_poll_tg_frame(dev->gb, dev->gb_len); + } else { /* Polling mode */ + cmd_code = PN533_CMD_IN_LIST_PASSIVE_TARGET; + skb = pn533_alloc_poll_in_frame(mod); + } + + if (!skb) { + nfc_dev_err(&dev->interface->dev, "Failed to allocate skb."); + return -ENOMEM; + } + + rc = pn533_send_cmd_async(dev, cmd_code, skb, pn533_poll_complete, + NULL); + if (rc < 0) { + dev_kfree_skb(skb); nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); + } return rc; } -- cgit v0.10.2 From 6ca55372bf55885e02d17c58cd29ceef045ee699 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:49 +0100 Subject: NFC: pn533: Fix quoted strings split across lines Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 1016e09..4397061 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -515,13 +515,13 @@ static void pn533_recv_response(struct urb *urb) case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: - nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with" - " status: %d", urb->status); + nfc_dev_dbg(&dev->interface->dev, + "Urb shutting down with status: %d", urb->status); dev->wq_in_error = urb->status; goto sched_wq; default: - nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:" - " %d", urb->status); + nfc_dev_err(&dev->interface->dev, + "Nonzero urb status received: %d", urb->status); dev->wq_in_error = urb->status; goto sched_wq; } @@ -538,8 +538,8 @@ static void pn533_recv_response(struct urb *urb) } if (!pn533_rx_frame_is_cmd_response(in_frame, dev->cmd)) { - nfc_dev_err(&dev->interface->dev, "The received frame is not " - "response to the last command"); + nfc_dev_err(&dev->interface->dev, + "It it not the response to the last command"); dev->wq_in_error = -EIO; goto sched_wq; } @@ -572,13 +572,13 @@ static void pn533_recv_ack(struct urb *urb) case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: - nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with" - " status: %d", urb->status); + nfc_dev_dbg(&dev->interface->dev, + "Urb shutting down with status: %d", urb->status); dev->wq_in_error = urb->status; goto sched_wq; default: - nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:" - " %d", urb->status); + nfc_dev_err(&dev->interface->dev, + "Nonzero urb status received: %d", urb->status); dev->wq_in_error = urb->status; goto sched_wq; } @@ -595,8 +595,8 @@ static void pn533_recv_ack(struct urb *urb) rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); if (rc) { - nfc_dev_err(&dev->interface->dev, "usb_submit_urb failed with" - " result %d", rc); + nfc_dev_err(&dev->interface->dev, + "usb_submit_urb failed with result %d", rc); dev->wq_in_error = rc; goto sched_wq; } @@ -1044,12 +1044,12 @@ static void pn533_send_complete(struct urb *urb) case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: - nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with" - " status: %d", urb->status); + nfc_dev_dbg(&dev->interface->dev, + "Urb shutting down with status: %d", urb->status); break; default: - nfc_dev_dbg(&dev->interface->dev, "Nonzero urb status received:" - " %d", urb->status); + nfc_dev_dbg(&dev->interface->dev, + "Nonzero urb status received: %d", urb->status); } } @@ -1753,8 +1753,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) del_timer(&dev->listen_timer); if (!dev->poll_mod_count) { - nfc_dev_dbg(&dev->interface->dev, "Polling operation was not" - " running"); + nfc_dev_dbg(&dev->interface->dev, + "Polling operation was not running"); return; } @@ -1813,35 +1813,35 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, protocol); if (dev->poll_mod_count) { - nfc_dev_err(&dev->interface->dev, "Cannot activate while" - " polling"); + nfc_dev_err(&dev->interface->dev, + "Cannot activate while polling"); return -EBUSY; } if (dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, "There is already an active" - " target"); + nfc_dev_err(&dev->interface->dev, + "There is already an active target"); return -EBUSY; } if (!dev->tgt_available_prots) { - nfc_dev_err(&dev->interface->dev, "There is no available target" - " to activate"); + nfc_dev_err(&dev->interface->dev, + "There is no available target to activate"); return -EINVAL; } if (!(dev->tgt_available_prots & (1 << protocol))) { - nfc_dev_err(&dev->interface->dev, "The target does not support" - " the requested protocol %u", protocol); + nfc_dev_err(&dev->interface->dev, + "Target doesn't support requested proto %u", + protocol); return -EINVAL; } if (protocol == NFC_PROTO_NFC_DEP) { rc = pn533_activate_target_nfcdep(dev); if (rc) { - nfc_dev_err(&dev->interface->dev, "Error %d when" - " activating target with" - " NFC_DEP protocol", rc); + nfc_dev_err(&dev->interface->dev, + "Activating target with DEP failed %d", rc); return rc; } } @@ -1884,8 +1884,8 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, rc = resp->data[0] & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) - nfc_dev_err(&dev->interface->dev, "Error 0x%x when releasing" - " the target", rc); + nfc_dev_err(&dev->interface->dev, + "Error 0x%x when releasing the target", rc); dev_kfree_skb(resp); return; @@ -2181,8 +2181,8 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, } if (!dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, "Cannot exchange data if" - " there is no active target"); + nfc_dev_err(&dev->interface->dev, + "Can't exchange data if there is no active target"); rc = -EINVAL; goto error; } @@ -2522,8 +2522,8 @@ static int pn533_probe(struct usb_interface *interface, } if (!in_endpoint || !out_endpoint) { - nfc_dev_err(&interface->dev, "Could not find bulk-in or" - " bulk-out endpoint"); + nfc_dev_err(&interface->dev, + "Could not find bulk-in or bulk-out endpoint"); rc = -ENODEV; goto error; } -- cgit v0.10.2 From 37cf4fc6c98f230ca026763ae03cb88ff786eeb9 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:50 +0100 Subject: NFC: pn533: Fix spacing issues Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 4397061..19fecdb 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1124,7 +1124,7 @@ static int pn533_target_found_type_a(struct nfc_target *nfc_tgt, u8 *tgt_data, { struct pn533_target_type_a *tgt_type_a; - tgt_type_a = (struct pn533_target_type_a *) tgt_data; + tgt_type_a = (struct pn533_target_type_a *)tgt_data; if (!pn533_target_type_a_is_valid(tgt_type_a, tgt_data_len)) return -EPROTO; @@ -1182,7 +1182,7 @@ static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data, { struct pn533_target_felica *tgt_felica; - tgt_felica = (struct pn533_target_felica *) tgt_data; + tgt_felica = (struct pn533_target_felica *)tgt_data; if (!pn533_target_felica_is_valid(tgt_felica, tgt_data_len)) return -EPROTO; @@ -1232,7 +1232,7 @@ static int pn533_target_found_jewel(struct nfc_target *nfc_tgt, u8 *tgt_data, { struct pn533_target_jewel *tgt_jewel; - tgt_jewel = (struct pn533_target_jewel *) tgt_data; + tgt_jewel = (struct pn533_target_jewel *)tgt_data; if (!pn533_target_jewel_is_valid(tgt_jewel, tgt_data_len)) return -EPROTO; @@ -1291,7 +1291,7 @@ static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data, { struct pn533_target_type_b *tgt_type_b; - tgt_type_b = (struct pn533_target_type_b *) tgt_data; + tgt_type_b = (struct pn533_target_type_b *)tgt_data; if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len)) return -EPROTO; @@ -1368,7 +1368,7 @@ static void pn533_poll_reset_mod_list(struct pn533 *dev) static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index) { dev->poll_mod_active[dev->poll_mod_count] = - (struct pn533_poll_modulations *) &poll_mod[mod_index]; + (struct pn533_poll_modulations *)&poll_mod[mod_index]; dev->poll_mod_count++; } @@ -1565,7 +1565,7 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) static void pn533_listen_mode_timer(unsigned long data) { - struct pn533 *dev = (struct pn533 *) data; + struct pn533 *dev = (struct pn533 *)data; nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout"); @@ -1789,7 +1789,7 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) if (IS_ERR(resp)) return PTR_ERR(resp); - rsp = (struct pn533_cmd_activate_response *) resp->data; + rsp = (struct pn533_cmd_activate_response *)resp->data; rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) dev_kfree_skb(resp); @@ -1969,7 +1969,7 @@ static int pn533_mod_to_baud(struct pn533 *dev) #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) + u8 comm_mode, u8 *gb, size_t gb_len) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); struct sk_buff *skb; -- cgit v0.10.2 From 5d467742bc53eff6233bd437c13dcefb449246f8 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:51 +0100 Subject: NFC: pn533: Fix open parenthesis alignment Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 19fecdb..02043dc 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -640,7 +640,7 @@ static int __pn533_send_cmd_frame_async(struct pn533 *dev, int rc; nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", - PN533_FRAME_CMD(out_frame)); + PN533_FRAME_CMD(out_frame)); dev->cmd = PN533_FRAME_CMD(out_frame); dev->cmd_complete = cmd_complete; @@ -1107,9 +1107,9 @@ static bool pn533_target_type_a_is_valid(struct pn533_target_type_a *type_a, platconf = PN533_TYPE_A_SENS_RES_PLATCONF(type_a->sens_res); if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL && - platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) || - (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL && - platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL)) + platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) || + (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL && + platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL)) return false; /* Requirements 4.8.2.1, 4.8.2.3, 4.8.2.5 and 4.8.2.7 from NFC Forum */ @@ -1187,9 +1187,8 @@ static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data, if (!pn533_target_felica_is_valid(tgt_felica, tgt_data_len)) return -EPROTO; - if (tgt_felica->nfcid2[0] == PN533_FELICA_SENSF_NFCID2_DEP_B1 && - tgt_felica->nfcid2[1] == - PN533_FELICA_SENSF_NFCID2_DEP_B2) + if ((tgt_felica->nfcid2[0] == PN533_FELICA_SENSF_NFCID2_DEP_B1) && + (tgt_felica->nfcid2[1] == PN533_FELICA_SENSF_NFCID2_DEP_B2)) nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK; else nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK; @@ -1219,9 +1218,9 @@ static bool pn533_target_jewel_is_valid(struct pn533_target_jewel *jewel, platconf = PN533_TYPE_A_SENS_RES_PLATCONF(jewel->sens_res); if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL && - platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) || - (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL && - platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL)) + platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) || + (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL && + platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL)) return false; return true; @@ -1810,7 +1809,7 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, int rc; nfc_dev_dbg(&dev->interface->dev, "%s - protocol=%u", __func__, - protocol); + protocol); if (dev->poll_mod_count) { nfc_dev_err(&dev->interface->dev, @@ -1908,7 +1907,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (dev->tgt_available_prots && !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { nfc_dev_err(&dev->interface->dev, - "The target does not support DEP"); + "The target does not support DEP"); rc = -EINVAL; goto error; } @@ -1918,7 +1917,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, rc = rsp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { nfc_dev_err(&dev->interface->dev, - "Bringing DEP link up failed %d", rc); + "Bringing DEP link up failed %d", rc); goto error; } @@ -1982,13 +1981,13 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, if (dev->poll_mod_count) { nfc_dev_err(&dev->interface->dev, - "Cannot bring the DEP link up while polling"); + "Cannot bring the DEP link up while polling"); return -EBUSY; } if (dev->tgt_active_prot) { nfc_dev_err(&dev->interface->dev, - "There is already an active target"); + "There is already an active target"); return -EBUSY; } @@ -2533,17 +2532,15 @@ static int pn533_probe(struct usb_interface *interface, dev->out_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->in_frame || !dev->out_frame || - !dev->in_urb || !dev->out_urb) + if (!dev->in_frame || !dev->out_frame || !dev->in_urb || !dev->out_urb) goto error; usb_fill_bulk_urb(dev->in_urb, dev->udev, - usb_rcvbulkpipe(dev->udev, in_endpoint), - NULL, 0, NULL, dev); + usb_rcvbulkpipe(dev->udev, in_endpoint), + NULL, 0, NULL, dev); usb_fill_bulk_urb(dev->out_urb, dev->udev, - usb_sndbulkpipe(dev->udev, out_endpoint), - NULL, 0, - pn533_send_complete, dev); + usb_sndbulkpipe(dev->udev, out_endpoint), + NULL, 0, pn533_send_complete, dev); INIT_WORK(&dev->cmd_work, pn533_wq_cmd); INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete); -- cgit v0.10.2 From b08e860355ba6f67b769c9061f468f7a8856bad9 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:52 +0100 Subject: NFC: pn533: Fix minor style issues Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 02043dc..2cb8ceb 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1376,13 +1376,13 @@ static void pn533_poll_create_mod_list(struct pn533 *dev, { pn533_poll_reset_mod_list(dev); - if (im_protocols & NFC_PROTO_MIFARE_MASK - || im_protocols & NFC_PROTO_ISO14443_MASK - || im_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 (im_protocols & NFC_PROTO_FELICA_MASK - || im_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); } -- cgit v0.10.2 From 89fb20256725e735601ea6439680956fa2ec4741 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:53 +0100 Subject: NFC: pn533: Remove unused pn533_send_cmd_frame_asy Remove obsolete send async api as it's no longer used. Remove global dev->in_frame as well, as each packet is kept is a seperate skb struct now, so that's not used anymore. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 2cb8ceb..d17ec6a 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -329,7 +329,6 @@ struct pn533 { struct pn533_frame *out_frame; struct urb *in_urb; - struct pn533_frame *in_frame; struct sk_buff_head resp_q; @@ -371,13 +370,9 @@ struct pn533 { struct pn533_cmd { struct list_head queue; - struct pn533_frame *out_frame; - struct pn533_frame *in_frame; - int in_frame_len; u8 cmd_code; struct sk_buff *req; struct sk_buff *resp; - pn533_cmd_complete_t cmd_complete; void *arg; }; @@ -911,69 +906,16 @@ static void pn533_wq_cmd(struct work_struct *work) mutex_unlock(&dev->cmd_lock); - if (cmd->cmd_code != PN533_CMD_UNDEF) - __pn533_send_cmd_frame_async(dev, - (struct pn533_frame *)cmd->req->data, - (struct pn533_frame *)cmd->resp->data, - PN533_NORMAL_FRAME_MAX_LEN, - pn533_send_async_complete, - cmd->arg); - else - __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, - cmd->in_frame_len, - cmd->cmd_complete, cmd->arg); + __pn533_send_cmd_frame_async(dev, + (struct pn533_frame *)cmd->req->data, + (struct pn533_frame *)cmd->resp->data, + PN533_NORMAL_FRAME_MAX_LEN, + pn533_send_async_complete, + cmd->arg); kfree(cmd); } -static int pn533_send_cmd_frame_async(struct pn533 *dev, - struct pn533_frame *out_frame, - struct pn533_frame *in_frame, - int in_frame_len, - pn533_cmd_complete_t cmd_complete, - void *arg) -{ - struct pn533_cmd *cmd; - int rc = 0; - - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - - mutex_lock(&dev->cmd_lock); - - if (!dev->cmd_pending) { - rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, - in_frame_len, cmd_complete, - arg); - if (!rc) - dev->cmd_pending = 1; - - goto unlock; - } - - nfc_dev_dbg(&dev->interface->dev, "%s Queueing command", __func__); - - cmd = kzalloc(sizeof(struct pn533_cmd), GFP_KERNEL); - if (!cmd) { - rc = -ENOMEM; - goto unlock; - } - - INIT_LIST_HEAD(&cmd->queue); - cmd->out_frame = out_frame; - cmd->in_frame = in_frame; - cmd->in_frame_len = in_frame_len; - cmd->cmd_code = PN533_CMD_UNDEF; - cmd->cmd_complete = cmd_complete; - cmd->arg = arg; - - list_add_tail(&cmd->queue, &dev->cmd_queue); - -unlock: - mutex_unlock(&dev->cmd_lock); - - return rc; -} - struct pn533_sync_cmd_response { struct sk_buff *resp; struct completion done; @@ -2527,12 +2469,11 @@ static int pn533_probe(struct usb_interface *interface, goto error; } - dev->in_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); dev->out_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->in_frame || !dev->out_frame || !dev->in_urb || !dev->out_urb) + if (!dev->out_frame || !dev->in_urb || !dev->out_urb) goto error; usb_fill_bulk_urb(dev->in_urb, dev->udev, @@ -2616,7 +2557,6 @@ free_nfc_dev: destroy_wq: destroy_workqueue(dev->wq); error: - kfree(dev->in_frame); usb_free_urb(dev->in_urb); kfree(dev->out_frame); usb_free_urb(dev->out_urb); @@ -2649,7 +2589,6 @@ static void pn533_disconnect(struct usb_interface *interface) kfree(cmd); } - kfree(dev->in_frame); usb_free_urb(dev->in_urb); kfree(dev->out_frame); usb_free_urb(dev->out_urb); -- cgit v0.10.2 From f8f991710b580878c88cfe49d918cfb0c9e15236 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:54 +0100 Subject: NFC: pn533: Fix urb->status handling Fix text message to be more suitable for the error code and treat ESHUTDOWN as an error not debug msg. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index d17ec6a..898375d 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -505,18 +505,19 @@ static void pn533_recv_response(struct urb *urb) switch (urb->status) { case 0: - /* success */ - break; + break; /* success */ case -ECONNRESET: case -ENOENT: - case -ESHUTDOWN: nfc_dev_dbg(&dev->interface->dev, - "Urb shutting down with status: %d", urb->status); + "The urb has been canceled (status %d)", + urb->status); dev->wq_in_error = urb->status; goto sched_wq; + break; + case -ESHUTDOWN: default: nfc_dev_err(&dev->interface->dev, - "Nonzero urb status received: %d", urb->status); + "Urb failure (status %d)", urb->status); dev->wq_in_error = urb->status; goto sched_wq; } @@ -562,18 +563,19 @@ static void pn533_recv_ack(struct urb *urb) switch (urb->status) { case 0: - /* success */ - break; + break; /* success */ case -ECONNRESET: case -ENOENT: - case -ESHUTDOWN: nfc_dev_dbg(&dev->interface->dev, - "Urb shutting down with status: %d", urb->status); + "The urb has been stopped (status %d)", + urb->status); dev->wq_in_error = urb->status; goto sched_wq; + break; + case -ESHUTDOWN: default: nfc_dev_err(&dev->interface->dev, - "Nonzero urb status received: %d", urb->status); + "Urb failure (status %d)", urb->status); dev->wq_in_error = urb->status; goto sched_wq; } @@ -981,17 +983,17 @@ static void pn533_send_complete(struct urb *urb) switch (urb->status) { case 0: - /* success */ - break; + break; /* success */ case -ECONNRESET: case -ENOENT: - case -ESHUTDOWN: nfc_dev_dbg(&dev->interface->dev, - "Urb shutting down with status: %d", urb->status); + "The urb has been stopped (status %d)", + urb->status); break; + case -ESHUTDOWN: default: - nfc_dev_dbg(&dev->interface->dev, - "Nonzero urb status received: %d", urb->status); + nfc_dev_err(&dev->interface->dev, + "Urb failure (status %d)", urb->status); } } -- cgit v0.10.2 From fcfafc7690164d08dfd8133a860f25db8019ca2e Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:55 +0100 Subject: NFC: pn533: Cleanup debug messages Remove debug messages which do not include valueable informations in debug mode. Add some new ones for better tracking or reword when if necessary. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 898375d..5fb5b8f 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -524,6 +524,7 @@ static void pn533_recv_response(struct urb *urb) in_frame = dev->in_urb->transfer_buffer; + nfc_dev_dbg(&dev->interface->dev, "Received a frame."); print_hex_dump(KERN_DEBUG, "PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame, PN533_FRAME_SIZE(in_frame), false); @@ -540,7 +541,6 @@ static void pn533_recv_response(struct urb *urb) goto sched_wq; } - nfc_dev_dbg(&dev->interface->dev, "Received a valid frame"); dev->wq_in_error = 0; dev->wq_in_frame = in_frame; @@ -588,8 +588,6 @@ static void pn533_recv_ack(struct urb *urb) goto sched_wq; } - nfc_dev_dbg(&dev->interface->dev, "Received a valid ack"); - rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); if (rc) { nfc_dev_err(&dev->interface->dev, @@ -636,9 +634,6 @@ static int __pn533_send_cmd_frame_async(struct pn533 *dev, { int rc; - nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", - PN533_FRAME_CMD(out_frame)); - dev->cmd = PN533_FRAME_CMD(out_frame); dev->cmd_complete = cmd_complete; dev->cmd_complete_arg = arg; @@ -705,10 +700,6 @@ static int pn533_send_async_complete(struct pn533 *dev, void *_arg, u8 *params, dev_kfree_skb(req); if (params_len < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when starting as a target", - params_len); - arg->complete_cb(dev, arg->complete_cb_context, ERR_PTR(params_len)); rc = params_len; @@ -737,7 +728,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, struct pn533_send_async_complete_arg *arg; int rc = 0; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", cmd_code); arg = kzalloc(sizeof(arg), GFP_KERNEL); if (!arg) @@ -765,7 +756,8 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, goto unlock; } - nfc_dev_dbg(&dev->interface->dev, "%s Queueing command", __func__); + nfc_dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x", __func__, + cmd_code); cmd = kzalloc(sizeof(struct pn533_cmd), GFP_KERNEL); if (!cmd) { @@ -801,8 +793,6 @@ static int pn533_send_data_async(struct pn533 *dev, u8 cmd_code, PN533_FRAME_MAX_PAYLOAD_LEN + PN533_FRAME_TAIL_LEN; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - resp = nfc_alloc_recv_skb(resp_len, GFP_KERNEL); if (!resp) return -ENOMEM; @@ -823,8 +813,6 @@ static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, struct sk_buff *resp; int rc; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - resp = alloc_skb(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); if (!resp) return -ENOMEM; @@ -858,8 +846,6 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, PN533_FRAME_MAX_PAYLOAD_LEN + PN533_FRAME_TAIL_LEN; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - resp = alloc_skb(resp_len, GFP_KERNEL); if (!resp) return -ENOMEM; @@ -928,8 +914,6 @@ static int pn533_send_sync_complete(struct pn533 *dev, void *_arg, { struct pn533_sync_cmd_response *arg = _arg; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - arg->resp = resp; complete(&arg->done); @@ -959,8 +943,6 @@ static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code, int rc; struct pn533_sync_cmd_response arg; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - init_completion(&arg.done); rc = pn533_send_cmd_async(dev, cmd_code, req, @@ -979,8 +961,6 @@ static void pn533_send_complete(struct urb *urb) { struct pn533 *dev = urb->context; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - switch (urb->status) { case 0: break; /* success */ @@ -1992,6 +1972,8 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + pn533_poll_reset_mod_list(dev); if (dev->tgt_mode || dev->tgt_active_prot) { @@ -2017,7 +1999,7 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) struct sk_buff *skb, *tmp, *t; unsigned int skb_len = 0, tmp_len = 0; - nfc_dev_dbg(&dev->interface->dev, "%s\n", __func__); + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); if (skb_queue_empty(&dev->resp_q)) return NULL; -- cgit v0.10.2 From 5b5a4437ae078cbe35020e74eb0b66ebedc2a2c0 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:56 +0100 Subject: NFC: pn533: Don't use out_frame in pn533_send_ack dev->out_frame buffer is much bigger for ACK frame needs. Use local buffer instead. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 5fb5b8f..5bc0c7c 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -94,7 +94,8 @@ MODULE_DEVICE_TABLE(usb, pn533_table); #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ PN533_FRAME_TAIL_LEN) -#define PN533_FRAME_ACK_SIZE (sizeof(struct pn533_frame) + 1) +#define PN533_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2), + Postamble (1) */ #define PN533_FRAME_CHECKSUM(f) (f->data[f->datalen]) #define PN533_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1]) @@ -402,26 +403,6 @@ static u8 pn533_data_checksum(u8 *data, int datalen) return pn533_checksum(sum); } -/** - * pn533_tx_frame_ack - create a ack frame - * @frame: The frame to be set as ack - * - * Ack is different type of standard frame. As a standard frame, it has - * preamble and start_frame. However the checksum of this frame must fail, - * i.e. datalen + datalen_checksum must NOT be zero. When the checksum test - * fails and datalen = 0 and datalen_checksum = 0xFF, the frame is a ack. - * After datalen_checksum field, the postamble is placed. - */ -static void pn533_tx_frame_ack(struct pn533_frame *frame) -{ - frame->preamble = 0; - frame->start_frame = cpu_to_be16(PN533_SOF); - frame->datalen = 0; - frame->datalen_checksum = 0xFF; - /* data[0] is used as postamble */ - frame->data[0] = 0; -} - static void pn533_tx_frame_init(struct pn533_frame *frame, u8 cmd) { frame->preamble = 0; @@ -612,14 +593,14 @@ static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags) static int pn533_send_ack(struct pn533 *dev, gfp_t flags) { + u8 ack[PN533_FRAME_ACK_SIZE] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; + /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ int rc; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - pn533_tx_frame_ack(dev->out_frame); - - dev->out_urb->transfer_buffer = dev->out_frame; - dev->out_urb->transfer_buffer_length = PN533_FRAME_ACK_SIZE; + dev->out_urb->transfer_buffer = ack; + dev->out_urb->transfer_buffer_length = sizeof(ack); rc = usb_submit_urb(dev->out_urb, flags); return rc; -- cgit v0.10.2 From e8f40531113c7e8c6266886803d5bf3a9e5c8d1b Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:57 +0100 Subject: NFC: pn533: Use skb in __pn533_send_cmd_frame_asyn __pn533_send_cmd_frame_async() should be frame type independent. So, don't use pn533_frame type params and instead use skb for req and resp pointers. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 5bc0c7c..cfbfc11 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -606,28 +606,27 @@ static int pn533_send_ack(struct pn533 *dev, gfp_t flags) return rc; } -static int __pn533_send_cmd_frame_async(struct pn533 *dev, - struct pn533_frame *out_frame, - struct pn533_frame *in_frame, - int in_frame_len, +static int __pn533_send_frame_async(struct pn533 *dev, + struct sk_buff *out, + struct sk_buff *in, + int in_len, pn533_cmd_complete_t cmd_complete, void *arg) { int rc; - dev->cmd = PN533_FRAME_CMD(out_frame); + dev->cmd = PN533_FRAME_CMD(((struct pn533_frame *)out->data)); dev->cmd_complete = cmd_complete; dev->cmd_complete_arg = arg; - dev->out_urb->transfer_buffer = out_frame; - dev->out_urb->transfer_buffer_length = - PN533_FRAME_SIZE(out_frame); + dev->out_urb->transfer_buffer = out->data; + dev->out_urb->transfer_buffer_length = out->len; - dev->in_urb->transfer_buffer = in_frame; - dev->in_urb->transfer_buffer_length = in_frame_len; + dev->in_urb->transfer_buffer = in->data; + dev->in_urb->transfer_buffer_length = in_len; print_hex_dump(KERN_DEBUG, "PN533 TX: ", DUMP_PREFIX_NONE, 16, 1, - out_frame, PN533_FRAME_SIZE(out_frame), false); + out->data, out->len, false); rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); if (rc) @@ -725,11 +724,8 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, mutex_lock(&dev->cmd_lock); if (!dev->cmd_pending) { - rc = __pn533_send_cmd_frame_async(dev, - (struct pn533_frame *)req->data, - (struct pn533_frame *)resp->data, - resp_len, pn533_send_async_complete, - arg); + rc = __pn533_send_frame_async(dev, req, resp, resp_len, + pn533_send_async_complete, arg); if (rc) goto error; @@ -844,10 +840,8 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, pn533_build_cmd_frame(cmd_code, req); - rc = __pn533_send_cmd_frame_async(dev, (struct pn533_frame *)req->data, - (struct pn533_frame *)resp->data, - resp_len, pn533_send_async_complete, - arg); + rc = __pn533_send_frame_async(dev, req, resp, resp_len, + pn533_send_async_complete, arg); if (rc < 0) { dev_kfree_skb(resp); kfree(arg); @@ -875,12 +869,10 @@ static void pn533_wq_cmd(struct work_struct *work) mutex_unlock(&dev->cmd_lock); - __pn533_send_cmd_frame_async(dev, - (struct pn533_frame *)cmd->req->data, - (struct pn533_frame *)cmd->resp->data, - PN533_NORMAL_FRAME_MAX_LEN, - pn533_send_async_complete, - cmd->arg); + __pn533_send_frame_async(dev, cmd->req, cmd->resp, + PN533_NORMAL_FRAME_MAX_LEN, + pn533_send_async_complete, + cmd->arg); kfree(cmd); } -- cgit v0.10.2 From a5798094e927847f0d503b756a997175d7ce01ec Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:58 +0100 Subject: NFC: pn533: Remove deprecated dev->out_frame buff As it's not used anymore get rid of that buffer. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index cfbfc11..82867a0 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -327,8 +327,6 @@ struct pn533 { struct nfc_dev *nfc_dev; struct urb *out_urb; - struct pn533_frame *out_frame; - struct urb *in_urb; struct sk_buff_head resp_q; @@ -2427,10 +2425,9 @@ static int pn533_probe(struct usb_interface *interface, } dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); - dev->out_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->out_frame || !dev->in_urb || !dev->out_urb) + if (!dev->in_urb || !dev->out_urb) goto error; usb_fill_bulk_urb(dev->in_urb, dev->udev, @@ -2515,7 +2512,6 @@ destroy_wq: destroy_workqueue(dev->wq); error: usb_free_urb(dev->in_urb); - kfree(dev->out_frame); usb_free_urb(dev->out_urb); kfree(dev); return rc; @@ -2547,7 +2543,6 @@ static void pn533_disconnect(struct usb_interface *interface) } usb_free_urb(dev->in_urb); - kfree(dev->out_frame); usb_free_urb(dev->out_urb); kfree(dev); -- cgit v0.10.2 From 0c33d2626d651f3f52d6a1e8b612e2830a4ab71f Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:42:59 +0100 Subject: NFC: pn533: Cleanup pn533_cmd_complete_t 'params' arg in pn533_cmd_complete_t definition has been deprecated and currently is not in use (resp skb is pass in arg ptr), so remove it. Also 'params_len' arg is used as a transfer status indicator, so simply reword it appropriately. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 82867a0..db13cd7 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -109,8 +109,6 @@ MODULE_DEVICE_TABLE(usb, pn533_table); /* PN533 Commands */ #define PN533_FRAME_CMD(f) (f->data[1]) -#define PN533_FRAME_CMD_PARAMS_PTR(f) (&f->data[2]) -#define PN533_FRAME_CMD_PARAMS_LEN(f) (f->datalen - 2) #define PN533_CMD_GET_FIRMWARE_VERSION 0x02 #define PN533_CMD_RF_CONFIGURATION 0x32 @@ -135,8 +133,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table); struct pn533; -typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, - u8 *params, int params_len); +typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, int status); typedef int (*pn533_send_async_complete_t) (struct pn533 *dev, void *arg, struct sk_buff *resp); @@ -458,19 +455,9 @@ static bool pn533_rx_frame_is_cmd_response(struct pn533_frame *frame, u8 cmd) static void pn533_wq_cmd_complete(struct work_struct *work) { struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work); - struct pn533_frame *in_frame; int rc; - in_frame = dev->wq_in_frame; - - if (dev->wq_in_error) - rc = dev->cmd_complete(dev, dev->cmd_complete_arg, NULL, - dev->wq_in_error); - else - rc = dev->cmd_complete(dev, dev->cmd_complete_arg, - PN533_FRAME_CMD_PARAMS_PTR(in_frame), - PN533_FRAME_CMD_PARAMS_LEN(in_frame)); - + rc = dev->cmd_complete(dev, dev->cmd_complete_arg, dev->wq_in_error); if (rc != -EINPROGRESS) queue_work(dev->wq, &dev->cmd_work); } @@ -664,8 +651,7 @@ struct pn533_send_async_complete_arg { struct sk_buff *req; }; -static int pn533_send_async_complete(struct pn533 *dev, void *_arg, u8 *params, - int params_len) +static int pn533_send_async_complete(struct pn533 *dev, void *_arg, int status) { struct pn533_send_async_complete_arg *arg = _arg; @@ -677,12 +663,12 @@ static int pn533_send_async_complete(struct pn533 *dev, void *_arg, u8 *params, dev_kfree_skb(req); - if (params_len < 0) { + if (status < 0) { arg->complete_cb(dev, arg->complete_cb_context, - ERR_PTR(params_len)); - rc = params_len; + ERR_PTR(status)); dev_kfree_skb(resp); - goto out; + kfree(arg); + return status; } skb_put(resp, PN533_FRAME_SIZE(frame)); @@ -691,7 +677,6 @@ static int pn533_send_async_complete(struct pn533 *dev, void *_arg, u8 *params, rc = arg->complete_cb(dev, arg->complete_cb_context, resp); -out: kfree(arg); return rc; } -- cgit v0.10.2 From 16f7541914e8bee0e76c510c4d8bc5ad8a5edf00 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:43:00 +0100 Subject: NFC: pn533: Remove unused dev->wq_in_frame Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index db13cd7..58f7f2c 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -335,7 +335,6 @@ struct pn533 { 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; @@ -467,8 +466,6 @@ static void pn533_recv_response(struct urb *urb) struct pn533 *dev = urb->context; struct pn533_frame *in_frame; - dev->wq_in_frame = NULL; - switch (urb->status) { case 0: break; /* success */ @@ -508,7 +505,6 @@ static void pn533_recv_response(struct urb *urb) } dev->wq_in_error = 0; - dev->wq_in_frame = in_frame; sched_wq: queue_work(dev->wq, &dev->cmd_complete_work); @@ -565,7 +561,6 @@ static void pn533_recv_ack(struct urb *urb) return; sched_wq: - dev->wq_in_frame = NULL; queue_work(dev->wq, &dev->cmd_complete_work); } -- cgit v0.10.2 From 9e2d493e74aca105aa86de56dbf80a0a654c4c53 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Mon, 10 Dec 2012 14:43:01 +0100 Subject: NFC: pn533: Introduce ops for frame logic Encapsulate whole frame logic (tx/rx frame structure and size) inside the ops structure to make the core driver generic for devices which handle frames in non standard menner (different then pn533 spec say). Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 58f7f2c..e8c0832 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -79,9 +79,6 @@ MODULE_DEVICE_TABLE(usb, pn533_table); #define PN533_LISTEN_TIME 2 /* frame definitions */ -#define PN533_NORMAL_FRAME_MAX_LEN 262 /* 6 (PREAMBLE, SOF, LEN, LCS, TFI) - 254 (DATA) - 2 (DCS, postamble) */ #define PN533_FRAME_HEADER_LEN (sizeof(struct pn533_frame) \ + 2) /* data[0] TFI, data[1] CC */ #define PN533_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/ @@ -92,8 +89,6 @@ MODULE_DEVICE_TABLE(usb, pn533_table); */ #define PN533_FRAME_MAX_PAYLOAD_LEN 263 -#define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ - PN533_FRAME_TAIL_LEN) #define PN533_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2), Postamble (1) */ #define PN533_FRAME_CHECKSUM(f) (f->data[f->datalen]) @@ -361,6 +356,8 @@ struct pn533 { struct list_head cmd_queue; u8 cmd_pending; + + struct pn533_frame_ops *ops; }; struct pn533_cmd { @@ -368,6 +365,7 @@ struct pn533_cmd { u8 cmd_code; struct sk_buff *req; struct sk_buff *resp; + int resp_len; void *arg; }; @@ -379,6 +377,22 @@ struct pn533_frame { u8 data[]; } __packed; +struct pn533_frame_ops { + void (*tx_frame_init)(void *frame, u8 cmd_code); + void (*tx_frame_finish)(void *frame); + void (*tx_update_payload_len)(void *frame, int len); + int tx_header_len; + int tx_tail_len; + + bool (*rx_is_frame_valid)(void *frame); + int (*rx_frame_size)(void *frame); + int rx_header_len; + int rx_tail_len; + + int max_payload_len; + u8 (*get_cmd_code)(void *frame); +}; + /* The rule: value + checksum = 0 */ static inline u8 pn533_checksum(u8 value) { @@ -397,17 +411,21 @@ static u8 pn533_data_checksum(u8 *data, int datalen) return pn533_checksum(sum); } -static void pn533_tx_frame_init(struct pn533_frame *frame, u8 cmd) +static void pn533_tx_frame_init(void *_frame, u8 cmd_code) { + struct pn533_frame *frame = _frame; + frame->preamble = 0; frame->start_frame = cpu_to_be16(PN533_SOF); PN533_FRAME_IDENTIFIER(frame) = PN533_DIR_OUT; - PN533_FRAME_CMD(frame) = cmd; + PN533_FRAME_CMD(frame) = cmd_code; frame->datalen = 2; } -static void pn533_tx_frame_finish(struct pn533_frame *frame) +static void pn533_tx_frame_finish(void *_frame) { + struct pn533_frame *frame = _frame; + frame->datalen_checksum = pn533_checksum(frame->datalen); PN533_FRAME_CHECKSUM(frame) = @@ -416,9 +434,17 @@ static void pn533_tx_frame_finish(struct pn533_frame *frame) PN533_FRAME_POSTAMBLE(frame) = 0; } -static bool pn533_rx_frame_is_valid(struct pn533_frame *frame) +static void pn533_tx_update_payload_len(void *_frame, int len) +{ + struct pn533_frame *frame = _frame; + + frame->datalen += len; +} + +static bool pn533_rx_frame_is_valid(void *_frame) { u8 checksum; + struct pn533_frame *frame = _frame; if (frame->start_frame != cpu_to_be16(PN533_SOF)) return false; @@ -445,9 +471,39 @@ static bool pn533_rx_frame_is_ack(struct pn533_frame *frame) return true; } -static bool pn533_rx_frame_is_cmd_response(struct pn533_frame *frame, u8 cmd) +static inline int pn533_rx_frame_size(void *frame) +{ + struct pn533_frame *f = frame; + + return sizeof(struct pn533_frame) + f->datalen + PN533_FRAME_TAIL_LEN; +} + +static u8 pn533_get_cmd_code(void *frame) +{ + struct pn533_frame *f = frame; + + return PN533_FRAME_CMD(f); +} + +struct pn533_frame_ops pn533_std_frame_ops = { + .tx_frame_init = pn533_tx_frame_init, + .tx_frame_finish = pn533_tx_frame_finish, + .tx_update_payload_len = pn533_tx_update_payload_len, + .tx_header_len = PN533_FRAME_HEADER_LEN, + .tx_tail_len = PN533_FRAME_TAIL_LEN, + + .rx_is_frame_valid = pn533_rx_frame_is_valid, + .rx_frame_size = pn533_rx_frame_size, + .rx_header_len = PN533_FRAME_HEADER_LEN, + .rx_tail_len = PN533_FRAME_TAIL_LEN, + + .max_payload_len = PN533_FRAME_MAX_PAYLOAD_LEN, + .get_cmd_code = pn533_get_cmd_code, +}; + +static bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame) { - return (PN533_FRAME_CMD(frame) == PN533_CMD_RESPONSE(cmd)); + return (dev->ops->get_cmd_code(frame) == PN533_CMD_RESPONSE(dev->cmd)); } @@ -464,7 +520,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work) static void pn533_recv_response(struct urb *urb) { struct pn533 *dev = urb->context; - struct pn533_frame *in_frame; + u8 *in_frame; switch (urb->status) { case 0: @@ -489,15 +545,15 @@ static void pn533_recv_response(struct urb *urb) nfc_dev_dbg(&dev->interface->dev, "Received a frame."); print_hex_dump(KERN_DEBUG, "PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, - in_frame, PN533_FRAME_SIZE(in_frame), false); + in_frame, dev->ops->rx_frame_size(in_frame), false); - if (!pn533_rx_frame_is_valid(in_frame)) { + if (!dev->ops->rx_is_frame_valid(in_frame)) { nfc_dev_err(&dev->interface->dev, "Received an invalid frame"); dev->wq_in_error = -EIO; goto sched_wq; } - if (!pn533_rx_frame_is_cmd_response(in_frame, dev->cmd)) { + if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) { nfc_dev_err(&dev->interface->dev, "It it not the response to the last command"); dev->wq_in_error = -EIO; @@ -595,7 +651,7 @@ static int __pn533_send_frame_async(struct pn533 *dev, { int rc; - dev->cmd = PN533_FRAME_CMD(((struct pn533_frame *)out->data)); + dev->cmd = dev->ops->get_cmd_code(out->data); dev->cmd_complete = cmd_complete; dev->cmd_complete_arg = arg; @@ -623,20 +679,20 @@ error: return rc; } -static void pn533_build_cmd_frame(u8 cmd_code, struct sk_buff *skb) +static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code, + struct sk_buff *skb) { - struct pn533_frame *frame; /* payload is already there, just update datalen */ int payload_len = skb->len; + struct pn533_frame_ops *ops = dev->ops; - skb_push(skb, PN533_FRAME_HEADER_LEN); - skb_put(skb, PN533_FRAME_TAIL_LEN); - frame = (struct pn533_frame *)skb->data; + skb_push(skb, ops->tx_header_len); + skb_put(skb, ops->tx_tail_len); - pn533_tx_frame_init(frame, cmd_code); - frame->datalen += payload_len; - pn533_tx_frame_finish(frame); + ops->tx_frame_init(skb->data, cmd_code); + ops->tx_update_payload_len(skb->data, payload_len); + ops->tx_frame_finish(skb->data); } struct pn533_send_async_complete_arg { @@ -653,7 +709,6 @@ static int pn533_send_async_complete(struct pn533 *dev, void *_arg, int status) struct sk_buff *req = arg->req; struct sk_buff *resp = arg->resp; - struct pn533_frame *frame = (struct pn533_frame *)resp->data; int rc; dev_kfree_skb(req); @@ -666,9 +721,9 @@ static int pn533_send_async_complete(struct pn533 *dev, void *_arg, int status) return status; } - skb_put(resp, PN533_FRAME_SIZE(frame)); - skb_pull(resp, PN533_FRAME_HEADER_LEN); - skb_trim(resp, resp->len - PN533_FRAME_TAIL_LEN); + skb_put(resp, dev->ops->rx_frame_size(resp->data)); + skb_pull(resp, dev->ops->rx_header_len); + skb_trim(resp, resp->len - dev->ops->rx_tail_len); rc = arg->complete_cb(dev, arg->complete_cb_context, resp); @@ -697,7 +752,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, arg->resp = resp; arg->req = req; - pn533_build_cmd_frame(cmd_code, req); + pn533_build_cmd_frame(dev, cmd_code, req); mutex_lock(&dev->cmd_lock); @@ -724,6 +779,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, cmd->cmd_code = cmd_code; cmd->req = req; cmd->resp = resp; + cmd->resp_len = resp_len; cmd->arg = arg; list_add_tail(&cmd->queue, &dev->cmd_queue); @@ -744,9 +800,9 @@ static int pn533_send_data_async(struct pn533 *dev, u8 cmd_code, { struct sk_buff *resp; int rc; - int resp_len = PN533_FRAME_HEADER_LEN + - PN533_FRAME_MAX_PAYLOAD_LEN + - PN533_FRAME_TAIL_LEN; + int resp_len = dev->ops->rx_header_len + + dev->ops->max_payload_len + + dev->ops->rx_tail_len; resp = nfc_alloc_recv_skb(resp_len, GFP_KERNEL); if (!resp) @@ -767,14 +823,16 @@ static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, { struct sk_buff *resp; int rc; + int resp_len = dev->ops->rx_header_len + + dev->ops->max_payload_len + + dev->ops->rx_tail_len; - resp = alloc_skb(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); + resp = alloc_skb(resp_len, GFP_KERNEL); if (!resp) return -ENOMEM; - rc = __pn533_send_async(dev, cmd_code, req, resp, - PN533_NORMAL_FRAME_MAX_LEN, - complete_cb, complete_cb_context); + rc = __pn533_send_async(dev, cmd_code, req, resp, resp_len, complete_cb, + complete_cb_context); if (rc) dev_kfree_skb(resp); @@ -797,9 +855,9 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, struct pn533_send_async_complete_arg *arg; struct sk_buff *resp; int rc; - int resp_len = PN533_FRAME_HEADER_LEN + - PN533_FRAME_MAX_PAYLOAD_LEN + - PN533_FRAME_TAIL_LEN; + int resp_len = dev->ops->rx_header_len + + dev->ops->max_payload_len + + dev->ops->rx_tail_len; resp = alloc_skb(resp_len, GFP_KERNEL); if (!resp) @@ -816,7 +874,7 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, arg->resp = resp; arg->req = req; - pn533_build_cmd_frame(cmd_code, req); + pn533_build_cmd_frame(dev, cmd_code, req); rc = __pn533_send_frame_async(dev, req, resp, resp_len, pn533_send_async_complete, arg); @@ -847,10 +905,8 @@ static void pn533_wq_cmd(struct work_struct *work) mutex_unlock(&dev->cmd_lock); - __pn533_send_frame_async(dev, cmd->req, cmd->resp, - PN533_NORMAL_FRAME_MAX_LEN, - pn533_send_async_complete, - cmd->arg); + __pn533_send_frame_async(dev, cmd->req, cmd->resp, cmd->resp_len, + pn533_send_async_complete, cmd->arg); kfree(cmd); } @@ -928,16 +984,16 @@ static void pn533_send_complete(struct urb *urb) } } -static struct sk_buff *pn533_alloc_skb(unsigned int size) +static struct sk_buff *pn533_alloc_skb(struct pn533 *dev, unsigned int size) { struct sk_buff *skb; - skb = alloc_skb(PN533_FRAME_HEADER_LEN + + skb = alloc_skb(dev->ops->tx_header_len + size + - PN533_FRAME_TAIL_LEN, GFP_KERNEL); + dev->ops->tx_tail_len, GFP_KERNEL); if (skb) - skb_reserve(skb, PN533_FRAME_HEADER_LEN); + skb_reserve(skb, dev->ops->tx_header_len); return skb; } @@ -1297,11 +1353,14 @@ static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) return -EAGAIN; } -static struct sk_buff *pn533_alloc_poll_tg_frame(u8 *gbytes, size_t gbytes_len) +static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) { struct sk_buff *skb; u8 *felica, *nfcid3, *gb; + u8 *gbytes = dev->gb; + size_t gbytes_len = dev->gb_len; + u8 felica_params[18] = {0x1, 0xfe, /* DEP */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -1316,7 +1375,7 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(u8 *gbytes, size_t gbytes_len) gbytes_len + 1; /* len Tk*/ - skb = pn533_alloc_skb(skb_len); + skb = pn533_alloc_skb(dev, skb_len); if (!skb) return NULL; @@ -1382,7 +1441,7 @@ static void pn533_wq_tg_get_data(struct work_struct *work) nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - skb = pn533_alloc_skb(0); + skb = pn533_alloc_skb(dev, 0); if (!skb) return; @@ -1507,12 +1566,12 @@ stop_poll: return rc; } -static struct sk_buff *pn533_alloc_poll_in_frame(struct pn533_poll_modulations - *mod) +static struct sk_buff *pn533_alloc_poll_in_frame(struct pn533 *dev, + struct pn533_poll_modulations *mod) { struct sk_buff *skb; - skb = pn533_alloc_skb(mod->len); + skb = pn533_alloc_skb(dev, mod->len); if (!skb) return NULL; @@ -1535,10 +1594,10 @@ static int pn533_send_poll_frame(struct pn533 *dev) if (mod->len == 0) { /* Listen mode */ cmd_code = PN533_CMD_TG_INIT_AS_TARGET; - skb = pn533_alloc_poll_tg_frame(dev->gb, dev->gb_len); + skb = pn533_alloc_poll_tg_frame(dev); } else { /* Polling mode */ cmd_code = PN533_CMD_IN_LIST_PASSIVE_TARGET; - skb = pn533_alloc_poll_in_frame(mod); + skb = pn533_alloc_poll_in_frame(dev, mod); } if (!skb) { @@ -1652,7 +1711,7 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - skb = pn533_alloc_skb(sizeof(u8) * 2); /*TG + Next*/ + skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/ if (!skb) return -ENOMEM; @@ -1746,7 +1805,7 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, dev->tgt_active_prot = 0; skb_queue_purge(&dev->resp_q); - skb = pn533_alloc_skb(sizeof(u8)); + skb = pn533_alloc_skb(dev, sizeof(u8)); if (!skb) return; @@ -1877,7 +1936,7 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, if (comm_mode == NFC_COMM_PASSIVE) skb_len += PASSIVE_DATA_LEN; - skb = pn533_alloc_skb(skb_len); + skb = pn533_alloc_skb(dev, skb_len); if (!skb) return -ENOMEM; @@ -2161,7 +2220,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - skb = pn533_alloc_skb(PN533_CMD_DATAEXCH_HEAD_LEN); + skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN); if (!skb) goto error; @@ -2214,7 +2273,7 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ - skb = pn533_alloc_skb(skb_len); + skb = pn533_alloc_skb(dev, skb_len); if (!skb) return -ENOMEM; @@ -2235,7 +2294,7 @@ static int pn533_get_firmware_version(struct pn533 *dev, struct sk_buff *skb; struct sk_buff *resp; - skb = pn533_alloc_skb(0); + skb = pn533_alloc_skb(dev, 0); if (!skb) return -ENOMEM; @@ -2259,7 +2318,7 @@ static int pn533_fw_reset(struct pn533 *dev) nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - skb = pn533_alloc_skb(sizeof(u8)); + skb = pn533_alloc_skb(dev, sizeof(u8)); if (!skb) return -ENOMEM; @@ -2436,14 +2495,7 @@ static int pn533_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); - memset(&fw_ver, 0, sizeof(fw_ver)); - rc = pn533_get_firmware_version(dev, &fw_ver); - if (rc < 0) - goto destroy_wq; - - nfc_dev_info(&dev->interface->dev, - "NXP PN533 firmware ver %d.%d now attached", - fw_ver.ver, fw_ver.rev); + dev->ops = &pn533_std_frame_ops; dev->device_type = id->driver_info; switch (dev->device_type) { @@ -2462,10 +2514,20 @@ static int pn533_probe(struct usb_interface *interface, goto destroy_wq; } + memset(&fw_ver, 0, sizeof(fw_ver)); + rc = pn533_get_firmware_version(dev, &fw_ver); + if (rc < 0) + goto destroy_wq; + + nfc_dev_info(&dev->interface->dev, + "NXP PN533 firmware ver %d.%d now attached", + fw_ver.ver, fw_ver.rev); + + dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, - PN533_FRAME_HEADER_LEN + + dev->ops->tx_header_len + PN533_CMD_DATAEXCH_HEAD_LEN, - PN533_FRAME_TAIL_LEN); + dev->ops->tx_tail_len); if (!dev->nfc_dev) goto destroy_wq; -- cgit v0.10.2 From 5f4d6214ef5e9b1ff6a72ddfa387c1d72adfac98 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 6 Dec 2012 23:10:40 +0100 Subject: NFC: nfcwilink: Use devm_kzalloc devm_kzalloc allocates memory that is released when a driver detaches. This patch uses devm_kzalloc for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index 50b1ee4..c7c182d 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c @@ -526,7 +526,7 @@ static int nfcwilink_probe(struct platform_device *pdev) nfc_dev_dbg(&pdev->dev, "probe entry"); - drv = kzalloc(sizeof(struct nfcwilink), GFP_KERNEL); + drv = devm_kzalloc(&pdev->dev, sizeof(struct nfcwilink), GFP_KERNEL); if (!drv) { rc = -ENOMEM; goto exit; @@ -547,7 +547,7 @@ static int nfcwilink_probe(struct platform_device *pdev) if (!drv->ndev) { nfc_dev_err(&pdev->dev, "nci_allocate_device failed"); rc = -ENOMEM; - goto free_exit; + goto exit; } nci_set_parent_dev(drv->ndev, &pdev->dev); @@ -566,9 +566,6 @@ static int nfcwilink_probe(struct platform_device *pdev) free_dev_exit: nci_free_device(drv->ndev); -free_exit: - kfree(drv); - exit: return rc; } @@ -588,8 +585,6 @@ static int nfcwilink_remove(struct platform_device *pdev) nci_unregister_device(ndev); nci_free_device(ndev); - kfree(drv); - dev_set_drvdata(&pdev->dev, NULL); return 0; -- cgit v0.10.2 From f0c9103813b3045bd5b43220b6a78c9908a45d24 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Mon, 26 Nov 2012 18:06:27 +0100 Subject: NFC: Fixed nfc core and hci unregistration and cleanup When an adapter is removed, it will unregister itself from hci and/or nfc core. In order to do that safely, work tasks must first be canceled and prevented to be scheduled again, before the hci or nfc device can be destroyed. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 671953e..e622457 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h @@ -87,6 +87,8 @@ struct nfc_hci_dev { u32 max_data_link_payload; + bool shutting_down; + struct mutex msg_tx_mutex; struct list_head msg_tx_queue; diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index fce80b2..1665674 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -115,6 +115,8 @@ struct nfc_dev { struct timer_list check_pres_timer; struct work_struct check_pres_work; + bool shutting_down; + struct nfc_ops *ops; }; #define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev) diff --git a/net/nfc/core.c b/net/nfc/core.c index aa64ea4..7d7b4ee 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -338,7 +338,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) dev->active_target = target; dev->rf_mode = NFC_RF_INITIATOR; - if (dev->ops->check_presence) + if (dev->ops->check_presence && !dev->shutting_down) mod_timer(&dev->check_pres_timer, jiffies + msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); } @@ -429,7 +429,7 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, cb_context); - if (!rc && dev->ops->check_presence) + if (!rc && dev->ops->check_presence && !dev->shutting_down) mod_timer(&dev->check_pres_timer, jiffies + msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { @@ -684,11 +684,6 @@ static void nfc_release(struct device *d) pr_debug("dev_name=%s\n", dev_name(&dev->dev)); - if (dev->ops->check_presence) { - del_timer_sync(&dev->check_pres_timer); - cancel_work_sync(&dev->check_pres_work); - } - nfc_genl_data_exit(&dev->genl_data); kfree(dev->targets); kfree(dev); @@ -706,15 +701,16 @@ static void nfc_check_pres_work(struct work_struct *work) rc = dev->ops->check_presence(dev, dev->active_target); if (rc == -EOPNOTSUPP) goto exit; - if (!rc) { - mod_timer(&dev->check_pres_timer, jiffies + - msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); - } else { + if (rc) { u32 active_target_idx = dev->active_target->idx; device_unlock(&dev->dev); nfc_target_lost(dev, active_target_idx); return; } + + if (!dev->shutting_down) + mod_timer(&dev->check_pres_timer, jiffies + + msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); } exit: @@ -853,26 +849,27 @@ void nfc_unregister_device(struct nfc_dev *dev) id = dev->idx; - mutex_lock(&nfc_devlist_mutex); - nfc_devlist_generation++; - - /* lock to avoid unregistering a device while an operation - is in progress */ - device_lock(&dev->dev); - device_del(&dev->dev); - device_unlock(&dev->dev); + if (dev->ops->check_presence) { + device_lock(&dev->dev); + dev->shutting_down = true; + device_unlock(&dev->dev); + del_timer_sync(&dev->check_pres_timer); + cancel_work_sync(&dev->check_pres_work); + } - mutex_unlock(&nfc_devlist_mutex); + rc = nfc_genl_device_removed(dev); + if (rc) + pr_debug("The userspace won't be notified that the device %s " + "was removed\n", dev_name(&dev->dev)); nfc_llcp_unregister_device(dev); - rc = nfc_genl_device_removed(dev); - if (rc) - pr_debug("The userspace won't be notified that the device %s was removed\n", - dev_name(&dev->dev)); + mutex_lock(&nfc_devlist_mutex); + nfc_devlist_generation++; + device_del(&dev->dev); + mutex_unlock(&nfc_devlist_mutex); ida_simple_remove(&nfc_index_ida, id); - } EXPORT_SYMBOL(nfc_unregister_device); diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 7bea574..b4b8426 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -57,6 +57,8 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) int r = 0; mutex_lock(&hdev->msg_tx_mutex); + if (hdev->shutting_down) + goto exit; if (hdev->cmd_pending_msg) { if (timer_pending(&hdev->cmd_timer) == 0) { @@ -868,6 +870,28 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) { struct hci_msg *msg, *n; + mutex_lock(&hdev->msg_tx_mutex); + + if (hdev->cmd_pending_msg) { + if (hdev->cmd_pending_msg->cb) + hdev->cmd_pending_msg->cb( + hdev->cmd_pending_msg->cb_context, + NULL, -ESHUTDOWN); + kfree(hdev->cmd_pending_msg); + hdev->cmd_pending_msg = NULL; + } + + hdev->shutting_down = true; + + mutex_unlock(&hdev->msg_tx_mutex); + + del_timer_sync(&hdev->cmd_timer); + cancel_work_sync(&hdev->msg_tx_work); + + cancel_work_sync(&hdev->msg_rx_work); + + nfc_unregister_device(hdev->ndev); + skb_queue_purge(&hdev->rx_hcp_frags); skb_queue_purge(&hdev->msg_rx_queue); @@ -876,13 +900,6 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) skb_queue_purge(&msg->msg_frags); kfree(msg); } - - del_timer_sync(&hdev->cmd_timer); - - nfc_unregister_device(hdev->ndev); - - cancel_work_sync(&hdev->msg_tx_work); - cancel_work_sync(&hdev->msg_rx_work); } EXPORT_SYMBOL(nfc_hci_unregister_device); diff --git a/net/nfc/hci/hcp.c b/net/nfc/hci/hcp.c index bc308a7..b6b4109 100644 --- a/net/nfc/hci/hcp.c +++ b/net/nfc/hci/hcp.c @@ -105,6 +105,13 @@ int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, } mutex_lock(&hdev->msg_tx_mutex); + + if (hdev->shutting_down) { + err = -ESHUTDOWN; + mutex_unlock(&hdev->msg_tx_mutex); + goto out_skb_err; + } + list_add_tail(&cmd->msg_l, &hdev->msg_tx_queue); mutex_unlock(&hdev->msg_tx_mutex); -- cgit v0.10.2 From 27c31191b3d7ff32c266a5dbea344b9aa96ebf14 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Wed, 28 Nov 2012 15:48:44 +0100 Subject: NFC: Added error handling in event_received hci ops There is no use to return an error if the caller doesn't get it. Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index cc666de..4af70f9 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -714,8 +714,8 @@ static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, return 0; } -static void pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, - u8 event, struct sk_buff *skb) +static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, + struct sk_buff *skb) { struct sk_buff *rgb_skb = NULL; int r = 0; @@ -724,25 +724,23 @@ static void pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, switch (event) { case PN544_HCI_EVT_ACTIVATED: if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) - nfc_hci_target_discovered(hdev, gate); + r = nfc_hci_target_discovered(hdev, gate); else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, - &rgb_skb); - + &rgb_skb); if (r < 0) goto exit; - nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, - NFC_COMM_PASSIVE, rgb_skb->data, - rgb_skb->len); + r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, + NFC_COMM_PASSIVE, rgb_skb->data, + rgb_skb->len); kfree_skb(rgb_skb); } - break; case PN544_HCI_EVT_DEACTIVATED: - nfc_hci_send_event(hdev, gate, - NFC_HCI_EVT_END_OPERATION, NULL, 0); + r = nfc_hci_send_event(hdev, gate, NFC_HCI_EVT_END_OPERATION, + NULL, 0); break; case PN544_HCI_EVT_RCV_DATA: if (skb->len < 2) { @@ -757,15 +755,16 @@ static void pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, } skb_pull(skb, 2); - nfc_tm_data_received(hdev->ndev, skb); - - return; + return nfc_tm_data_received(hdev->ndev, skb); default: + pr_err("Discarded unknown event %x to gate %x\n", event, gate); break; } exit: kfree_skb(skb); + + return r; } static struct nfc_hci_ops pn544_hci_ops = { diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index e622457..834e364 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h @@ -57,8 +57,8 @@ struct nfc_hci_ops { int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); int (*check_presence)(struct nfc_hci_dev *hdev, struct nfc_target *target); - void (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, - struct sk_buff *skb); + int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, + struct sk_buff *skb); }; /* Pipes */ diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index b4b8426..f30f6fe 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -323,16 +323,18 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, break; default: if (hdev->ops->event_received) { - hdev->ops->event_received(hdev, gate, event, skb); - return; + r = hdev->ops->event_received(hdev, gate, event, skb); + goto exit_noskb; + } else { + r = -EINVAL; } - break; } exit: kfree_skb(skb); +exit_noskb: if (r) { /* TODO: There was an error dispatching the event, * how to propagate up to nfc core? -- cgit v0.10.2 From 40d06d3647ea872a7346be1f6859f18cd0fe08d3 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Tue, 4 Dec 2012 16:43:24 +0100 Subject: NFC: Changed event_received hci ops result semantic Some chips use a standard HCI event code, destined to a proprietary gate, with a different meaning. Therefore, the HCI driver must always have a chance to intercept the event before standard processing is attempted. The new semantic specifies that the result value "1" means that the driver doesn't especially handle the event. result <= 0 means it was handled. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 4af70f9..9349c54 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -714,18 +714,23 @@ static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, return 0; } +/* + * Returns: + * <= 0: driver handled the event, skb consumed + * 1: driver does not handle the event, please do standard processing + */ static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, struct sk_buff *skb) { struct sk_buff *rgb_skb = NULL; - int r = 0; + int r; pr_debug("hci event %d", event); switch (event) { case PN544_HCI_EVT_ACTIVATED: - if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) + if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) { r = nfc_hci_target_discovered(hdev, gate); - else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { + } else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, &rgb_skb); if (r < 0) @@ -736,6 +741,8 @@ static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, rgb_skb->len); kfree_skb(rgb_skb); + } else { + r = -EINVAL; } break; case PN544_HCI_EVT_DEACTIVATED: @@ -757,8 +764,7 @@ static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, skb_pull(skb, 2); return nfc_tm_data_received(hdev->ndev, skb); default: - pr_err("Discarded unknown event %x to gate %x\n", event, gate); - break; + return 1; } exit: diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index f30f6fe..0430f30 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -297,6 +297,12 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, goto exit; } + if (hdev->ops->event_received) { + r = hdev->ops->event_received(hdev, gate, event, skb); + if (r <= 0) + goto exit_noskb; + } + switch (event) { case NFC_HCI_EVT_TARGET_DISCOVERED: if (skb->len < 1) { /* no status data? */ @@ -322,12 +328,8 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, r = nfc_hci_target_discovered(hdev, gate); break; default: - if (hdev->ops->event_received) { - r = hdev->ops->event_received(hdev, gate, event, skb); - goto exit_noskb; - } else { - r = -EINVAL; - } + pr_info("Discarded unknown event %x to gate %x\n", event, gate); + r = -EINVAL; break; } -- cgit v0.10.2 From 924d4a023ee6da2e40c78578829e68bcbabee2dd Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Tue, 4 Dec 2012 16:44:25 +0100 Subject: NFC: Fixed skb leak in tm_send() nfc and hci ops implementations Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 9349c54..cd8fb16 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -675,11 +675,17 @@ static int pn544_hci_im_transceive(struct nfc_hci_dev *hdev, static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) { + int r; + /* Set default false for multiple information chaining */ *skb_push(skb, 1) = 0; - return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, - PN544_HCI_EVT_SND_DATA, skb->data, skb->len); + r = nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, + PN544_HCI_EVT_SND_DATA, skb->data, skb->len); + + kfree_skb(skb); + + return r; } static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 0430f30..d9190da 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -675,8 +675,10 @@ static int hci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) if (hdev->ops->tm_send) return hdev->ops->tm_send(hdev, skb); - else - return -ENOTSUPP; + + kfree_skb(skb); + + return -ENOTSUPP; } static int hci_check_presence(struct nfc_dev *nfc_dev, -- cgit v0.10.2 From bf71ab8ba53081c28b960d48e0c4cd1c17588aa6 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Tue, 18 Dec 2012 14:15:49 +0100 Subject: NFC: Add HCI quirks to support driver (non)standard implementations Some chips diverge from the HCI spec in their implementation of standard features. This adds a new quirks parameter to nfc_hci_allocate_device() to let the driver indicate its divergence. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index cd8fb16..ece8342 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -833,7 +833,7 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_NFC_DEP_MASK; - info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, + info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, 0, protocols, llc_name, phy_headroom + PN544_CMDS_HEADROOM, phy_tailroom, phy_payload); diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 834e364..2ff7175 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h @@ -82,6 +82,16 @@ typedef int (*xmit) (struct sk_buff *skb, void *cb_data); #define NFC_HCI_MAX_GATES 256 +/* + * These values can be specified by a driver to indicate it requires some + * adaptation of the HCI standard. + * + * NFC_HCI_QUIRK_SHORT_CLEAR - send HCI_ADM_CLEAR_ALL_PIPE cmd with no params + */ +enum { + NFC_HCI_QUIRK_SHORT_CLEAR = 0, +}; + struct nfc_hci_dev { struct nfc_dev *ndev; @@ -131,11 +141,14 @@ struct nfc_hci_dev { u8 *gb; size_t gb_len; + + unsigned long quirks; }; /* hci device allocation */ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, struct nfc_hci_init_data *init_data, + unsigned long quirks, u32 protocols, const char *llc_name, int tx_headroom, diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 7d99410..64f922b 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c @@ -280,14 +280,19 @@ static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) { u8 param[2]; + size_t param_len = 2; /* TODO: Find out what the identity reference data is * and fill param with it. HCI spec 6.1.3.5 */ pr_debug("\n"); + if (test_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &hdev->quirks)) + param_len = 0; + return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, - NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL); + NFC_HCI_ADM_CLEAR_ALL_PIPE, param, param_len, + NULL); } int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index d9190da..755a6b9 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -795,6 +795,7 @@ static struct nfc_ops hci_nfc_ops = { struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, struct nfc_hci_init_data *init_data, + unsigned long quirks, u32 protocols, const char *llc_name, int tx_headroom, @@ -838,6 +839,8 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); + hdev->quirks = quirks; + return hdev; } EXPORT_SYMBOL(nfc_hci_allocate_device); -- cgit v0.10.2 From aa74103071312fede1f4953fe3c027941add1256 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 18 Dec 2012 16:26:23 +0100 Subject: NFC: pn544: Separate the core code and the i2c one into different modules As we may need to support other physical layers, we can avoid linking the core part into each and every pn544 module. Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index ec85767..80c728b 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig @@ -5,19 +5,6 @@ menu "Near Field Communication (NFC) devices" depends on NFC -config PN544_HCI_NFC - tristate "HCI PN544 NFC driver" - depends on I2C && NFC_HCI && NFC_SHDLC - select CRC_CCITT - default n - ---help--- - NXP PN544 i2c driver. - This is a driver based on the SHDLC and HCI NFC kernel layers and - will thus not work with NXP libnfc library. - - To compile this driver as a module, choose m here. The module will - be called pn544_hci. - config NFC_PN533 tristate "NXP PN533 USB driver" depends on USB @@ -39,4 +26,6 @@ config NFC_WILINK Say Y here to compile support for Texas Instrument's NFC WiLink driver into the kernel or say M to compile it as module. +source "drivers/nfc/pn544/Kconfig" + endmenu diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index 36c3590..574bbc0 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile @@ -2,7 +2,7 @@ # Makefile for nfc devices # -obj-$(CONFIG_PN544_HCI_NFC) += pn544/ +obj-$(CONFIG_NFC_PN544) += pn544/ obj-$(CONFIG_NFC_PN533) += pn533.o obj-$(CONFIG_NFC_WILINK) += nfcwilink.o diff --git a/drivers/nfc/pn544/Kconfig b/drivers/nfc/pn544/Kconfig new file mode 100644 index 0000000..c277790 --- /dev/null +++ b/drivers/nfc/pn544/Kconfig @@ -0,0 +1,23 @@ +config NFC_PN544 + tristate "NXP PN544 NFC driver" + depends on NFC_HCI + select CRC_CCITT + default n + ---help--- + NXP PN544 core driver. + This is a driver based on the HCI NFC kernel layers and + will thus not work with NXP libnfc library. + + To compile this driver as a module, choose m here. The module will + be called pn544. + Say N if unsure. + +config NFC_PN544_I2C + tristate "NFC PN544 i2c support" + depends on NFC_PN544 && I2C && NFC_SHDLC + ---help--- + This module adds support for the NXP pn544 i2c interface. + Select this if your platform is using the i2c bus. + + If you choose to build a module, it'll be called pn544_i2c. + Say N if unsure. \ No newline at end of file diff --git a/drivers/nfc/pn544/Makefile b/drivers/nfc/pn544/Makefile index 7257338..ac07679 100644 --- a/drivers/nfc/pn544/Makefile +++ b/drivers/nfc/pn544/Makefile @@ -2,6 +2,7 @@ # Makefile for PN544 HCI based NFC driver # -obj-$(CONFIG_PN544_HCI_NFC) += pn544_i2c.o +pn544_i2c-objs = i2c.o -pn544_i2c-y := pn544.o i2c.o +obj-$(CONFIG_NFC_PN544) += pn544.o +obj-$(CONFIG_NFC_PN544_I2C) += pn544_i2c.o diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index ece8342..d108c79 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -862,6 +863,7 @@ err_alloc_hdev: err_info_alloc: return r; } +EXPORT_SYMBOL(pn544_hci_probe); void pn544_hci_remove(struct nfc_hci_dev *hdev) { @@ -871,3 +873,7 @@ void pn544_hci_remove(struct nfc_hci_dev *hdev) nfc_hci_free_device(hdev); kfree(info); } +EXPORT_SYMBOL(pn544_hci_remove); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DRIVER_DESC); -- cgit v0.10.2 From 234d4d6b1038f004f233f14906ec9328bf53088b Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 18 Dec 2012 16:40:16 +0100 Subject: NFC: pn544: Use module_i2c_driver The pn544 init routine does nothing but adding the driver to the i2c bus. Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index 7da9071..ec79f35 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -472,29 +472,7 @@ static struct i2c_driver pn544_hci_i2c_driver = { .remove = __devexit_p(pn544_hci_i2c_remove), }; -static int __init pn544_hci_i2c_init(void) -{ - int r; - - pr_debug(DRIVER_DESC ": %s\n", __func__); - - r = i2c_add_driver(&pn544_hci_i2c_driver); - if (r) { - pr_err(PN544_HCI_I2C_DRIVER_NAME - ": driver registration failed\n"); - return r; - } - - return 0; -} - -static void __exit pn544_hci_i2c_exit(void) -{ - i2c_del_driver(&pn544_hci_i2c_driver); -} - -module_init(pn544_hci_i2c_init); -module_exit(pn544_hci_i2c_exit); +module_i2c_driver(pn544_hci_i2c_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION(DRIVER_DESC); -- cgit v0.10.2 From a0f36536ac2ec0f7a9cfb53c72d6d8c378815fdb Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 18 Dec 2012 18:07:37 +0100 Subject: NFC: pn544: Use devm_kzalloc API Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index ec79f35..7f96ca2 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -376,12 +376,12 @@ static int __devinit pn544_hci_i2c_probe(struct i2c_client *client, return -ENODEV; } - phy = kzalloc(sizeof(struct pn544_i2c_phy), GFP_KERNEL); + phy = devm_kzalloc(&client->dev, sizeof(struct pn544_i2c_phy), + GFP_KERNEL); if (!phy) { dev_err(&client->dev, "Cannot allocate memory for pn544 i2c phy.\n"); - r = -ENOMEM; - goto err_phy_alloc; + return -ENOMEM; } phy->i2c_dev = client; @@ -390,20 +390,18 @@ static int __devinit pn544_hci_i2c_probe(struct i2c_client *client, pdata = client->dev.platform_data; if (pdata == NULL) { dev_err(&client->dev, "No platform data\n"); - r = -EINVAL; - goto err_pdata; + return -EINVAL; } if (pdata->request_resources == NULL) { dev_err(&client->dev, "request_resources() missing\n"); - r = -EINVAL; - goto err_pdata; + return -EINVAL; } r = pdata->request_resources(client); if (r) { dev_err(&client->dev, "Cannot get platform resources\n"); - goto err_pdata; + return r; } phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); @@ -435,10 +433,6 @@ err_rti: if (pdata->free_resources != NULL) pdata->free_resources(); -err_pdata: - kfree(phy); - -err_phy_alloc: return r; } @@ -458,8 +452,6 @@ static __devexit int pn544_hci_i2c_remove(struct i2c_client *client) if (pdata->free_resources) pdata->free_resources(); - kfree(phy); - return 0; } -- cgit v0.10.2 From 2ad554a502facd705ce6eb362d0f1ac3ca426508 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Tue, 18 Dec 2012 17:35:02 +0100 Subject: NFC: update HCI documentation Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz diff --git a/Documentation/nfc/nfc-hci.txt b/Documentation/nfc/nfc-hci.txt index 89a339c..0686c9e 100644 --- a/Documentation/nfc/nfc-hci.txt +++ b/Documentation/nfc/nfc-hci.txt @@ -17,10 +17,12 @@ HCI HCI registers as an nfc device with NFC Core. Requests coming from userspace are routed through netlink sockets to NFC Core and then to HCI. From this point, they are translated in a sequence of HCI commands sent to the HCI layer in the -host controller (the chip). The sending context blocks while waiting for the -response to arrive. +host controller (the chip). Commands can be executed synchronously (the sending +context blocks waiting for response) or asynchronously (the response is returned +from HCI Rx context). HCI events can also be received from the host controller. They will be handled -and a translation will be forwarded to NFC Core as needed. +and a translation will be forwarded to NFC Core as needed. There are hooks to +let the HCI driver handle proprietary events or override standard behavior. HCI uses 2 execution contexts: - one for executing commands : nfc_hci_msg_tx_work(). Only one command can be executing at any given moment. @@ -33,6 +35,8 @@ The Session initialization is an HCI standard which must unfortunately support proprietary gates. This is the reason why the driver will pass a list of proprietary gates that must be part of the session. HCI will ensure all those gates have pipes connected when the hci device is set up. +In case the chip supports pre-opened gates and pseudo-static pipes, the driver +can pass that information to HCI core. HCI Gates and Pipes ------------------- @@ -46,6 +50,13 @@ without knowing the pipe connected to it. Driver interface ---------------- +A driver is generally written in two parts : the physical link management and +the HCI management. This makes it easier to maintain a driver for a chip that +can be connected using various phy (i2c, spi, ...) + +HCI Management +-------------- + A driver would normally register itself with HCI and provide the following entry points: @@ -53,58 +64,113 @@ struct nfc_hci_ops { int (*open)(struct nfc_hci_dev *hdev); void (*close)(struct nfc_hci_dev *hdev); int (*hci_ready) (struct nfc_hci_dev *hdev); - int (*xmit)(struct nfc_hci_dev *hdev, struct sk_buff *skb); - int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols); - int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate, - struct nfc_target *target); + int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); + int (*start_poll) (struct nfc_hci_dev *hdev, + u32 im_protocols, u32 tm_protocols); + int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target, + u8 comm_mode, u8 *gb, size_t gb_len); + int (*dep_link_down)(struct nfc_hci_dev *hdev); + int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, + struct nfc_target *target); int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, struct nfc_target *target); - int (*data_exchange) (struct nfc_hci_dev *hdev, - struct nfc_target *target, - struct sk_buff *skb, struct sk_buff **res_skb); + int (*im_transceive) (struct nfc_hci_dev *hdev, + struct nfc_target *target, struct sk_buff *skb, + data_exchange_cb_t cb, void *cb_context); + int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); int (*check_presence)(struct nfc_hci_dev *hdev, struct nfc_target *target); + int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, + struct sk_buff *skb); }; - open() and close() shall turn the hardware on and off. - hci_ready() is an optional entry point that is called right after the hci session has been set up. The driver can use it to do additional initialization that must be performed using HCI commands. -- xmit() shall simply write a frame to the chip. +- xmit() shall simply write a frame to the physical link. - start_poll() is an optional entrypoint that shall set the hardware in polling mode. This must be implemented only if the hardware uses proprietary gates or a mechanism slightly different from the HCI standard. +- dep_link_up() is called after a p2p target has been detected, to finish +the p2p connection setup with hardware parameters that need to be passed back +to nfc core. +- dep_link_down() is called to bring the p2p link down. - target_from_gate() is an optional entrypoint to return the nfc protocols corresponding to a proprietary gate. - complete_target_discovered() is an optional entry point to let the driver perform additional proprietary processing necessary to auto activate the discovered target. -- data_exchange() must be implemented by the driver if proprietary HCI commands +- im_transceive() must be implemented by the driver if proprietary HCI commands are required to send data to the tag. Some tag types will require custom commands, others can be written to using the standard HCI commands. The driver can check the tag type and either do proprietary processing, or return 1 to ask -for standard processing. +for standard processing. The data exchange command itself must be sent +asynchronously. +- tm_send() is called to send data in the case of a p2p connection - check_presence() is an optional entry point that will be called regularly by the core to check that an activated tag is still in the field. If this is not implemented, the core will not be able to push tag_lost events to the user space +- event_received() is called to handle an event coming from the chip. Driver +can handle the event or return 1 to let HCI attempt standard processing. On the rx path, the driver is responsible to push incoming HCP frames to HCI using nfc_hci_recv_frame(). HCI will take care of re-aggregation and handling This must be done from a context that can sleep. -SHDLC ------ +PHY Management +-------------- + +The physical link (i2c, ...) management is defined by the following struture: + +struct nfc_phy_ops { + int (*write)(void *dev_id, struct sk_buff *skb); + int (*enable)(void *dev_id); + void (*disable)(void *dev_id); +}; + +enable(): turn the phy on (power on), make it ready to transfer data +disable(): turn the phy off +write(): Send a data frame to the chip. Note that to enable higher +layers such as an llc to store the frame for re-emission, this function must +not alter the skb. It must also not return a positive result (return 0 for +success, negative for failure). + +Data coming from the chip shall be sent directly to nfc_hci_recv_frame(). + +LLC +--- + +Communication between the CPU and the chip often requires some link layer +protocol. Those are isolated as modules managed by the HCI layer. There are +currently two modules : nop (raw transfert) and shdlc. +A new llc must implement the following functions: + +struct nfc_llc_ops { + void *(*init) (struct nfc_hci_dev *hdev, xmit_to_drv_t xmit_to_drv, + rcv_to_hci_t rcv_to_hci, int tx_headroom, + int tx_tailroom, int *rx_headroom, int *rx_tailroom, + llc_failure_t llc_failure); + void (*deinit) (struct nfc_llc *llc); + int (*start) (struct nfc_llc *llc); + int (*stop) (struct nfc_llc *llc); + void (*rcv_from_drv) (struct nfc_llc *llc, struct sk_buff *skb); + int (*xmit_from_hci) (struct nfc_llc *llc, struct sk_buff *skb); +}; + +- init() : allocate and init your private storage +- deinit() : cleanup +- start() : establish the logical connection +- stop () : terminate the logical connection +- rcv_from_drv() : handle data coming from the chip, going to HCI +- xmit_from_hci() : handle data sent by HCI, going to the chip -Most chips use shdlc to ensure integrity and delivery ordering of the HCP -frames between the host controller (the chip) and hosts (entities connected -to the chip, like the cpu). In order to simplify writing the driver, an shdlc -layer is available for use by the driver. -When used, the driver actually registers with shdlc, and shdlc will register -with HCI. HCI sees shdlc as the driver and thus send its HCP frames -through shdlc->xmit. -SHDLC adds a new execution context (nfc_shdlc_sm_work()) to run its state -machine and handle both its rx and tx path. +The llc must be registered with nfc before it can be used. Do that by +calling nfc_llc_register(const char *name, struct nfc_llc_ops *ops); + +Again, note that the llc does not handle the physical link. It is thus very +easy to mix any physical link with any llc for a given chip driver. Included Drivers ---------------- @@ -117,10 +183,12 @@ Execution Contexts The execution contexts are the following: - IRQ handler (IRQH): -fast, cannot sleep. stores incoming frames into an shdlc rx queue +fast, cannot sleep. sends incoming frames to HCI where they are passed to +the current llc. In case of shdlc, the frame is queued in shdlc rx queue. - SHDLC State Machine worker (SMW) -handles shdlc rx & tx queues. Dispatches HCI cmd responses. +Only when llc_shdlc is used: handles shdlc rx & tx queues. +Dispatches HCI cmd responses. - HCI Tx Cmd worker (MSGTXWQ) Serializes execution of HCI commands. Completes execution in case of response @@ -166,6 +234,15 @@ waiting command execution. Response processing involves invoking the completion callback that was provided by nfc_hci_msg_tx_work() when it sent the command. The completion callback will then wake the syscall context. +It is also possible to execute the command asynchronously using this API: + +static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, + const u8 *param, size_t param_len, + data_exchange_cb_t cb, void *cb_context) + +The workflow is the same, except that the API call returns immediately, and +the callback will be called with the result from the SMW context. + Workflow receiving an HCI event or command ------------------------------------------ -- cgit v0.10.2 From 390a1bd8538132186ddb679cafe9e75b7ef7e2d2 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 19 Dec 2012 19:11:32 +0100 Subject: NFC: Initial Secure Element API Each NFC adapter can have several links to different secure elements and that property needs to be exported by the drivers. A secure element link can be enabled and disabled, and card emulation will be handled by the currently active one. Otherwise card emulation will be host implemented. Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index c7c182d..3b731ac 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c @@ -542,6 +542,7 @@ static int nfcwilink_probe(struct platform_device *pdev) drv->ndev = nci_allocate_device(&nfcwilink_ops, protocols, + NFC_SE_NONE, NFCWILINK_HDR_LEN, 0); if (!drv->ndev) { diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index e8c0832..31a5b3b 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -2525,6 +2525,7 @@ static int pn533_probe(struct usb_interface *interface, dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, + NFC_SE_NONE, dev->ops->tx_header_len + PN533_CMD_DATAEXCH_HEAD_LEN, dev->ops->tx_tail_len); diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index d108c79..9c5f16e 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -801,7 +801,7 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, struct nfc_hci_dev **hdev) { struct pn544_hci_info *info; - u32 protocols; + u32 protocols, se; struct nfc_hci_init_data init_data; int r; @@ -834,8 +834,10 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_NFC_DEP_MASK; + se = NFC_SE_UICC | NFC_SE_EMBEDDED; + info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, 0, - protocols, llc_name, + protocols, se, llc_name, phy_headroom + PN544_CMDS_HEADROOM, phy_tailroom, phy_payload); if (!info->hdev) { diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 2ff7175..b87a169 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h @@ -59,6 +59,8 @@ struct nfc_hci_ops { struct nfc_target *target); int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, struct sk_buff *skb); + int (*enable_se)(struct nfc_dev *dev, u32 secure_element); + int (*disable_se)(struct nfc_dev *dev, u32 secure_element); }; /* Pipes */ @@ -150,6 +152,7 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, struct nfc_hci_init_data *init_data, unsigned long quirks, u32 protocols, + u32 supported_se, const char *llc_name, int tx_headroom, int tx_tailroom, diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index d705d86..5bc0c46 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -147,6 +147,7 @@ struct nci_dev { /* ----- NCI Devices ----- */ struct nci_dev *nci_allocate_device(struct nci_ops *ops, __u32 supported_protocols, + __u32 supported_se, int tx_headroom, int tx_tailroom); void nci_free_device(struct nci_dev *ndev); diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 1665674..87a6417 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -68,6 +68,8 @@ struct nfc_ops { void *cb_context); int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb); int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); + int (*enable_se)(struct nfc_dev *dev, u32 secure_element); + int (*disable_se)(struct nfc_dev *dev, u32 secure_element); }; #define NFC_TARGET_IDX_ANY -1 @@ -109,6 +111,9 @@ struct nfc_dev { struct nfc_genl_data genl_data; u32 supported_protocols; + u32 supported_se; + u32 active_se; + int tx_headroom; int tx_tailroom; @@ -125,6 +130,7 @@ extern struct class nfc_class; struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, u32 supported_protocols, + u32 supported_se, int tx_headroom, int tx_tailroom); diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 0e63cee..80e4ecd 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h @@ -67,6 +67,11 @@ * subsequent CONNECT and CC messages. * If one of the passed parameters is wrong none is set and -EINVAL is * returned. + * @NFC_CMD_ENABLE_SE: Enable the physical link to a specific secure element. + * Once enabled a secure element will handle card emulation mode, i.e. + * starting a poll from a device which has a secure element enabled means + * we want to do SE based card emulation. + * @NFC_CMD_DISABLE_SE: Disable the physical link to a specific secure element. */ enum nfc_commands { NFC_CMD_UNSPEC, @@ -86,6 +91,8 @@ enum nfc_commands { NFC_EVENT_TM_DEACTIVATED, NFC_CMD_LLC_GET_PARAMS, NFC_CMD_LLC_SET_PARAMS, + NFC_CMD_ENABLE_SE, + NFC_CMD_DISABLE_SE, /* private: internal use only */ __NFC_CMD_AFTER_LAST }; @@ -114,6 +121,7 @@ enum nfc_commands { * @NFC_ATTR_LLC_PARAM_LTO: Link TimeOut parameter * @NFC_ATTR_LLC_PARAM_RW: Receive Window size parameter * @NFC_ATTR_LLC_PARAM_MIUX: MIU eXtension parameter + * @NFC_ATTR_SE: Available Secure Elements */ enum nfc_attrs { NFC_ATTR_UNSPEC, @@ -134,6 +142,7 @@ enum nfc_attrs { NFC_ATTR_LLC_PARAM_LTO, NFC_ATTR_LLC_PARAM_RW, NFC_ATTR_LLC_PARAM_MIUX, + NFC_ATTR_SE, /* private: internal use only */ __NFC_ATTR_AFTER_LAST }; @@ -172,6 +181,11 @@ enum nfc_attrs { #define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP) #define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B) +/* NFC Secure Elements */ +#define NFC_SE_NONE 0x0 +#define NFC_SE_UICC 0x1 +#define NFC_SE_EMBEDDED 0x2 + struct sockaddr_nfc { sa_family_t sa_family; __u32 dev_idx; diff --git a/net/nfc/core.c b/net/nfc/core.c index 7d7b4ee..25522e5 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -757,6 +757,7 @@ struct nfc_dev *nfc_get_device(unsigned int idx) */ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, u32 supported_protocols, + u32 supported_se, int tx_headroom, int tx_tailroom) { struct nfc_dev *dev; @@ -774,6 +775,8 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, dev->ops = ops; dev->supported_protocols = supported_protocols; + dev->supported_se = supported_se; + dev->active_se = NFC_SE_NONE; dev->tx_headroom = tx_headroom; dev->tx_tailroom = tx_tailroom; diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 755a6b9..91020b2 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -797,6 +797,7 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, struct nfc_hci_init_data *init_data, unsigned long quirks, u32 protocols, + u32 supported_se, const char *llc_name, int tx_headroom, int tx_tailroom, @@ -822,7 +823,7 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, return NULL; } - hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, + hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, supported_se, tx_headroom + HCI_CMDS_HEADROOM, tx_tailroom); if (!hdev->ndev) { diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 5f98dc1..48ada0e 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -658,6 +658,7 @@ static struct nfc_ops nci_nfc_ops = { */ struct nci_dev *nci_allocate_device(struct nci_ops *ops, __u32 supported_protocols, + __u32 supported_se, int tx_headroom, int tx_tailroom) { struct nci_dev *ndev; @@ -680,6 +681,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, supported_protocols, + supported_se, tx_headroom + NCI_DATA_HDR_SIZE, tx_tailroom); if (!ndev->nfc_dev) diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 3568ae1..504b883 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -366,6 +366,7 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || + nla_put_u32(msg, NFC_ATTR_SE, dev->supported_se) || nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) || nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode)) goto nla_put_failure; -- cgit v0.10.2 From 8a0ecfe74b3692258311d084d31613516828905f Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Fri, 21 Dec 2012 10:39:01 +0100 Subject: NFC: pn533: Fix missing parenthesis This is a quite critical patch as it fixes potential reference to undefined general_bytes which were never set correctly on target activation due to missing parenthesis. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 31a5b3b..f1702f9 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1724,9 +1724,10 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) rsp = (struct pn533_cmd_activate_response *)resp->data; rc = rsp->status & PN533_CMD_RET_MASK; - if (rc != PN533_CMD_RET_SUCCESS) + if (rc != PN533_CMD_RET_SUCCESS) { dev_kfree_skb(resp); return -EIO; + } /* ATR_RES general bytes are located at offset 16 */ gt_len = resp->len - 16; -- cgit v0.10.2 From 1353a10c474d1c6895051d33eefeb93542015008 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 10 Jan 2013 01:25:04 +0100 Subject: NFC: Update pn544 documentation The pn544 driver no longer has a /dev/pn544 interface nor a sysfs one. Reported-by: Marcel Holtmann Signed-off-by: Samuel Ortiz diff --git a/Documentation/nfc/nfc-pn544.txt b/Documentation/nfc/nfc-pn544.txt index 2fcac9f..b36ca14 100644 --- a/Documentation/nfc/nfc-pn544.txt +++ b/Documentation/nfc/nfc-pn544.txt @@ -1,32 +1,15 @@ Kernel driver for the NXP Semiconductors PN544 Near Field Communication chip -Author: Jari Vanhala -Contact: Matti Aaltonen (matti.j.aaltonen at nokia.com) - General ------- The PN544 is an integrated transmission module for contactless communication. The driver goes under drives/nfc/ and is compiled as a -module named "pn544". It registers a misc device and creates a device -file named "/dev/pn544". +module named "pn544". Host Interfaces: I2C, SPI and HSU, this driver supports currently only I2C. -The Interface -------------- - -The driver offers a sysfs interface for a hardware test and an IOCTL -interface for selecting between two operating modes. There are read, -write and poll functions for transferring messages. The two operating -modes are the normal (HCI) mode and the firmware update mode. - -PN544 is controlled by sending messages from the userspace to the -chip. The main function of the driver is just to pass those messages -without caring about the message content. - - Protocols --------- @@ -47,68 +30,3 @@ and third (LSB) bytes of the message. The maximum FW message length is For the ETSI HCI specification see http://www.etsi.org/WebSite/Technologies/ProtocolSpecification.aspx - -The Hardware Test ------------------ - -The idea of the test is that it can performed by reading from the -corresponding sysfs file. The test is implemented in the board file -and it should test that PN544 can be put into the firmware update -mode. If the test is not implemented the sysfs file does not get -created. - -Example: -> cat /sys/module/pn544/drivers/i2c\:pn544/3-002b/nfc_test -1 - -Normal Operation ----------------- - -PN544 is powered up when the device file is opened, otherwise it's -turned off. Only one instance can use the device at a time. - -Userspace applications control PN544 with HCI messages. The hardware -sends an interrupt when data is available for reading. Data is -physically read when the read function is called by a userspace -application. Poll() checks the read interrupt state. Configuration and -self testing are also done from the userspace using read and write. - -Example platform data: - -static int rx71_pn544_nfc_request_resources(struct i2c_client *client) -{ - /* Get and setup the HW resources for the device */ -} - -static void rx71_pn544_nfc_free_resources(void) -{ - /* Release the HW resources */ -} - -static void rx71_pn544_nfc_enable(int fw) -{ - /* Turn the device on */ -} - -static int rx71_pn544_nfc_test(void) -{ - /* - * Put the device into the FW update mode - * and then back to the normal mode. - * Check the behavior and return one on success, - * zero on failure. - */ -} - -static void rx71_pn544_nfc_disable(void) -{ - /* turn the power off */ -} - -static struct pn544_nfc_platform_data rx71_nfc_data = { - .request_resources = rx71_pn544_nfc_request_resources, - .free_resources = rx71_pn544_nfc_free_resources, - .enable = rx71_pn544_nfc_enable, - .test = rx71_pn544_nfc_test, - .disable = rx71_pn544_nfc_disable, -}; -- cgit v0.10.2 From fad2e371bb5a9f64dced90309fa7cb8bce09e92f Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 11 Jan 2013 14:48:48 +0100 Subject: NFC: Avoid memcpy on LLCP connection less Rx path We can cast msg_name to a sockaddr_nfc_llcp pointer directly. Signed-off-by: Samuel Ortiz diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 12ec487..463231b 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -682,17 +682,17 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (sk->sk_type == SOCK_DGRAM && msg->msg_name) { struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb); - struct sockaddr_nfc_llcp sockaddr; + struct sockaddr_nfc_llcp *sockaddr = + (struct sockaddr_nfc_llcp *) msg->msg_name; - pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); + msg->msg_namelen = sizeof(struct sockaddr_nfc_llcp); - sockaddr.sa_family = AF_NFC; - sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP; - sockaddr.dsap = ui_cb->dsap; - sockaddr.ssap = ui_cb->ssap; + pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); - memcpy(msg->msg_name, &sockaddr, sizeof(sockaddr)); - msg->msg_namelen = sizeof(sockaddr); + sockaddr->sa_family = AF_NFC; + sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP; + sockaddr->dsap = ui_cb->dsap; + sockaddr->ssap = ui_cb->ssap; } /* Mark read part of skb as used */ -- cgit v0.10.2 From fb97c3e80f99988079df4fb5f3c84aea4e7f806a Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 11 Jan 2013 14:54:22 +0100 Subject: NFC: Use skb_copy_datagram_iovec Safer and more robust than than memcpy_toiovec. Signed-off-by: Samuel Ortiz diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 463231b..5332751 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -672,7 +672,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, copied = min_t(unsigned int, rlen, len); cskb = skb; - if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) { + if (skb_copy_datagram_iovec(cskb, 0, msg->msg_iov, copied)) { if (!(flags & MSG_PEEK)) skb_queue_head(&sk->sk_receive_queue, skb); return -EFAULT; -- cgit v0.10.2 From 858ce0220922a52e009d17dcaaab5dfd76f9833b Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Sat, 12 Jan 2013 19:37:12 +0100 Subject: NFC: pn533: Fix bad allocation size Use dereferenced pointer in sizeof instead of pointer itself. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index f1702f9..f696318 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -743,7 +743,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", cmd_code); - arg = kzalloc(sizeof(arg), GFP_KERNEL); + arg = kzalloc(sizeof(*arg), GFP_KERNEL); if (!arg) return -ENOMEM; @@ -863,7 +863,7 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, if (!resp) return -ENOMEM; - arg = kzalloc(sizeof(arg), GFP_KERNEL); + arg = kzalloc(sizeof(*arg), GFP_KERNEL); if (!arg) { dev_kfree_skb(resp); return -ENOMEM; -- cgit v0.10.2 From d3710e74cf329839dea8d13b1ad56e572b06b173 Mon Sep 17 00:00:00 2001 From: Lauro Ramos Venancio Date: Wed, 5 Dec 2012 21:12:25 -0300 Subject: NFC: Change nfc.h license nfc.h being GPL makes it quite controversial for non GPL applications to include it. Moreover, nfc.h only includes structures and API definitions that are hardly copyrightable. Signed-off-by: Lauro Ramos Venancio Signed-off-by: Samuel Ortiz diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 80e4ecd..7969f46 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h @@ -5,20 +5,17 @@ * Lauro Ramos Venancio * Aloisio Almeida Jr * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __LINUX_NFC_H -- cgit v0.10.2