Commit 53cf48399ad3b08c9115b4fce73dee0b6e726c91

Authored by Waldemar Rymarkiewicz
Committed by Samuel Ortiz
1 parent 58520373d8

NFC: pn533: Add support for ACS ACR122U reader

ACS ACR122U is an USB NFC reader, PC/SC and CCID compilant, based
on NXP PN532 chip.

Internally, it's build of MCU, PN532 and an antenna. MCU makes the
device CCID and PC/SC compilant and provide USB connection.

In this achitecture, a host cannot talk directly to PN532 and must
rely on MCU. Luckily, MCU exposes pseud-APDU through PC/SC Escape
mechanism which let the host to transmit standard PN532 commands
directly to PN532 chip with some limitations.

The frame roughly looks like:

    CCID header    |          APDU header           |    PN532 header
(pc_to_rdr_escape) |  (pseudo apdu Direct Tramsmit) | (len, TFI, cmd, params)

Accordign to limitations, ACR122U does't provide any mechanism to
abort last issued command.

Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

Showing 1 changed file with 217 additions and 2 deletions Side-by-side Diff

... ... @@ -38,9 +38,13 @@
38 38 #define SONY_VENDOR_ID 0x054c
39 39 #define PASORI_PRODUCT_ID 0x02e1
40 40  
41   -#define PN533_DEVICE_STD 0x1
42   -#define PN533_DEVICE_PASORI 0x2
  41 +#define ACS_VENDOR_ID 0x072f
  42 +#define ACR122U_PRODUCT_ID 0x2200
43 43  
  44 +#define PN533_DEVICE_STD 0x1
  45 +#define PN533_DEVICE_PASORI 0x2
  46 +#define PN533_DEVICE_ACR122U 0x3
  47 +
44 48 #define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\
45 49 NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\
46 50 NFC_PROTO_NFC_DEP_MASK |\
... ... @@ -68,6 +72,11 @@
68 72 .idProduct = PASORI_PRODUCT_ID,
69 73 .driver_info = PN533_DEVICE_PASORI,
70 74 },
  75 + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
  76 + .idVendor = ACS_VENDOR_ID,
  77 + .idProduct = ACR122U_PRODUCT_ID,
  78 + .driver_info = PN533_DEVICE_ACR122U,
  79 + },
71 80 { }
72 81 };
73 82 MODULE_DEVICE_TABLE(usb, pn533_table);
... ... @@ -99,6 +108,21 @@
99 108 #define PN533_STD_FRAME_DIR_OUT 0xD4
100 109 #define PN533_STD_FRAME_DIR_IN 0xD5
101 110  
  111 +/* ACS ACR122 pn533 frame definitions */
  112 +#define PN533_ACR122_TX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_tx_frame) \
  113 + + 2)
  114 +#define PN533_ACR122_TX_FRAME_TAIL_LEN 0
  115 +#define PN533_ACR122_RX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_rx_frame) \
  116 + + 2)
  117 +#define PN533_ACR122_RX_FRAME_TAIL_LEN 2
  118 +#define PN533_ACR122_FRAME_MAX_PAYLOAD_LEN PN533_STD_FRAME_MAX_PAYLOAD_LEN
  119 +
  120 +/* CCID messages types */
  121 +#define PN533_ACR122_PC_TO_RDR_ICCPOWERON 0x62
  122 +#define PN533_ACR122_PC_TO_RDR_ESCAPE 0x6B
  123 +
  124 +#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83
  125 +
