diff options
author | Christophe Ricard <christophe.ricard@gmail.com> | 2014-05-13 16:03:42 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2014-05-19 18:48:28 -0400 |
commit | 7974728094d35f38775417a26d8f30ea3602496a (patch) | |
tree | 706107db0e911312647d4b153a8df265fc5a8b09 /drivers/nfc | |
parent | a779b8878c20a5cafff26d774eed4d36a903882a (diff) |
NFC: st21nfca: Add ISO15693 Reader/Writer support
Add support for ISO/IEC 15693 RF technology and Type 5 tags.
ISO15963 is using proprietary gate 12.
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index d9ee3d0c1a78..51e0f00b3a4f 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #define ST21NFCA_RF_READER_CMD_PRESENCE_CHECK 0x30 | 33 | #define ST21NFCA_RF_READER_CMD_PRESENCE_CHECK 0x30 |
34 | 34 | ||
35 | #define ST21NFCA_RF_READER_ISO15693_GATE 0x12 | 35 | #define ST21NFCA_RF_READER_ISO15693_GATE 0x12 |
36 | #define ST21NFCA_RF_READER_ISO15693_INVENTORY 0x01 | ||
36 | 37 | ||
37 | /* | 38 | /* |
38 | * Reader gate for communication with contact-less cards using Type A | 39 | * Reader gate for communication with contact-less cards using Type A |
@@ -70,6 +71,7 @@ static struct nfc_hci_gate st21nfca_gates[] = { | |||
70 | {ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE}, | 71 | {ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE}, |
71 | {ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, | 72 | {ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, |
72 | {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, | 73 | {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, |
74 | {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, | ||
73 | }; | 75 | }; |
74 | 76 | ||
75 | struct st21nfca_pipe_info { | 77 | struct st21nfca_pipe_info { |
@@ -421,6 +423,34 @@ exit: | |||
421 | return r; | 423 | return r; |
422 | } | 424 | } |
423 | 425 | ||
426 | static int st21nfca_get_iso15693_inventory(struct nfc_hci_dev *hdev, | ||
427 | struct nfc_target *target) | ||
428 | { | ||
429 | int r; | ||
430 | struct sk_buff *inventory_skb = NULL; | ||
431 | |||
432 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_ISO15693_GATE, | ||
433 | ST21NFCA_RF_READER_ISO15693_INVENTORY, | ||
434 | &inventory_skb); | ||
435 | if (r < 0) | ||
436 | goto exit; | ||
437 | |||
438 | skb_pull(inventory_skb, 2); | ||
439 | |||
440 | if (inventory_skb->len == 0 || | ||
441 | inventory_skb->len > NFC_ISO15693_UID_MAXSIZE) { | ||
442 | r = -EPROTO; | ||
443 | goto exit; | ||
444 | } | ||
445 | |||
446 | memcpy(target->iso15693_uid, inventory_skb->data, inventory_skb->len); | ||
447 | target->iso15693_dsfid = inventory_skb->data[1]; | ||
448 | target->is_iso15693 = 1; | ||
449 | exit: | ||
450 | kfree_skb(inventory_skb); | ||
451 | return r; | ||
452 | } | ||
453 | |||
424 | static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | 454 | static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, |
425 | struct nfc_target *target) | 455 | struct nfc_target *target) |
426 | { | 456 | { |
@@ -462,6 +492,12 @@ static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | |||
462 | } | 492 | } |
463 | 493 | ||
464 | break; | 494 | break; |
495 | case ST21NFCA_RF_READER_ISO15693_GATE: | ||
496 | target->supported_protocols = NFC_PROTO_ISO15693_MASK; | ||
497 | r = st21nfca_get_iso15693_inventory(hdev, target); | ||
498 | if (r < 0) | ||
499 | return r; | ||
500 | break; | ||
465 | default: | 501 | default: |
466 | return -EPROTO; | 502 | return -EPROTO; |
467 | } | 503 | } |
@@ -469,6 +505,25 @@ static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | |||
469 | return 0; | 505 | return 0; |
470 | } | 506 | } |
471 | 507 | ||
508 | #define ST21NFCA_CB_TYPE_READER_ISO15693 1 | ||
509 | static void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb, | ||
510 | int err) | ||
511 | { | ||
512 | struct st21nfca_hci_info *info = context; | ||
513 | |||
514 | switch (info->async_cb_type) { | ||
515 | case ST21NFCA_CB_TYPE_READER_ISO15693: | ||
516 | if (err == 0) | ||
517 | skb_trim(skb, skb->len - 1); | ||
518 | info->async_cb(info->async_cb_context, skb, err); | ||
519 | break; | ||
520 | default: | ||
521 | if (err == 0) | ||
522 | kfree_skb(skb); | ||
523 | break; | ||
524 | } | ||
525 | } | ||
526 | |||
472 | /* | 527 | /* |
473 | * Returns: | 528 | * Returns: |
474 | * <= 0: driver handled the data exchange | 529 | * <= 0: driver handled the data exchange |
@@ -479,6 +534,8 @@ static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev, | |||
479 | struct sk_buff *skb, | 534 | struct sk_buff *skb, |
480 | data_exchange_cb_t cb, void *cb_context) | 535 | data_exchange_cb_t cb, void *cb_context) |
481 | { | 536 | { |
537 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
538 | |||
482 | pr_info(DRIVER_DESC ": %s for gate=%d len=%d\n", __func__, | 539 | pr_info(DRIVER_DESC ": %s for gate=%d len=%d\n", __func__, |
483 | target->hci_reader_gate, skb->len); | 540 | target->hci_reader_gate, skb->len); |
484 | 541 | ||
@@ -494,6 +551,19 @@ static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev, | |||
494 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | 551 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, |
495 | ST21NFCA_WR_XCHG_DATA, skb->data, | 552 | ST21NFCA_WR_XCHG_DATA, skb->data, |
496 | skb->len, cb, cb_context); | 553 | skb->len, cb, cb_context); |
554 | case ST21NFCA_RF_READER_ISO15693_GATE: | ||
555 | info->async_cb_type = ST21NFCA_CB_TYPE_READER_ISO15693; | ||
556 | info->async_cb = cb; | ||
557 | info->async_cb_context = cb_context; | ||
558 | |||
559 | *skb_push(skb, 1) = 0x17; | ||
560 | |||
561 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | ||
562 | ST21NFCA_WR_XCHG_DATA, skb->data, | ||
563 | skb->len, | ||
564 | st21nfca_hci_data_exchange_cb, | ||
565 | info); | ||
566 | break; | ||
497 | default: | 567 | default: |
498 | return 1; | 568 | return 1; |
499 | } | 569 | } |
@@ -577,7 +647,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | |||
577 | NFC_PROTO_MIFARE_MASK | | 647 | NFC_PROTO_MIFARE_MASK | |
578 | NFC_PROTO_FELICA_MASK | | 648 | NFC_PROTO_FELICA_MASK | |
579 | NFC_PROTO_ISO14443_MASK | | 649 | NFC_PROTO_ISO14443_MASK | |
580 | NFC_PROTO_ISO14443_B_MASK; | 650 | NFC_PROTO_ISO14443_B_MASK | |
651 | NFC_PROTO_ISO15693_MASK; | ||
581 | 652 | ||
582 | set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); | 653 | set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); |
583 | 654 | ||