From a381d4828625f526d290b296a829f8549b14ce49 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 21 Jan 2014 16:23:59 -0700 Subject: NFC: digital: Add Digital Layer support for ISO/IEC 15693 Add support for ISO/IEC 15693 to the digital layer. The code currently uses single-slot anticollision only since the digital layer infrastructure only supports one tag per adapter (making it pointless to do 16-slot anticollision). The code uses two new framing types: 'NFC_DIGITAL_FRAMING_ISO15693_INVENTORY' and 'NFC_DIGITAL_FRAMING_ISO15693_TVT'. The former is used to tell the driver to prepare for an Inventory command and the ensuing anticollision sequence. The latter is used to tell the driver that the anticollision sequence is over and to prepare for non-inventory commands. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- net/nfc/digital.h | 1 + net/nfc/digital_core.c | 14 ++++++ net/nfc/digital_technology.c | 109 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) (limited to 'net/nfc') diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 08b29b55ea63..3c757dc7d44f 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h @@ -72,6 +72,7 @@ void digital_poll_next_tech(struct nfc_digital_dev *ddev); int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); +int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech); int digital_target_found(struct nfc_digital_dev *ddev, struct nfc_target *target, u8 protocol); diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index c129d1571ca6..48906ca60540 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -25,6 +25,8 @@ #define DIGITAL_PROTO_NFCF_RF_TECH \ (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) +#define DIGITAL_PROTO_ISO15693_RF_TECH NFC_PROTO_ISO15693_MASK + struct digital_cmd { struct list_head queue; @@ -331,6 +333,12 @@ int digital_target_found(struct nfc_digital_dev *ddev, } break; + case NFC_PROTO_ISO15693: + framing = NFC_DIGITAL_FRAMING_ISO15693_TVT; + check_crc = digital_skb_check_crc_b; + add_crc = digital_skb_add_crc_b; + break; + default: pr_err("Invalid protocol %d\n", protocol); return -EINVAL; @@ -469,6 +477,10 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, digital_in_send_sensf_req); } + if (matching_im_protocols & DIGITAL_PROTO_ISO15693_RF_TECH) + digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_ISO15693, + digital_in_send_iso15693_inv_req); + if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { if (ddev->ops->tg_listen_mdaa) { digital_add_poll_tech(ddev, 0, @@ -700,6 +712,8 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, ddev->protocols |= NFC_PROTO_FELICA_MASK; if (supported_protocols & NFC_PROTO_NFC_DEP_MASK) ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; + if (supported_protocols & NFC_PROTO_ISO15693_MASK) + ddev->protocols |= NFC_PROTO_ISO15693_MASK; ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 251c8c753ebe..97d3f602fc06 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c @@ -51,6 +51,15 @@ #define DIGITAL_SENSF_REQ_RC_SC 1 #define DIGITAL_SENSF_REQ_RC_AP 2 +#define DIGITAL_CMD_ISO15693_INVENTORY_REQ 0x01 + +#define DIGITAL_ISO15693_REQ_FLAG_DATA_RATE BIT(1) +#define DIGITAL_ISO15693_REQ_FLAG_INVENTORY BIT(2) +#define DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS BIT(5) +#define DIGITAL_ISO15693_RES_FLAG_ERROR BIT(0) +#define DIGITAL_ISO15693_RES_IS_VALID(flags) \ + (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR)) + struct digital_sdd_res { u8 nfcid1[4]; u8 bcc; @@ -82,6 +91,19 @@ struct digital_sensf_res { u8 rd[2]; } __packed; +struct digital_iso15693_inv_req { + u8 flags; + u8 cmd; + u8 mask_len; + u64 mask; +} __packed; + +struct digital_iso15693_inv_res { + u8 flags; + u8 dsfid; + u64 uid; +} __packed; + static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, struct nfc_target *target); @@ -473,6 +495,93 @@ int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech) return rc; } +static void digital_in_recv_iso15693_inv_res(struct nfc_digital_dev *ddev, + void *arg, struct sk_buff *resp) +{ + struct digital_iso15693_inv_res *res; + struct nfc_target *target = NULL; + int rc; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + resp = NULL; + goto out_free_skb; + } + + if (resp->len != sizeof(*res)) { + rc = -EIO; + goto out_free_skb; + } + + res = (struct digital_iso15693_inv_res *)resp->data; + + if (!DIGITAL_ISO15693_RES_IS_VALID(res->flags)) { + PROTOCOL_ERR("ISO15693 - 10.3.1"); + rc = -EINVAL; + goto out_free_skb; + } + + target = kzalloc(sizeof(*target), GFP_KERNEL); + if (!target) { + rc = -ENOMEM; + goto out_free_skb; + } + + target->is_iso15693 = 1; + target->iso15693_dsfid = res->dsfid; + memcpy(target->iso15693_uid, &res->uid, sizeof(target->iso15693_uid)); + + rc = digital_target_found(ddev, target, NFC_PROTO_ISO15693); + + kfree(target); + +out_free_skb: + dev_kfree_skb(resp); + + if (rc) + digital_poll_next_tech(ddev); +} + +int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech) +{ + struct digital_iso15693_inv_req *req; + struct sk_buff *skb; + int rc; + + rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, + NFC_DIGITAL_RF_TECH_ISO15693); + if (rc) + return rc; + + rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, + NFC_DIGITAL_FRAMING_ISO15693_INVENTORY); + if (rc) + return rc; + + skb = digital_skb_alloc(ddev, sizeof(*req)); + if (!skb) + return -ENOMEM; + + skb_put(skb, sizeof(*req) - sizeof(req->mask)); /* No mask */ + req = (struct digital_iso15693_inv_req *)skb->data; + + /* Single sub-carrier, high data rate, no AFI, single slot + * Inventory command + */ + req->flags = DIGITAL_ISO15693_REQ_FLAG_DATA_RATE | + DIGITAL_ISO15693_REQ_FLAG_INVENTORY | + DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS; + req->cmd = DIGITAL_CMD_ISO15693_INVENTORY_REQ; + req->mask_len = 0; + + rc = digital_in_send_cmd(ddev, skb, 30, + digital_in_recv_iso15693_inv_res, NULL); + if (rc) + kfree_skb(skb); + + return rc; +} + static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) { struct sk_buff *skb; -- cgit From f5f6872ed2d9a33f99013f6bad734b7f0684da23 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 14 Jan 2014 17:52:11 -0700 Subject: NFC: Add netlink support for ISO/IEC 15693 Add ISO/IEC 15693 support by having netlink push the 1-byte DSFID and 8-byte UID tag information upstream. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- net/nfc/netlink.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'net/nfc') diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index ebbf6fb88b35..43cb1c17e267 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -94,6 +94,14 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, target->sensf_res)) goto nla_put_failure; + if (target->is_iso15693) { + if (nla_put_u8(msg, NFC_ATTR_TARGET_ISO15693_DSFID, + target->iso15693_dsfid) || + nla_put(msg, NFC_ATTR_TARGET_ISO15693_UID, + sizeof(target->iso15693_uid), target->iso15693_uid)) + goto nla_put_failure; + } + return genlmsg_end(msg, hdr); nla_put_failure: -- cgit From 12e3d241e42956da168fd499347855af799f62fb Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Mon, 27 Jan 2014 00:31:31 +0100 Subject: NFC: digital: Add poll support for type 4A tag platform This adds support for ATS request and response handling for type 4A tag activation. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/digital_core.c | 7 ++++ net/nfc/digital_technology.c | 81 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 2 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 48906ca60540..e1f240266adf 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -337,6 +337,11 @@ int digital_target_found(struct nfc_digital_dev *ddev, framing = NFC_DIGITAL_FRAMING_ISO15693_TVT; check_crc = digital_skb_check_crc_b; add_crc = digital_skb_add_crc_b; + + case NFC_PROTO_ISO14443: + framing = NFC_DIGITAL_FRAMING_NFCA_T4T; + check_crc = digital_skb_check_crc_a; + add_crc = digital_skb_add_crc_a; break; default: @@ -714,6 +719,8 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; if (supported_protocols & NFC_PROTO_ISO15693_MASK) ddev->protocols |= NFC_PROTO_ISO15693_MASK; + if (supported_protocols & NFC_PROTO_ISO14443_MASK) + ddev->protocols |= NFC_PROTO_ISO14443_MASK; ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 97d3f602fc06..6649d9461dff 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c @@ -30,6 +30,7 @@ #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) +#define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20) #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) @@ -60,6 +61,16 @@ #define DIGITAL_ISO15693_RES_IS_VALID(flags) \ (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR)) +static const u8 digital_ats_fsc[] = { + 16, 24, 32, 40, 48, 64, 96, 128, +}; + +#define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F) +#define DIGITAL_ATS_MAX_FSC 256 + +#define DIGITAL_RATS_BYTE1 0xE0 +#define DIGITAL_RATS_PARAM 0x80 + struct digital_sdd_res { u8 nfcid1[4]; u8 bcc; @@ -107,6 +118,63 @@ struct digital_iso15693_inv_res { static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, struct nfc_target *target); +static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg, + struct sk_buff *resp) +{ + struct nfc_target *target = arg; + u8 fsdi; + int rc; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + resp = NULL; + goto exit; + } + + if (resp->len < 2) { + rc = -EIO; + goto exit; + } + + fsdi = DIGITAL_ATS_FSCI(resp->data[1]); + if (fsdi >= 8) + ddev->target_fsc = DIGITAL_ATS_MAX_FSC; + else + ddev->target_fsc = digital_ats_fsc[fsdi]; + + ddev->curr_nfc_dep_pni = 0; + + rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443); + +exit: + dev_kfree_skb(resp); + kfree(target); + + if (rc) + digital_poll_next_tech(ddev); +} + +static int digital_in_send_rats(struct nfc_digital_dev *ddev, + struct nfc_target *target) +{ + int rc; + struct sk_buff *skb; + + skb = digital_skb_alloc(ddev, 2); + if (!skb) + return -ENOMEM; + + *skb_put(skb, 1) = DIGITAL_RATS_BYTE1; + *skb_put(skb, 1) = DIGITAL_RATS_PARAM; + + rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats, + target); + if (rc) + kfree_skb(skb); + + return rc; +} + static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, struct sk_buff *resp) { @@ -144,8 +212,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, goto exit_free_skb; } + target->sel_res = sel_res; + if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { nfc_proto = NFC_PROTO_MIFARE; + } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) { + rc = digital_in_send_rats(ddev, target); + if (rc) + goto exit; + /* + * Skip target_found and don't free it for now. This will be + * done when receiving the ATS + */ + goto exit_free_skb; } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { nfc_proto = NFC_PROTO_NFC_DEP; } else { @@ -153,8 +232,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, goto exit; } - target->sel_res = sel_res; - rc = digital_target_found(ddev, target, nfc_proto); exit: -- cgit From c813007f9ffb0b6e9f3dc43bfd9e28806aa57e5d Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Mon, 27 Jan 2014 00:31:32 +0100 Subject: NFC: digital: Add ISO-DEP support for data exchange When a type 4A target is activated, this change adds the ISO-DEP SoD when sending frames and removes it when receiving responses. Chaining is not supported so sent frames are rejected if they exceed remote FSC bytes. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/digital.h | 5 ++++ net/nfc/digital_core.c | 25 +++++++++++++++---- net/nfc/digital_technology.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 3c757dc7d44f..3759add68b1b 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h @@ -74,6 +74,11 @@ int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech); +int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev, + struct sk_buff *skb); +int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev, + struct sk_buff *skb); + int digital_target_found(struct nfc_digital_dev *ddev, struct nfc_target *target, u8 protocol); diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index e1f240266adf..5b440e7d9598 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -624,20 +624,30 @@ static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg, if (IS_ERR(resp)) { rc = PTR_ERR(resp); + resp = NULL; goto done; } - if (ddev->curr_protocol == NFC_PROTO_MIFARE) + if (ddev->curr_protocol == NFC_PROTO_MIFARE) { rc = digital_in_recv_mifare_res(resp); - else - rc = ddev->skb_check_crc(resp); + /* crc check is done in digital_in_recv_mifare_res() */ + goto done; + } + + if (ddev->curr_protocol == NFC_PROTO_ISO14443) { + rc = digital_in_iso_dep_pull_sod(ddev, resp); + if (rc) + goto done; + } + + rc = ddev->skb_check_crc(resp); +done: if (rc) { kfree_skb(resp); resp = NULL; } -done: data_exch->cb(data_exch->cb_context, resp, rc); kfree(data_exch); @@ -649,6 +659,7 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, { struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); struct digital_data_exch *data_exch; + int rc; data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL); if (!data_exch) { @@ -662,6 +673,12 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) return digital_in_send_dep_req(ddev, target, skb, data_exch); + if (ddev->curr_protocol == NFC_PROTO_ISO14443) { + rc = digital_in_iso_dep_push_sod(ddev, skb); + if (rc) + return rc; + } + ddev->skb_add_crc(skb); return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 6649d9461dff..278c3fed27e0 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c @@ -61,6 +61,15 @@ #define DIGITAL_ISO15693_RES_IS_VALID(flags) \ (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR)) +#define DIGITAL_ISO_DEP_I_PCB 0x02 +#define DIGITAL_ISO_DEP_PNI(pni) ((pni) & 0x01) + +#define DIGITAL_ISO_DEP_PCB_TYPE(pcb) ((pcb) & 0xC0) + +#define DIGITAL_ISO_DEP_I_BLOCK 0x00 + +#define DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb) ((pcb) & 0x08) + static const u8 digital_ats_fsc[] = { 16, 24, 32, 40, 48, 64, 96, 128, }; @@ -118,6 +127,54 @@ struct digital_iso15693_inv_res { static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, struct nfc_target *target); +int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev, + struct sk_buff *skb) +{ + u8 pcb; + u8 block_type; + + if (skb->len < 1) + return -EIO; + + pcb = *skb->data; + block_type = DIGITAL_ISO_DEP_PCB_TYPE(pcb); + + /* No support fo R-block nor S-block */ + if (block_type != DIGITAL_ISO_DEP_I_BLOCK) { + pr_err("ISO_DEP R-block and S-block not supported\n"); + return -EIO; + } + + if (DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb)) { + pr_err("DID field in ISO_DEP PCB not supported\n"); + return -EIO; + } + + skb_pull(skb, 1); + + return 0; +} + +int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev, + struct sk_buff *skb) +{ + /* + * Chaining not supported so skb->len + 1 PCB byte + 2 CRC bytes must + * not be greater than remote FSC + */ + if (skb->len + 3 > ddev->target_fsc) + return -EIO; + + skb_push(skb, 1); + + *skb->data = DIGITAL_ISO_DEP_I_PCB | ddev->curr_nfc_dep_pni; + + ddev->curr_nfc_dep_pni = + DIGITAL_ISO_DEP_PNI(ddev->curr_nfc_dep_pni + 1); + + return 0; +} + static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg, struct sk_buff *resp) { -- cgit From 564af14e36742f5900e40d48dcf30a3414acb143 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Wed, 12 Feb 2014 12:13:23 +0100 Subject: NFC: digital: Add missing break in switch statement There was a missing break making the digital stack configured for ISO1443 target instead of ISO15693. Reported-by: Dan Carpenter Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/digital_core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/nfc') diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 5b440e7d9598..10146e703270 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -337,6 +337,7 @@ int digital_target_found(struct nfc_digital_dev *ddev, framing = NFC_DIGITAL_FRAMING_ISO15693_TVT; check_crc = digital_skb_check_crc_b; add_crc = digital_skb_add_crc_b; + break; case NFC_PROTO_ISO14443: framing = NFC_DIGITAL_FRAMING_NFCA_T4T; -- cgit From 6ea7398d00345a33b47d905875416ca4421838de Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Wed, 12 Feb 2014 14:27:51 +0100 Subject: NFC: digital: Fix a possible memory leak This fixes a memory leak issue that may occur if data sending fails in initiator mode. The data_exch structure was not released in case of error. Reported-by: Dan Carpenter Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/digital_core.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 10146e703270..969a7f924a37 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -671,19 +671,27 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, data_exch->cb = cb; data_exch->cb_context = cb_context; - if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) - return digital_in_send_dep_req(ddev, target, skb, data_exch); + if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) { + rc = digital_in_send_dep_req(ddev, target, skb, data_exch); + goto exit; + } if (ddev->curr_protocol == NFC_PROTO_ISO14443) { rc = digital_in_iso_dep_push_sod(ddev, skb); if (rc) - return rc; + goto exit; } ddev->skb_add_crc(skb); - return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, - data_exch); + rc = digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, + data_exch); + +exit: + if (rc) + kfree(data_exch); + + return rc; } static struct nfc_ops digital_nfc_ops = { -- cgit From 9bec44bf0bcd623b5ea48ae1ce44205260ad4b77 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 13 Feb 2014 13:25:48 +0800 Subject: NFC: NCI: Use reinit_completion() at appropriate places Calling init_completion() once is enough. Then use reinit_completion() instead in __nci_request() and nci_spi_send(). Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- net/nfc/nci/core.c | 3 ++- net/nfc/nci/spi.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 46bda010bf11..28d07626b14d 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -74,7 +74,7 @@ static int __nci_request(struct nci_dev *ndev, ndev->req_status = NCI_REQ_PEND; - init_completion(&ndev->req_completion); + reinit_completion(&ndev->req_completion); req(ndev, opt); completion_rc = wait_for_completion_interruptible_timeout(&ndev->req_completion, @@ -709,6 +709,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, ndev->ops = ops; ndev->tx_headroom = tx_headroom; ndev->tx_tailroom = tx_tailroom; + init_completion(&ndev->req_completion); ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, supported_protocols, diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index f1d426f10cce..ec250e77763a 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c @@ -105,7 +105,7 @@ int nci_spi_send(struct nci_spi *nspi, if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) goto done; - init_completion(&nspi->req_completion); + reinit_completion(&nspi->req_completion); completion_rc = wait_for_completion_interruptible_timeout( &nspi->req_completion, NCI_SPI_SEND_TIMEOUT); @@ -145,6 +145,7 @@ struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, nspi->spi = spi; nspi->ndev = ndev; + init_completion(&nspi->req_completion); return nspi; } -- cgit From 156cef80f2a1aea4f150dff5d990e8fbbd96d862 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 14 Feb 2014 19:29:19 +0800 Subject: NFC: Use list_for_each_entry in nfc_find_se() nfc_find_se() does not modify any list entry while iterating the list. So use list_for_each_entry instead of list_for_each_entry_safe. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- net/nfc/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/core.c b/net/nfc/core.c index ca1e65f4b133..ada92316f723 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -546,9 +546,9 @@ error: struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx) { - struct nfc_se *se, *n; + struct nfc_se *se; - list_for_each_entry_safe(se, n, &dev->secure_elements, list) + list_for_each_entry(se, &dev->secure_elements, list) if (se->idx == se_idx) return se; -- cgit From 4f913d4631fa9c47320669b2e7ec62fa7436719d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 22 Feb 2014 10:16:11 +0800 Subject: NFC: digital: Use matching_[im|tm]_protocols to check with NFC protocols masks This ensures we won't add polling function to the table of polling technologies for non-supported protocols. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- net/nfc/digital_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 969a7f924a37..492fa7355e0d 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -475,7 +475,7 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, digital_in_send_sens_req); - if (im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { + if (matching_im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, digital_in_send_sensf_req); @@ -487,7 +487,7 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_ISO15693, digital_in_send_iso15693_inv_req); - if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { + if (matching_tm_protocols & NFC_PROTO_NFC_DEP_MASK) { if (ddev->ops->tg_listen_mdaa) { digital_add_poll_tech(ddev, 0, digital_tg_listen_mdaa); -- cgit From 0b51fc5633df563695f5021bc121a9df20b3eb14 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 22 Feb 2014 22:14:18 +0800 Subject: NFC: Use LIST_HEAD() at appropriate places Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- net/nfc/hci/llc.c | 4 +--- net/nfc/llcp_core.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/hci/llc.c b/net/nfc/hci/llc.c index a07d2b818487..1b90c0531852 100644 --- a/net/nfc/hci/llc.c +++ b/net/nfc/hci/llc.c @@ -20,14 +20,12 @@ #include "llc.h" -static struct list_head llc_engines; +static LIST_HEAD(llc_engines); int nfc_llc_init(void) { int r; - INIT_LIST_HEAD(&llc_engines); - r = nfc_llc_nop_register(); if (r) goto exit; diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 6184bd1fba3a..9d37dedec906 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -27,7 +27,7 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; -static struct list_head llcp_devices; +static LIST_HEAD(llcp_devices); static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb); @@ -1622,8 +1622,6 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) int __init nfc_llcp_init(void) { - INIT_LIST_HEAD(&llcp_devices); - return nfc_llcp_sock_init(); } -- cgit From ceeee42d85b4c91b16b6019e69c584589b72be04 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 6 Mar 2014 07:39:19 -0700 Subject: NFC: digital: Rename Type V tags to Type 5 tags According to the latest draft specification from the NFC-V committee, ISO/IEC 15693 tags will be referred to as "Type 5" tags and not "Type V" tags anymore. Make the code reflect the new terminology. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- net/nfc/digital_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/nfc') diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 492fa7355e0d..e01e15dbf1ab 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -334,7 +334,7 @@ int digital_target_found(struct nfc_digital_dev *ddev, break; case NFC_PROTO_ISO15693: - framing = NFC_DIGITAL_FRAMING_ISO15693_TVT; + framing = NFC_DIGITAL_FRAMING_ISO15693_T5T; check_crc = digital_skb_check_crc_b; add_crc = digital_skb_add_crc_b; break; -- cgit From 365a721adbdfe5f6577a66b9b74c12dc98fbb4a3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 24 Feb 2014 21:04:30 +0800 Subject: NFC: Remove redundant test for dev->n_targets in nfc_find_target Without this test, it returns NULL if dev->n_targets is 0 anyway. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- net/nfc/core.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/core.c b/net/nfc/core.c index ada92316f723..be5d50c6d81d 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -280,9 +280,6 @@ static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx) { int i; - if (dev->n_targets == 0) - return NULL; - for (i = 0; i < dev->n_targets; i++) { if (dev->targets[i].idx == target_idx) return &dev->targets[i]; -- cgit From 3143a4ca610d6a3de0d8814ee6f5f7da6fc7fbfa Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 25 Feb 2014 09:18:10 +0800 Subject: NFC: Move checking valid gb_len value to nfc_llcp_set_remote_gb This checking is common for all caller, so move the checking to one place. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- net/nfc/core.c | 3 --- net/nfc/llcp_core.c | 8 +++++--- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/core.c b/net/nfc/core.c index be5d50c6d81d..819b87702b70 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -652,9 +652,6 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) { pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len); - if (gb_len > NFC_MAX_GT_LEN) - return -EINVAL; - return nfc_llcp_set_remote_gb(dev, gb, gb_len); } EXPORT_SYMBOL(nfc_set_remote_general_bytes); diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 9d37dedec906..0cf9d4f45e6a 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -609,14 +609,16 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) { - struct nfc_llcp_local *local = nfc_llcp_find_local(dev); + struct nfc_llcp_local *local; + + if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN) + return -EINVAL; + local = nfc_llcp_find_local(dev); if (local == NULL) { pr_err("No LLCP device\n"); return -ENODEV; } - if (gb_len < 3) - return -EINVAL; memset(local->remote_gb, 0, NFC_MAX_GT_LEN); memcpy(local->remote_gb, gb, gb_len); -- cgit From 29e27dd86b5c4f8e6feb62d7b6a8491539ff1ef1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 26 Feb 2014 10:26:45 +0800 Subject: NFC: llcp: Use list_for_each_entry in nfc_llcp_find_local() nfc_llcp_find_local() does not modify any list entry while iterating the list. So use list_for_each_entry instead of list_for_each_entry_safe. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- net/nfc/llcp_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/nfc') diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 0cf9d4f45e6a..b486f12ae243 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -293,9 +293,9 @@ static void nfc_llcp_sdreq_timer(unsigned long data) struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) { - struct nfc_llcp_local *local, *n; + struct nfc_llcp_local *local; - list_for_each_entry_safe(local, n, &llcp_devices, list) + list_for_each_entry(local, &llcp_devices, list) if (local->dev == dev) return local; -- cgit