102 126 /* PN533 Commands */
103 127 #define PN533_STD_FRAME_CMD(f) (f->data[1])
104 128  
... ... @@ -394,6 +418,116 @@
394 418 u8 (*get_cmd_code)(void *frame);
395 419 };
396 420  
  421 +struct pn533_acr122_ccid_hdr {
  422 + u8 type;
  423 + u32 datalen;
  424 + u8 slot;
  425 + u8 seq;
  426 + u8 params[3]; /* 3 msg specific bytes or status, error and 1 specific
  427 + byte for reposnse msg */
  428 + u8 data[]; /* payload */
  429 +} __packed;
  430 +
  431 +struct pn533_acr122_apdu_hdr {
  432 + u8 class;
  433 + u8 ins;
  434 + u8 p1;
  435 + u8 p2;
  436 +} __packed;
  437 +
  438 +struct pn533_acr122_tx_frame {
  439 + struct pn533_acr122_ccid_hdr ccid;
  440 + struct pn533_acr122_apdu_hdr apdu;
  441 + u8 datalen;
  442 + u8 data[]; /* pn533 frame: TFI ... */
  443 +} __packed;
  444 +
  445 +struct pn533_acr122_rx_frame {
  446 + struct pn533_acr122_ccid_hdr ccid;
  447 + u8 data[]; /* pn533 frame : TFI ... */
  448 +} __packed;
  449 +
  450 +static void pn533_acr122_tx_frame_init(void *_frame, u8 cmd_code)
  451 +{
  452 + struct pn533_acr122_tx_frame *frame = _frame;
  453 +
  454 + frame->ccid.type = PN533_ACR122_PC_TO_RDR_ESCAPE;
  455 + frame->ccid.datalen = sizeof(frame->apdu) + 1; /* sizeof(apdu_hdr) +
  456 + sizeof(datalen) */
  457 + frame->ccid.slot = 0;
  458 + frame->ccid.seq = 0;
  459 + frame->ccid.params[0] = 0;
  460 + frame->ccid.params[1] = 0;
  461 + frame->ccid.params[2] = 0;
  462 +
  463 + frame->data[0] = PN533_STD_FRAME_DIR_OUT;
  464 + frame->data[1] = cmd_code;
  465 + frame->datalen = 2; /* data[0] + data[1] */
  466 +
  467 + frame->apdu.class = 0xFF;
  468 + frame->apdu.ins = 0;
  469 + frame->apdu.p1 = 0;
  470 + frame->apdu.p2 = 0;
  471 +}
  472 +
  473 +static void pn533_acr122_tx_frame_finish(void *_frame)
  474 +{
  475 + struct pn533_acr122_tx_frame *frame = _frame;
  476 +
  477 + frame->ccid.datalen += frame->datalen;
  478 +}
  479 +
  480 +static void pn533_acr122_tx_update_payload_len(void *_frame, int len)
  481 +{
  482 + struct pn533_acr122_tx_frame *frame = _frame;
  483 +
  484 + frame->datalen += len;
  485 +}
  486 +
  487 +static bool pn533_acr122_is_rx_frame_valid(void *_frame)
  488 +{
  489 + struct pn533_acr122_rx_frame *frame = _frame;
  490 +
  491 + if (frame->ccid.type != 0x83)
  492 + return false;
  493 +
  494 + if (frame->data[frame->ccid.datalen - 2] == 0x63)
  495 + return false;
  496 +
  497 + return true;
  498 +}
  499 +
  500 +static int pn533_acr122_rx_frame_size(void *frame)
  501 +{
  502 + struct pn533_acr122_rx_frame *f = frame;
  503 +
  504 + /* f->ccid.datalen already includes tail length */
  505 + return sizeof(struct pn533_acr122_rx_frame) + f->ccid.datalen;
  506 +}
  507 +
  508 +static u8 pn533_acr122_get_cmd_code(void *frame)
  509 +{
  510 + struct pn533_acr122_rx_frame *f = frame;
  511 +
  512 + return PN533_STD_FRAME_CMD(f);
  513 +}
  514 +
  515 +static struct pn533_frame_ops pn533_acr122_frame_ops = {
  516 + .tx_frame_init = pn533_acr122_tx_frame_init,
  517 + .tx_frame_finish = pn533_acr122_tx_frame_finish,
  518 + .tx_update_payload_len = pn533_acr122_tx_update_payload_len,
  519 + .tx_header_len = PN533_ACR122_TX_FRAME_HEADER_LEN,
  520 + .tx_tail_len = PN533_ACR122_TX_FRAME_TAIL_LEN,
  521 +
  522 + .rx_is_frame_valid = pn533_acr122_is_rx_frame_valid,
  523 + .rx_header_len = PN533_ACR122_RX_FRAME_HEADER_LEN,
  524 + .rx_tail_len = PN533_ACR122_RX_FRAME_TAIL_LEN,
  525 + .rx_frame_size = pn533_acr122_rx_frame_size,
  526 +
  527 + .max_payload_len = PN533_ACR122_FRAME_MAX_PAYLOAD_LEN,
  528 + .get_cmd_code = pn533_acr122_get_cmd_code,
  529 +};
  530 +
