Received: by 2002:ac0:98c7:0:0:0:0:0 with SMTP id g7-v6csp630502imd; Thu, 1 Nov 2018 03:04:36 -0700 (PDT) X-Google-Smtp-Source: AJdET5eM2LTmZwGZqfWZTDVgptV1U9ULYg2dIs4rrPc4nH+dJsLWKcJJSk46Z4t98GWMFgFuODnk X-Received: by 2002:a62:500c:: with SMTP id e12-v6mr7214319pfb.30.1541066676346; Thu, 01 Nov 2018 03:04:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1541066676; cv=none; d=google.com; s=arc-20160816; b=nWZvkhxiLfLmXms8k+nZNrTcnmg7jRhWqRydOU98ZmBwEH+Fw534sdSF2+ilJfWqQr 0NvgskcA77r8Yhw3Qo9WBELjjVk0D4NLhbPR6ntmo37xBlpzVqeuIHh1yylOeSu4JlBx F8NepxLvUIccswOPARKAwWSk+8Qz+lw5lVmEtG34ldMUYv/ngP9rAke6PD680vpSUqmH KBSRQcHUfrVJU3UZihcVns+6AH1D+3Aw9UHcx145hYiBaKewwlsfzH+1LbzmvGKsnRo4 1qRevCyLzrQ2BP1e6LRpO+r8VRj5d2y1ZBh1S90auw0UL6rBE4kUa7/5mpsZeO2sjHVy KDeQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:to:from; bh=d8eIuU3MBpu3DPYNvMbWQy5fP/lgog7WSuvbCr4Pkvk=; b=CM95rrZJROJD8jCkY+Ikwt9gwwkDrk0kyCe6OHkLgLhXn2oD/SVTF25UdrGq3sl53a hMRAlNVMhCJipJWPAGuS4w3Fx+D3D/zrDi5x7KydsdzUz08whk+piqZIq603VwhLM0wW O1j34HQL0C3rY4ivRybOfLqFOArMvO4HxDTKrOW6UnFjAby6iKYKebrkvZxcEkL2X02R aeaiVK+2h3Nx45chFpgKCXxM0F0JdGEdjnphcsrK78vlpOKIwEMpQawv4kSFEwq4jXPB MxRIo21qOCbtHEF1rbC4GO8l2Lz70MCdIcgzj/wwZru3F1XBT/qv9CT7zyWzeY0al7Or P8bA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 134-v6si30395855pfu.273.2018.11.01.03.04.20; Thu, 01 Nov 2018 03:04:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728328AbeKATGJ (ORCPT + 99 others); Thu, 1 Nov 2018 15:06:09 -0400 Received: from smtp3-1.goneo.de ([85.220.129.38]:59255 "EHLO smtp3-1.goneo.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727875AbeKATGI (ORCPT ); Thu, 1 Nov 2018 15:06:08 -0400 Received: from localhost (localhost [127.0.0.1]) by smtp3.goneo.de (Postfix) with ESMTP id 22A5823F020; Thu, 1 Nov 2018 11:03:48 +0100 (CET) X-Virus-Scanned: by goneo X-Spam-Flag: NO X-Spam-Score: -3.098 X-Spam-Level: X-Spam-Status: No, score=-3.098 tagged_above=-999 tests=[ALL_TRUSTED=-1, AWL=-0.198, BAYES_00=-1.9] autolearn=ham Received: from smtp3.goneo.de ([127.0.0.1]) by localhost (smtp3.goneo.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id dKwWfsCqXITZ; Thu, 1 Nov 2018 11:03:46 +0100 (CET) Received: from lem-wkst-02.lemonage.de. (hq.lemonage.de [87.138.178.34]) by smtp3.goneo.de (Postfix) with ESMTPA id 7E49623F3BB; Thu, 1 Nov 2018 11:03:46 +0100 (CET) From: Lars Poeschel To: devicetree@vger.kernel.org, Samuel Ortiz , Kees Cook , Lars Poeschel , linux-wireless@vger.kernel.org (open list:NFC SUBSYSTEM), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v4 5/6] nfc: pn533: Add autopoll capability Date: Thu, 1 Nov 2018 11:02:13 +0100 Message-Id: <20181101100216.613-5-poeschel@lemonage.de> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181101100216.613-1-poeschel@lemonage.de> References: <20181101100216.613-1-poeschel@lemonage.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org pn532 devices support an autopoll command, that lets the chip automatically poll for selected nfc technologies instead of manually looping through every single nfc technology the user is interested in. This is faster and less cpu and bus intensive than manually polling. This adds this autopoll capability to the pn533 driver. Signed-off-by: Lars Poeschel --- drivers/nfc/pn533/pn533.c | 193 +++++++++++++++++++++++++++++++++++++- drivers/nfc/pn533/pn533.h | 10 +- 2 files changed, 197 insertions(+), 6 deletions(-) diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c index f0c541152777..8c21ee72832f 100644 --- a/drivers/nfc/pn533/pn533.c +++ b/drivers/nfc/pn533/pn533.c @@ -197,6 +197,32 @@ struct pn533_cmd_jump_dep_response { u8 gt[]; } __packed; +struct pn532_autopoll_resp { + u8 type; + u8 ln; + u8 tg; + u8 tgdata[]; +} __packed; + +/* PN532_CMD_IN_AUTOPOLL */ +#define PN532_AUTOPOLL_POLLNR_INFINITE 0xff +#define PN532_AUTOPOLL_PERIOD 0x03 /* in units of 150 ms */ + +#define PN532_AUTOPOLL_TYPE_GENERIC_106 0x00 +#define PN532_AUTOPOLL_TYPE_GENERIC_212 0x01 +#define PN532_AUTOPOLL_TYPE_GENERIC_424 0x02 +#define PN532_AUTOPOLL_TYPE_JEWEL 0x04 +#define PN532_AUTOPOLL_TYPE_MIFARE 0x10 +#define PN532_AUTOPOLL_TYPE_FELICA212 0x11 +#define PN532_AUTOPOLL_TYPE_FELICA424 0x12 +#define PN532_AUTOPOLL_TYPE_ISOA 0x20 +#define PN532_AUTOPOLL_TYPE_ISOB 0x23 +#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106 0x40 +#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212 0x41 +#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424 0x42 +#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106 0x80 +#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_212 0x81 +#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_424 0x82 /* PN533_TG_INIT_AS_TARGET */ #define PN533_INIT_TARGET_PASSIVE 0x1 @@ -1401,6 +1427,101 @@ static int pn533_poll_dep(struct nfc_dev *nfc_dev) return rc; } +static int pn533_autopoll_complete(struct pn533 *dev, void *arg, + struct sk_buff *resp) +{ + u8 nbtg; + int rc; + struct pn532_autopoll_resp *apr; + struct nfc_target nfc_tgt; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + + nfc_err(dev->dev, "%s autopoll complete error %d\n", + __func__, rc); + + if (rc == -ENOENT) { + if (dev->poll_mod_count != 0) + return rc; + goto stop_poll; + } else if (rc < 0) { + nfc_err(dev->dev, + "Error %d when running autopoll\n", rc); + goto stop_poll; + } + } + + nbtg = resp->data[0]; + if ((nbtg > 2) || (nbtg <= 0)) + return -EAGAIN; + + apr = (struct pn532_autopoll_resp *)&resp->data[1]; + while (nbtg--) { + memset(&nfc_tgt, 0, sizeof(struct nfc_target)); + switch (apr->type) { + case PN532_AUTOPOLL_TYPE_ISOA: + dev_dbg(dev->dev, "ISOA"); + rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_FELICA212: + case PN532_AUTOPOLL_TYPE_FELICA424: + dev_dbg(dev->dev, "FELICA"); + rc = pn533_target_found_felica(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_JEWEL: + dev_dbg(dev->dev, "JEWEL"); + rc = pn533_target_found_jewel(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_ISOB: + dev_dbg(dev->dev, "ISOB"); + rc = pn533_target_found_type_b(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_MIFARE: + dev_dbg(dev->dev, "Mifare"); + rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + default: + nfc_err(dev->dev, + "Unknown current poll modulation"); + rc = -EPROTO; + } + + if (rc) + goto done; + + if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { + nfc_err(dev->dev, + "The Tg found doesn't have the desired protocol"); + rc = -EAGAIN; + goto done; + } + + dev->tgt_available_prots = nfc_tgt.supported_protocols; + apr = (struct pn532_autopoll_resp *) + (apr->tgdata + (apr->ln - 1)); + } + + pn533_poll_reset_mod_list(dev); + nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1); + +done: + dev_kfree_skb(resp); + return rc; + +stop_poll: + nfc_err(dev->dev, "autopoll operation has been stopped\n"); + + pn533_poll_reset_mod_list(dev); + dev->poll_protocols = 0; + return rc; +} + static int pn533_poll_complete(struct pn533 *dev, void *arg, struct sk_buff *resp) { @@ -1546,6 +1667,7 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, struct pn533_poll_modulations *cur_mod; u8 rand_mod; int rc; + struct sk_buff *skb; dev_dbg(dev->dev, "%s: im protocols 0x%x tm protocols 0x%x\n", @@ -1569,9 +1691,73 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, tm_protocols = 0; } - pn533_poll_create_mod_list(dev, im_protocols, tm_protocols); dev->poll_protocols = im_protocols; dev->listen_protocols = tm_protocols; + if (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL) { + skb = pn533_alloc_skb(dev, 4 + 6); + if (!skb) + return -ENOMEM; + + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_POLLNR_INFINITE; + *((u8 *)skb_put(skb, sizeof(u8))) = PN532_AUTOPOLL_PERIOD; + + if ((im_protocols & NFC_PROTO_MIFARE_MASK) && + (im_protocols & NFC_PROTO_ISO14443_MASK) && + (im_protocols & NFC_PROTO_NFC_DEP_MASK)) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_GENERIC_106; + else { + if (im_protocols & NFC_PROTO_MIFARE_MASK) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_MIFARE; + + if (im_protocols & NFC_PROTO_ISO14443_MASK) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_ISOA; + + if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106; + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212; + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424; + } + } + + if (im_protocols & NFC_PROTO_FELICA_MASK || + im_protocols & NFC_PROTO_NFC_DEP_MASK) { + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_FELICA212; + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_FELICA424; + } + + if (im_protocols & NFC_PROTO_JEWEL_MASK) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_JEWEL; + + if (im_protocols & NFC_PROTO_ISO14443_B_MASK) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_ISOB; + + if (tm_protocols) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106; + + rc = pn533_send_cmd_async(dev, PN533_CMD_IN_AUTOPOLL, skb, + pn533_autopoll_complete, NULL); + + if (rc < 0) + dev_kfree_skb(skb); + else + dev->poll_mod_count++; + + return rc; + } + + pn533_poll_create_mod_list(dev, im_protocols, tm_protocols); /* Do not always start polling from the same modulation */ get_random_bytes(&rand_mod, sizeof(rand_mod)); @@ -2471,7 +2657,8 @@ static int pn533_dev_up(struct nfc_dev *nfc_dev) if (dev->phy_ops) dev->phy_ops->dev_up(dev); - if (dev->device_type == PN533_DEVICE_PN532) { + if ((dev->device_type == PN533_DEVICE_PN532) || + (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL)) { int rc = pn532_sam_configuration(nfc_dev); if (rc) @@ -2518,6 +2705,7 @@ static int pn533_setup(struct pn533 *dev) case PN533_DEVICE_PASORI: case PN533_DEVICE_ACR122U: case PN533_DEVICE_PN532: + case PN533_DEVICE_PN532_AUTOPOLL: max_retries.mx_rty_atr = 0x2; max_retries.mx_rty_psl = 0x1; max_retries.mx_rty_passive_act = @@ -2554,6 +2742,7 @@ static int pn533_setup(struct pn533 *dev) switch (dev->device_type) { case PN533_DEVICE_STD: case PN533_DEVICE_PN532: + case PN533_DEVICE_PN532_AUTOPOLL: break; case PN533_DEVICE_PASORI: diff --git a/drivers/nfc/pn533/pn533.h b/drivers/nfc/pn533/pn533.h index d1a0543f66a8..e0636263911d 100644 --- a/drivers/nfc/pn533/pn533.h +++ b/drivers/nfc/pn533/pn533.h @@ -18,10 +18,11 @@ * along with this program; if not, see . */ -#define PN533_DEVICE_STD 0x1 -#define PN533_DEVICE_PASORI 0x2 -#define PN533_DEVICE_ACR122U 0x3 -#define PN533_DEVICE_PN532 0x4 +#define PN533_DEVICE_STD 0x1 +#define PN533_DEVICE_PASORI 0x2 +#define PN533_DEVICE_ACR122U 0x3 +#define PN533_DEVICE_PN532 0x4 +#define PN533_DEVICE_PN532_AUTOPOLL 0x5 #define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\ NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\ @@ -87,6 +88,7 @@ #define PN533_CMD_IN_ATR 0x50 #define PN533_CMD_IN_RELEASE 0x52 #define PN533_CMD_IN_JUMP_FOR_DEP 0x56 +#define PN533_CMD_IN_AUTOPOLL 0x60 #define PN533_CMD_TG_INIT_AS_TARGET 0x8c #define PN533_CMD_TG_GET_DATA 0x86 -- 2.19.1