diff options
| author | John W. Linville <linville@tuxdriver.com> | 2014-03-17 13:16:50 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2014-03-17 13:16:50 -0400 |
| commit | 20d83f2464c0d1e27b24d654aa5495dcc44759c0 (patch) | |
| tree | a6c36d9e48920f6d81b7dac9ad6b1f99dfdaf592 /net/nfc/digital_technology.c | |
| parent | 5f667642f4b290b04d88d5ca926fba81fed6180d (diff) | |
| parent | 29e27dd86b5c4f8e6feb62d7b6a8491539ff1ef1 (diff) | |
Merge tag 'nfc-next-3.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next
Samuel Ortiz <sameo@linux.intel.com> says:
"NFC: 3.15: First pull request
This is the NFC pull request for 3.15. With this one we have:
- Support for ISO 15693 a.k.a. NFC vicinity a.k.a. Type 5 tags. ISO
15693 are long range (1 - 2 meters) vicinity tags/cards. The kernel
now supports those through the NFC netlink and digital APIs.
- Support for TI's trf7970a chipset. This chipset relies on the NFC
digital layer and the driver currently supports type 2, 4A and 5 tags.
- Support for NXP's pn544 secure firmare download. The pn544 C3 chipsets
relies on a different firmware download protocal than the C2 one. We
now support both and use the right one depending on the version we
detect at runtime.
- Support for 4A tags from the NFC digital layer.
- A bunch of cleanups and minor fixes from Axel Lin and Thierry Escande."
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/nfc/digital_technology.c')
| -rw-r--r-- | net/nfc/digital_technology.c | 247 |
1 files changed, 245 insertions, 2 deletions
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 251c8c753ebe..278c3fed27e0 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) | 31 | #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) |
| 32 | #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) | 32 | #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) |
| 33 | #define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20) | ||
| 33 | #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) | 34 | #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) |
| 34 | 35 | ||
| 35 | #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) | 36 | #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) |
| @@ -51,6 +52,34 @@ | |||
| 51 | #define DIGITAL_SENSF_REQ_RC_SC 1 | 52 | #define DIGITAL_SENSF_REQ_RC_SC 1 |
| 52 | #define DIGITAL_SENSF_REQ_RC_AP 2 | 53 | #define DIGITAL_SENSF_REQ_RC_AP 2 |
| 53 | 54 | ||
| 55 | #define DIGITAL_CMD_ISO15693_INVENTORY_REQ 0x01 | ||
| 56 | |||
| 57 | #define DIGITAL_ISO15693_REQ_FLAG_DATA_RATE BIT(1) | ||
| 58 | #define DIGITAL_ISO15693_REQ_FLAG_INVENTORY BIT(2) | ||
| 59 | #define DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS BIT(5) | ||
| 60 | #define DIGITAL_ISO15693_RES_FLAG_ERROR BIT(0) | ||
| 61 | #define DIGITAL_ISO15693_RES_IS_VALID(flags) \ | ||
| 62 | (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR)) | ||
| 63 | |||
| 64 | #define DIGITAL_ISO_DEP_I_PCB 0x02 | ||
| 65 | #define DIGITAL_ISO_DEP_PNI(pni) ((pni) & 0x01) | ||
| 66 | |||
| 67 | #define DIGITAL_ISO_DEP_PCB_TYPE(pcb) ((pcb) & 0xC0) | ||
| 68 | |||
| 69 | #define DIGITAL_ISO_DEP_I_BLOCK 0x00 | ||
| 70 | |||
| 71 | #define DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb) ((pcb) & 0x08) | ||
| 72 | |||
| 73 | static const u8 digital_ats_fsc[] = { | ||
| 74 | 16, 24, 32, 40, 48, 64, 96, 128, | ||
| 75 | }; | ||
| 76 | |||
| 77 | #define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F) | ||
| 78 | #define DIGITAL_ATS_MAX_FSC 256 | ||
| 79 | |||
| 80 | #define DIGITAL_RATS_BYTE1 0xE0 | ||
| 81 | #define DIGITAL_RATS_PARAM 0x80 | ||
| 82 | |||
| 54 | struct digital_sdd_res { | 83 | struct digital_sdd_res { |
| 55 | u8 nfcid1[4]; | 84 | u8 nfcid1[4]; |
| 56 | u8 bcc; | 85 | u8 bcc; |
| @@ -82,9 +111,127 @@ struct digital_sensf_res { | |||
| 82 | u8 rd[2]; | 111 | u8 rd[2]; |
| 83 | } __packed; | 112 | } __packed; |
| 84 | 113 | ||
| 114 | struct digital_iso15693_inv_req { | ||
| 115 | u8 flags; | ||
| 116 | u8 cmd; | ||
| 117 | u8 mask_len; | ||
| 118 | u64 mask; | ||
| 119 | } __packed; | ||
| 120 | |||
| 121 | struct digital_iso15693_inv_res { | ||
| 122 | u8 flags; | ||
| 123 | u8 dsfid; | ||
| 124 | u64 uid; | ||
| 125 | } __packed; | ||
| 126 | |||
| 85 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, | 127 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, |
| 86 | struct nfc_target *target); | 128 | struct nfc_target *target); |
| 87 | 129 | ||
| 130 | int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev, | ||
| 131 | struct sk_buff *skb) | ||
| 132 | { | ||
| 133 | u8 pcb; | ||
| 134 | u8 block_type; | ||
| 135 | |||
| 136 | if (skb->len < 1) | ||
| 137 | return -EIO; | ||
| 138 | |||
| 139 | pcb = *skb->data; | ||
| 140 | block_type = DIGITAL_ISO_DEP_PCB_TYPE(pcb); | ||
| 141 | |||
| 142 | /* No support fo R-block nor S-block */ | ||
| 143 | if (block_type != DIGITAL_ISO_DEP_I_BLOCK) { | ||
| 144 | pr_err("ISO_DEP R-block and S-block not supported\n"); | ||
| 145 | return -EIO; | ||
| 146 | } | ||
| 147 | |||
| 148 | if (DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb)) { | ||
| 149 | pr_err("DID field in ISO_DEP PCB not supported\n"); | ||
| 150 | return -EIO; | ||
| 151 | } | ||
| 152 | |||
| 153 | skb_pull(skb, 1); | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev, | ||
| 159 | struct sk_buff *skb) | ||
| 160 | { | ||
| 161 | /* | ||
| 162 | * Chaining not supported so skb->len + 1 PCB byte + 2 CRC bytes must | ||
| 163 | * not be greater than remote FSC | ||
| 164 | */ | ||
| 165 | if (skb->len + 3 > ddev->target_fsc) | ||
| 166 | return -EIO; | ||
| 167 | |||
| 168 | skb_push(skb, 1); | ||
| 169 | |||
| 170 | *skb->data = DIGITAL_ISO_DEP_I_PCB | ddev->curr_nfc_dep_pni; | ||
| 171 | |||
| 172 | ddev->curr_nfc_dep_pni = | ||
| 173 | DIGITAL_ISO_DEP_PNI(ddev->curr_nfc_dep_pni + 1); | ||
| 174 | |||
| 175 | return 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg, | ||
| 179 | struct sk_buff *resp) | ||
| 180 | { | ||
| 181 | struct nfc_target *target = arg; | ||
| 182 | u8 fsdi; | ||
| 183 | int rc; | ||
| 184 | |||
| 185 | if (IS_ERR(resp)) { | ||
| 186 | rc = PTR_ERR(resp); | ||
| 187 | resp = NULL; | ||
| 188 | goto exit; | ||
| 189 | } | ||
| 190 | |||
| 191 | if (resp->len < 2) { | ||
| 192 | rc = -EIO; | ||
| 193 | goto exit; | ||
| 194 | } | ||
| 195 | |||
| 196 | fsdi = DIGITAL_ATS_FSCI(resp->data[1]); | ||
| 197 | if (fsdi >= 8) | ||
| 198 | ddev->target_fsc = DIGITAL_ATS_MAX_FSC; | ||
| 199 | else | ||
| 200 | ddev->target_fsc = digital_ats_fsc[fsdi]; | ||
| 201 | |||
| 202 | ddev->curr_nfc_dep_pni = 0; | ||
| 203 | |||
| 204 | rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443); | ||
| 205 | |||
| 206 | exit: | ||
| 207 | dev_kfree_skb(resp); | ||
| 208 | kfree(target); | ||
| 209 | |||
| 210 | if (rc) | ||
| 211 | digital_poll_next_tech(ddev); | ||
| 212 | } | ||
| 213 | |||
| 214 | static int digital_in_send_rats(struct nfc_digital_dev *ddev, | ||
| 215 | struct nfc_target *target) | ||
| 216 | { | ||
| 217 | int rc; | ||
| 218 | struct sk_buff *skb; | ||
| 219 | |||
| 220 | skb = digital_skb_alloc(ddev, 2); | ||
| 221 | if (!skb) | ||
| 222 | return -ENOMEM; | ||
| 223 | |||
| 224 | *skb_put(skb, 1) = DIGITAL_RATS_BYTE1; | ||
| 225 | *skb_put(skb, 1) = DIGITAL_RATS_PARAM; | ||
| 226 | |||
| 227 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats, | ||
| 228 | target); | ||
| 229 | if (rc) | ||
| 230 | kfree_skb(skb); | ||
| 231 | |||
| 232 | return rc; | ||
| 233 | } | ||
| 234 | |||
| 88 | static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | 235 | static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, |
| 89 | struct sk_buff *resp) | 236 | struct sk_buff *resp) |
| 90 | { | 237 | { |
| @@ -122,8 +269,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
| 122 | goto exit_free_skb; | 269 | goto exit_free_skb; |
| 123 | } | 270 | } |
| 124 | 271 | ||
| 272 | target->sel_res = sel_res; | ||
| 273 | |||
| 125 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { | 274 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { |
| 126 | nfc_proto = NFC_PROTO_MIFARE; | 275 | nfc_proto = NFC_PROTO_MIFARE; |
| 276 | } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) { | ||
| 277 | rc = digital_in_send_rats(ddev, target); | ||
| 278 | if (rc) | ||
| 279 | goto exit; | ||
| 280 | /* | ||
| 281 | * Skip target_found and don't free it for now. This will be | ||
| 282 | * done when receiving the ATS | ||
| 283 | */ | ||
| 284 | goto exit_free_skb; | ||
| 127 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { | 285 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { |
| 128 | nfc_proto = NFC_PROTO_NFC_DEP; | 286 | nfc_proto = NFC_PROTO_NFC_DEP; |
| 129 | } else { | 287 | } else { |
| @@ -131,8 +289,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
| 131 | goto exit; | 289 | goto exit; |
| 132 | } | 290 | } |
| 133 | 291 | ||
| 134 | target->sel_res = sel_res; | ||
| 135 | |||
| 136 | rc = digital_target_found(ddev, target, nfc_proto); | 292 | rc = digital_target_found(ddev, target, nfc_proto); |
| 137 | 293 | ||
| 138 | exit: | 294 | exit: |
| @@ -473,6 +629,93 @@ int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech) | |||
| 473 | return rc; | 629 | return rc; |
| 474 | } | 630 | } |
| 475 | 631 | ||
| 632 | static void digital_in_recv_iso15693_inv_res(struct nfc_digital_dev *ddev, | ||
| 633 | void *arg, struct sk_buff *resp) | ||
| 634 | { | ||
| 635 | struct digital_iso15693_inv_res *res; | ||
| 636 | struct nfc_target *target = NULL; | ||
| 637 | int rc; | ||
| 638 | |||
| 639 | if (IS_ERR(resp)) { | ||
| 640 | rc = PTR_ERR(resp); | ||
| 641 | resp = NULL; | ||
| 642 | goto out_free_skb; | ||
| 643 | } | ||
| 644 | |||
| 645 | if (resp->len != sizeof(*res)) { | ||
| 646 | rc = -EIO; | ||
| 647 | goto out_free_skb; | ||
| 648 | } | ||
| 649 | |||
| 650 | res = (struct digital_iso15693_inv_res *)resp->data; | ||
| 651 | |||
| 652 | if (!DIGITAL_ISO15693_RES_IS_VALID(res->flags)) { | ||
| 653 | PROTOCOL_ERR("ISO15693 - 10.3.1"); | ||
| 654 | rc = -EINVAL; | ||
| 655 | goto out_free_skb; | ||
| 656 | } | ||
| 657 | |||
| 658 | target = kzalloc(sizeof(*target), GFP_KERNEL); | ||
| 659 | if (!target) { | ||
| 660 | rc = -ENOMEM; | ||
| 661 | goto out_free_skb; | ||
| 662 | } | ||
| 663 | |||
| 664 | target->is_iso15693 = 1; | ||
| 665 | target->iso15693_dsfid = res->dsfid; | ||
| 666 | memcpy(target->iso15693_uid, &res->uid, sizeof(target->iso15693_uid)); | ||
| 667 | |||
| 668 | rc = digital_target_found(ddev, target, NFC_PROTO_ISO15693); | ||
| 669 | |||
| 670 | kfree(target); | ||
| 671 | |||
| 672 | out_free_skb: | ||
| 673 | dev_kfree_skb(resp); | ||
| 674 | |||
| 675 | if (rc) | ||
| 676 | digital_poll_next_tech(ddev); | ||
| 677 | } | ||
| 678 | |||
| 679 | int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
| 680 | { | ||
| 681 | struct digital_iso15693_inv_req *req; | ||
| 682 | struct sk_buff *skb; | ||
| 683 | int rc; | ||
| 684 | |||
| 685 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, | ||
| 686 | NFC_DIGITAL_RF_TECH_ISO15693); | ||
| 687 | if (rc) | ||
| 688 | return rc; | ||
| 689 | |||
| 690 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 691 | NFC_DIGITAL_FRAMING_ISO15693_INVENTORY); | ||
| 692 | if (rc) | ||
| 693 | return rc; | ||
| 694 | |||
| 695 | skb = digital_skb_alloc(ddev, sizeof(*req)); | ||
| 696 | if (!skb) | ||
| 697 | return -ENOMEM; | ||
| 698 | |||
| 699 | skb_put(skb, sizeof(*req) - sizeof(req->mask)); /* No mask */ | ||
| 700 | req = (struct digital_iso15693_inv_req *)skb->data; | ||
| 701 | |||
| 702 | /* Single sub-carrier, high data rate, no AFI, single slot | ||
| 703 | * Inventory command | ||
| 704 | */ | ||
| 705 | req->flags = DIGITAL_ISO15693_REQ_FLAG_DATA_RATE | | ||
| 706 | DIGITAL_ISO15693_REQ_FLAG_INVENTORY | | ||
| 707 | DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS; | ||
| 708 | req->cmd = DIGITAL_CMD_ISO15693_INVENTORY_REQ; | ||
| 709 | req->mask_len = 0; | ||
| 710 | |||
| 711 | rc = digital_in_send_cmd(ddev, skb, 30, | ||
| 712 | digital_in_recv_iso15693_inv_res, NULL); | ||
| 713 | if (rc) | ||
| 714 | kfree_skb(skb); | ||
| 715 | |||
| 716 | return rc; | ||
| 717 | } | ||
| 718 | |||
| 476 | static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) | 719 | static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) |
| 477 | { | 720 | { |
| 478 | struct sk_buff *skb; | 721 | struct sk_buff *skb; |