397 531 /* The rule: value + checksum = 0 */
398 532 static inline u8 pn533_std_checksum(u8 value)
399 533 {
... ... @@ -2335,6 +2469,72 @@
2335 2469 return 0;
2336 2470 }
2337 2471  
  2472 +struct pn533_acr122_poweron_rdr_arg {
  2473 + int rc;
  2474 + struct completion done;
  2475 +};
  2476 +
  2477 +static void pn533_acr122_poweron_rdr_resp(struct urb *urb)
  2478 +{
  2479 + struct pn533_acr122_poweron_rdr_arg *arg = urb->context;
  2480 +
  2481 + nfc_dev_dbg(&urb->dev->dev, "%s", __func__);
  2482 +
  2483 + print_hex_dump(KERN_ERR, "ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1,
  2484 + urb->transfer_buffer, urb->transfer_buffer_length,
  2485 + false);
  2486 +
  2487 + arg->rc = urb->status;
  2488 + complete(&arg->done);
  2489 +}
  2490 +
  2491 +static int pn533_acr122_poweron_rdr(struct pn533 *dev)
  2492 +{
  2493 + /* Power on th reader (CCID cmd) */
  2494 + u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON,
  2495 + 0, 0, 0, 0, 0, 0, 3, 0, 0};
  2496 + u8 buf[255];
  2497 + int rc;
  2498 + void *cntx;
  2499 + struct pn533_acr122_poweron_rdr_arg arg;
  2500 +
  2501 + nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
  2502 +
  2503 + init_completion(&arg.done);
  2504 + cntx = dev->in_urb->context; /* backup context */
  2505 +
  2506 + dev->in_urb->transfer_buffer = buf;
  2507 + dev->in_urb->transfer_buffer_length = 255;
  2508 + dev->in_urb->complete = pn533_acr122_poweron_rdr_resp;
  2509 + dev->in_urb->context = &arg;
  2510 +
  2511 + dev->out_urb->transfer_buffer = cmd;
  2512 + dev->out_urb->transfer_buffer_length = sizeof(cmd);
  2513 +
  2514 + print_hex_dump(KERN_ERR, "ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1,
  2515 + cmd, sizeof(cmd), false);
  2516 +
  2517 + rc = usb_submit_urb(dev->out_urb, GFP_KERNEL);
  2518 + if (rc) {
  2519 + nfc_dev_err(&dev->interface->dev,
  2520 + "Reader power on cmd error %d", rc);
  2521 + return rc;
  2522 + }
  2523 +
  2524 + rc = usb_submit_urb(dev->in_urb, GFP_KERNEL);
  2525 + if (rc) {
  2526 + nfc_dev_err(&dev->interface->dev,
  2527 + "Can't submit for reader power on cmd response %d",
  2528 + rc);
  2529 + return rc;
  2530 + }
  2531 +
  2532 + wait_for_completion(&arg.done);
  2533 + dev->in_urb->context = cntx; /* restore context */
  2534 +
  2535 + return arg.rc;
  2536 +}
  2537 +
2338 2538 static struct nfc_ops pn533_nfc_ops = {
2339 2539 .dev_up = NULL,
2340 2540 .dev_down = NULL,
... ... @@ -2369,6 +2569,7 @@
2369 2569 break;
2370 2570  
2371 2571 case PN533_DEVICE_PASORI:
  2572 + case PN533_DEVICE_ACR122U:
2372 2573 max_retries.mx_rty_atr = 0x2;
2373 2574 max_retries.mx_rty_psl = 0x1;
2374 2575 max_retries.mx_rty_passive_act =
... ... @@ -2508,6 +2709,20 @@
2508 2709  
2509 2710 case PN533_DEVICE_PASORI:
2510 2711 protocols = PN533_NO_TYPE_B_PROTOCOLS;
  2712 + break;
  2713 +
  2714 + case PN533_DEVICE_ACR122U:
  2715 + protocols = PN533_NO_TYPE_B_PROTOCOLS;
  2716 + dev->ops = &pn533_acr122_frame_ops;
  2717 + dev->protocol_type = PN533_PROTO_REQ_RESP,
  2718 +
  2719 + rc = pn533_acr122_poweron_rdr(dev);
  2720 + if (rc < 0) {
  2721 + nfc_dev_err(&dev->interface->dev,
  2722 + "Couldn't poweron the reader (error %d)",
  2723 + rc);
  2724 + goto destroy_wq;
  2725 + }
2511 2726 break;
2512 2727  
2513 2728 default: