From fe7c580073280c15bb4eb4f82bf20dddc1a68383 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 15 May 2012 15:57:06 +0200 Subject: NFC: Add target mode protocols to the polling loop startup routine Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index e1a640d..281f3a3 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -481,12 +481,13 @@ static int hci_dev_down(struct nfc_dev *nfc_dev) return 0; } -static int hci_start_poll(struct nfc_dev *nfc_dev, u32 protocols) +static int hci_start_poll(struct nfc_dev *nfc_dev, + u32 im_protocols, u32 tm_protocols) { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); if (hdev->ops->start_poll) - return hdev->ops->start_poll(hdev, protocols); + return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); else return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, NFC_HCI_EVT_READER_REQUESTED, NULL, 0); -- cgit v1.1 From be9ae4ce4ee66e211815122ab4f41913efed4fec Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 16 May 2012 15:55:48 +0200 Subject: NFC: Introduce target mode tx ops And rename the initiator mode data exchange ops for consistency sake. Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 281f3a3..a8b0b71 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -512,9 +512,9 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev, { } -static int hci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, - struct sk_buff *skb, data_exchange_cb_t cb, - void *cb_context) +static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, + struct sk_buff *skb, data_exchange_cb_t cb, + void *cb_context) { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); int r; @@ -580,7 +580,7 @@ static struct nfc_ops hci_nfc_ops = { .stop_poll = hci_stop_poll, .activate_target = hci_activate_target, .deactivate_target = hci_deactivate_target, - .data_exchange = hci_data_exchange, + .im_transceive = hci_transceive, .check_presence = hci_check_presence, }; -- cgit v1.1 From a9a741a7e2e6337ae5c030e78827c233c08902a7 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Mon, 30 Apr 2012 18:21:51 +0200 Subject: NFC: Prepare asynchronous error management for driver and shdlc Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index a8b0b71..1dc6485 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -717,6 +717,14 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev) } EXPORT_SYMBOL(nfc_hci_get_clientdata); +void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err) +{ + /* TODO: lower layer has permanent failure. + * complete potential HCI command or send an empty tag discovered event + */ +} +EXPORT_SYMBOL(nfc_hci_driver_failure); + void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) { struct hcp_packet *packet; -- cgit v1.1 From 1c215d79a18a22fc6c2a9ef8658d426bac492b58 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Wed, 2 May 2012 11:37:19 +0200 Subject: NFC: Remove an impossible HCI error case nfc_hci_recv_frame can not be called with a NULL skb. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 1dc6485..1a009d5 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -735,16 +735,6 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) struct sk_buff *frag_skb; int msg_len; - if (skb == NULL) { - /* TODO ELa: lower layer had permanent failure, need to - * propagate that up - */ - - skb_queue_purge(&hdev->rx_hcp_frags); - - return; - } - packet = (struct hcp_packet *)skb->data; if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) { skb_queue_tail(&hdev->rx_hcp_frags, skb); -- cgit v1.1 From 72b06f75fea45fa861f2e137bc94e56aab306c4b Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Mon, 11 Jun 2012 13:36:52 +0200 Subject: NFC: Implement HCP reaggregation allocation error case We can now report an ENOMEM error up to the HCI layer. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 1a009d5..7d4fdbc 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -717,12 +717,18 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev) } EXPORT_SYMBOL(nfc_hci_get_clientdata); -void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err) +static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err) { - /* TODO: lower layer has permanent failure. + /* + * TODO: lower layer has permanent failure. * complete potential HCI command or send an empty tag discovered event */ } + +void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err) +{ + nfc_hci_failure(hdev, err); +} EXPORT_SYMBOL(nfc_hci_driver_failure); void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) @@ -755,9 +761,8 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN + msg_len, GFP_KERNEL); if (hcp_skb == NULL) { - /* TODO ELa: cannot deliver HCP message. How to - * propagate error up? - */ + nfc_hci_failure(hdev, -ENOMEM); + return; } *skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe; -- cgit v1.1 From 6c1c5b9e1d8a25268a607c762576b5c16e3e7230 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Thu, 3 May 2012 15:35:25 +0200 Subject: NFC: Changed HCI cmd execution completion result to std linux errno An HCI command can complete either from an HCI response (with an HCI result) or as a consequence of any other system error during processing. The completion therefore needs to take a standard errno code. The HCI response will convert its result to a standard errno before calling the completion. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 7d4fdbc..5be7405c 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -32,6 +32,18 @@ /* Largest headroom needed for outgoing HCI commands */ #define HCI_CMDS_HEADROOM 1 +static int nfc_hci_result_to_errno(u8 result) +{ + switch (result) { + case NFC_HCI_ANY_OK: + return 0; + case NFC_HCI_ANY_E_TIMEOUT: + return -ETIME; + default: + return -1; + } +} + static void nfc_hci_msg_tx_work(struct work_struct *work) { struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev, @@ -46,7 +58,7 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) if (timer_pending(&hdev->cmd_timer) == 0) { if (hdev->cmd_pending_msg->cb) hdev->cmd_pending_msg->cb(hdev, - NFC_HCI_ANY_E_TIMEOUT, + -ETIME, NULL, hdev-> cmd_pending_msg-> @@ -71,8 +83,7 @@ next_msg: kfree_skb(skb); skb_queue_purge(&msg->msg_frags); if (msg->cb) - msg->cb(hdev, NFC_HCI_ANY_E_NOK, NULL, - msg->cb_context); + msg->cb(hdev, r, NULL, msg->cb_context); kfree(msg); break; } @@ -129,7 +140,8 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, del_timer_sync(&hdev->cmd_timer); if (hdev->cmd_pending_msg->cb) - hdev->cmd_pending_msg->cb(hdev, result, skb, + hdev->cmd_pending_msg->cb(hdev, nfc_hci_result_to_errno(result), + skb, hdev->cmd_pending_msg->cb_context); else kfree_skb(skb); -- cgit v1.1 From ccca0d6e8805f12fcda2e740c44afa7191923559 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Thu, 3 May 2012 15:59:37 +0200 Subject: NFC: Factorize HCI cmd completion HCI cmd can be completed either from an HCI response or from an internal driver or HCI error. This requires to factorize the completion code outside of the device lock. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 5be7405c..9a1a12f 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -127,21 +127,13 @@ static void nfc_hci_msg_rx_work(struct work_struct *work) } } -void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, - struct sk_buff *skb) +static void __nfc_hci_cmd_completion(struct nfc_hci_dev *hdev, int err, + struct sk_buff *skb) { - mutex_lock(&hdev->msg_tx_mutex); - - if (hdev->cmd_pending_msg == NULL) { - kfree_skb(skb); - goto exit; - } - del_timer_sync(&hdev->cmd_timer); if (hdev->cmd_pending_msg->cb) - hdev->cmd_pending_msg->cb(hdev, nfc_hci_result_to_errno(result), - skb, + hdev->cmd_pending_msg->cb(hdev, err, skb, hdev->cmd_pending_msg->cb_context); else kfree_skb(skb); @@ -150,6 +142,19 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, hdev->cmd_pending_msg = NULL; queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work); +} + +void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, + struct sk_buff *skb) +{ + mutex_lock(&hdev->msg_tx_mutex); + + if (hdev->cmd_pending_msg == NULL) { + kfree_skb(skb); + goto exit; + } + + __nfc_hci_cmd_completion(hdev, nfc_hci_result_to_errno(result), skb); exit: mutex_unlock(&hdev->msg_tx_mutex); -- cgit v1.1 From a070c8591a503ec65e2c84ebaf3454e5cd76e3fe Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Mon, 11 Jun 2012 15:06:56 +0200 Subject: NFC: Implement HCI driver or internal error management If there is an ongoing HCI command executing, it will be completed, thereby pushing the error up to the core. Otherwise, HCI will directly notify the core with the error. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 9a1a12f..e6b2df3 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -736,10 +736,17 @@ EXPORT_SYMBOL(nfc_hci_get_clientdata); static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err) { - /* - * TODO: lower layer has permanent failure. - * complete potential HCI command or send an empty tag discovered event - */ + mutex_lock(&hdev->msg_tx_mutex); + + if (hdev->cmd_pending_msg == NULL) { + nfc_driver_failure(hdev->ndev, err); + goto exit; + } + + __nfc_hci_cmd_completion(hdev, err, NULL); + +exit: + mutex_unlock(&hdev->msg_tx_mutex); } void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err) -- cgit v1.1 From a10d595b1074d04446f77161eea165e5809e163c Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Tue, 5 Jun 2012 14:42:11 +0200 Subject: NFC: Allow HCI driver to pre-open pipes to some gates Some NFC chips will statically create and open pipes for both standard and proprietary gates. The driver can now pass this information to HCI such that HCI will not attempt to create and open them, but will instead directly use the passed pipe ids. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index e6b2df3..4ccc518 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -315,15 +315,15 @@ static void nfc_hci_cmd_timeout(unsigned long data) } static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count, - u8 gates[]) + struct nfc_hci_gate *gates) { int r; - u8 *p = gates; while (gate_count--) { - r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, *p); + r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, + gates->gate, gates->pipe); if (r < 0) return r; - p++; + gates++; } return 0; @@ -333,14 +333,13 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev) { struct sk_buff *skb = NULL; int r; - u8 hci_gates[] = { /* NFC_HCI_ADMIN_GATE MUST be first */ - NFC_HCI_ADMIN_GATE, NFC_HCI_LOOPBACK_GATE, - NFC_HCI_ID_MGMT_GATE, NFC_HCI_LINK_MGMT_GATE, - NFC_HCI_RF_READER_B_GATE, NFC_HCI_RF_READER_A_GATE - }; + + if (hdev->init_data.gates[0].gate != NFC_HCI_ADMIN_GATE) + return -EPROTO; r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, - NFC_HCI_ADMIN_GATE); + hdev->init_data.gates[0].gate, + hdev->init_data.gates[0].pipe); if (r < 0) goto exit; @@ -368,10 +367,6 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev) if (r < 0) goto exit; - r = hci_dev_connect_gates(hdev, sizeof(hci_gates), hci_gates); - if (r < 0) - goto disconnect_all; - r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, hdev->init_data.gates); if (r < 0) -- cgit v1.1 From 01d719a2287ec34f631800d10f1fad3c134c3e89 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 4 Jul 2012 00:14:04 +0200 Subject: NFC: Add ISO 14443 type B protocol Some devices (e.g. Sony's PaSoRi) can not do type B polling, so we have to make a distinction between ISO14443 type A and B poll modes. Cc: Eric Lapuyade Cc: Ilan Elias Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 4ccc518..36717ce 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -230,7 +230,7 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) } break; case NFC_HCI_RF_READER_B_GATE: - targets->supported_protocols = NFC_PROTO_ISO14443_MASK; + targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK; break; default: if (hdev->ops->target_from_gate) -- cgit v1.1 From 1913e57cf9a7be4565c56a3fbfd85106919ea006 Mon Sep 17 00:00:00 2001 From: Mathias Jeppsson Date: Sat, 7 Jul 2012 00:53:18 +0200 Subject: NFC: Fix empty HCI message list check list_first_entry() will never return NULL. Instead use list_for_each_entry_safe() to iterate through the list. Signed-off-by: Mathias Jeppsson Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- net/nfc/hci/core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index e1a640d..da6e039 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -682,13 +682,12 @@ EXPORT_SYMBOL(nfc_hci_register_device); void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) { - struct hci_msg *msg; + struct hci_msg *msg, *n; skb_queue_purge(&hdev->rx_hcp_frags); skb_queue_purge(&hdev->msg_rx_queue); - while ((msg = list_first_entry(&hdev->msg_tx_queue, struct hci_msg, - msg_l)) != NULL) { + list_for_each_entry_safe(msg, n, &hdev->msg_tx_queue, msg_l) { list_del(&msg->msg_l); skb_queue_purge(&msg->msg_frags); kfree(msg); -- cgit v1.1 From 81b3039557faf1359f40494003aaade745de6c24 Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Thu, 12 Jul 2012 20:27:54 +0200 Subject: NFC: Set target nfcid1 for all HCI reader A targets Without the discovered target nfcid1 and its length set properly, type 2 tags detection fails with the pn544 as it checks for them from pn544_hci_complete_target_discovered(). Signed-off-by: Eric Lapuyade Reported-by: Mathias Jeppsson Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- net/nfc/hci/core.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'net/nfc/hci/core.c') diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index da6e039..4896ef1 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -170,6 +170,7 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) struct nfc_target *targets; struct sk_buff *atqa_skb = NULL; struct sk_buff *sak_skb = NULL; + struct sk_buff *uid_skb = NULL; int r; pr_debug("from gate %d\n", gate); @@ -205,6 +206,19 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) targets->sens_res = be16_to_cpu(*(u16 *)atqa_skb->data); targets->sel_res = sak_skb->data[0]; + r = nfc_hci_get_param(hdev, NFC_HCI_RF_READER_A_GATE, + NFC_HCI_RF_READER_A_UID, &uid_skb); + if (r < 0) + goto exit; + + if (uid_skb->len == 0 || uid_skb->len > NFC_NFCID1_MAXSIZE) { + r = -EPROTO; + goto exit; + } + + memcpy(targets->nfcid1, uid_skb->data, uid_skb->len); + targets->nfcid1_len = uid_skb->len; + if (hdev->ops->complete_target_discovered) { r = hdev->ops->complete_target_discovered(hdev, gate, targets); @@ -240,6 +254,7 @@ exit: kfree(targets); kfree_skb(atqa_skb); kfree_skb(sak_skb); + kfree_skb(uid_skb); return r; } -- cgit v1.1