diff options
author | Christophe Ricard <christophe.ricard@gmail.com> | 2014-05-20 16:21:59 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2014-07-22 19:14:41 -0400 |
commit | 1892bf844ea0261736bd5e75546fc996e9daeedf (patch) | |
tree | d86f6354b212c50f75225b1bc8524ef70c243bda /drivers/nfc/st21nfca | |
parent | d57d74eb7626a2aeefad47a8d4246e9daf2199f5 (diff) |
NFC: st21nfca: Adding P2P support to st21nfca in Initiator & Target mode
Support for Initiator and Target mode with ISO18092 commands support:
- ATR_REQ/ATR_RES
- PSL_REQ/PSL_RES
- DEP_REQ/DEP_RES
Work based on net/nfc/digital_dep.c.
st21nfca is using:
- Gate reader F for P2P in initiator mode.
- Gate card F for P2P in target mode.
Felica tag and p2p are differentiated with NFCID2.
When starting with 01FE it is acting in p2p mode.
On complete_target_discovered on ST21NFCA_RF_READER_F_GATE
supported_protocols is set to NFC_PROTO_NFC_DEP_MASK
for P2P.
Tested against: Nexus S, Galaxy S2, Galaxy S3, Galaxy S3 Mini,
Nexus 4 & Nexus 5.
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc/st21nfca')
-rw-r--r-- | drivers/nfc/st21nfca/Makefile | 2 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca.c | 264 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca.h | 26 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca_dep.c | 661 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca_dep.h | 43 |
5 files changed, 993 insertions, 3 deletions
diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile index 038ed093a119..db7a38ae05f7 100644 --- a/drivers/nfc/st21nfca/Makefile +++ b/drivers/nfc/st21nfca/Makefile | |||
@@ -4,5 +4,5 @@ | |||
4 | 4 | ||
5 | st21nfca_i2c-objs = i2c.o | 5 | st21nfca_i2c-objs = i2c.o |
6 | 6 | ||
7 | obj-$(CONFIG_NFC_ST21NFCA) += st21nfca.o | 7 | obj-$(CONFIG_NFC_ST21NFCA) += st21nfca.o st21nfca_dep.o |
8 | obj-$(CONFIG_NFC_ST21NFCA_I2C) += st21nfca_i2c.o | 8 | obj-$(CONFIG_NFC_ST21NFCA_I2C) += st21nfca_i2c.o |
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index 7ff1dcdd16ba..a902b0551c86 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <net/nfc/llc.h> | 22 | #include <net/nfc/llc.h> |
23 | 23 | ||
24 | #include "st21nfca.h" | 24 | #include "st21nfca.h" |
25 | #include "st21nfca_dep.h" | ||
25 | 26 | ||
26 | #define DRIVER_DESC "HCI NFC driver for ST21NFCA" | 27 | #define DRIVER_DESC "HCI NFC driver for ST21NFCA" |
27 | 28 | ||
@@ -73,6 +74,7 @@ static struct nfc_hci_gate st21nfca_gates[] = { | |||
73 | {ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, | 74 | {ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, |
74 | {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, | 75 | {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, |
75 | {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, | 76 | {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, |
77 | {ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE}, | ||
76 | }; | 78 | }; |
77 | 79 | ||
78 | struct st21nfca_pipe_info { | 80 | struct st21nfca_pipe_info { |
@@ -300,6 +302,9 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, | |||
300 | u32 im_protocols, u32 tm_protocols) | 302 | u32 im_protocols, u32 tm_protocols) |
301 | { | 303 | { |
302 | int r; | 304 | int r; |
305 | u32 pol_req; | ||
306 | u8 param[19]; | ||
307 | struct sk_buff *datarate_skb; | ||
303 | 308 | ||
304 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", | 309 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", |
305 | __func__, im_protocols, tm_protocols); | 310 | __func__, im_protocols, tm_protocols); |
@@ -332,6 +337,31 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, | |||
332 | ST21NFCA_RF_READER_F_GATE); | 337 | ST21NFCA_RF_READER_F_GATE); |
333 | if (r < 0) | 338 | if (r < 0) |
334 | return r; | 339 | return r; |
340 | } else { | ||
341 | hdev->gb = nfc_get_local_general_bytes(hdev->ndev, | ||
342 | &hdev->gb_len); | ||
343 | |||
344 | if (hdev->gb == NULL || hdev->gb_len == 0) { | ||
345 | im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | ||
346 | tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | ||
347 | } | ||
348 | |||
349 | param[0] = ST21NFCA_RF_READER_F_DATARATE_106 | | ||
350 | ST21NFCA_RF_READER_F_DATARATE_212 | | ||
351 | ST21NFCA_RF_READER_F_DATARATE_424; | ||
352 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE, | ||
353 | ST21NFCA_RF_READER_F_DATARATE, | ||
354 | param, 1); | ||
355 | if (r < 0) | ||
356 | return r; | ||
357 | |||
358 | pol_req = | ||
359 | be32_to_cpu(ST21NFCA_RF_READER_F_POL_REQ_DEFAULT); | ||
360 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE, | ||
361 | ST21NFCA_RF_READER_F_POL_REQ, | ||
362 | (u8 *) &pol_req, 4); | ||
363 | if (r < 0) | ||
364 | return r; | ||
335 | } | 365 | } |
336 | 366 | ||
337 | if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) { | 367 | if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) { |
@@ -354,6 +384,95 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, | |||
354 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 384 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
355 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | 385 | NFC_HCI_EVT_END_OPERATION, NULL, 0); |
356 | } | 386 | } |
387 | |||
388 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
389 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
390 | ST21NFCA_RF_CARD_F_DATARATE, | ||
391 | &datarate_skb); | ||
392 | if (r < 0) | ||
393 | return r; | ||
394 | |||
395 | /* Configure the maximum supported datarate to 424Kbps */ | ||
396 | if (datarate_skb->len > 0 && | ||
397 | datarate_skb->data[0] != | ||
398 | ST21NFCA_RF_CARD_F_DATARATE_212_424) { | ||
399 | param[0] = ST21NFCA_RF_CARD_F_DATARATE_212_424; | ||
400 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
401 | ST21NFCA_RF_CARD_F_DATARATE, | ||
402 | param, 1); | ||
403 | if (r < 0) | ||
404 | return r; | ||
405 | } | ||
406 | |||
407 | /* | ||
408 | * Configure sens_res | ||
409 | * | ||
410 | * NFC Forum Digital Spec Table 7: | ||
411 | * NFCID1 size: triple (10 bytes) | ||
412 | */ | ||
413 | param[0] = 0x00; | ||
414 | param[1] = 0x08; | ||
415 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
416 | ST21NFCA_RF_CARD_F_SENS_RES, param, 2); | ||
417 | if (r < 0) | ||
418 | return r; | ||
419 | |||
420 | /* | ||
421 | * Configure sel_res | ||
422 | * | ||
423 | * NFC Forum Digistal Spec Table 17: | ||
424 | * b3 set to 0b (value b7-b6): | ||
425 | * - 10b: Configured for NFC-DEP Protocol | ||
426 | */ | ||
427 | param[0] = 0x40; | ||
428 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
429 | ST21NFCA_RF_CARD_F_SEL_RES, param, 1); | ||
430 | if (r < 0) | ||
431 | return r; | ||
432 | |||
433 | /* Configure NFCID1 Random uid */ | ||
434 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
435 | ST21NFCA_RF_CARD_F_NFCID1, NULL, 0); | ||
436 | if (r < 0) | ||
437 | return r; | ||
438 | |||
439 | /* Configure NFCID2_LIST */ | ||
440 | /* System Code */ | ||
441 | param[0] = 0x00; | ||
442 | param[1] = 0x00; | ||
443 | /* NFCID2 */ | ||
444 | param[2] = 0x01; | ||
445 | param[3] = 0xfe; | ||
446 | param[4] = 'S'; | ||
447 | param[5] = 'T'; | ||
448 | param[6] = 'M'; | ||
449 | param[7] = 'i'; | ||
450 | param[8] = 'c'; | ||
451 | param[9] = 'r'; | ||
452 | /* 8 byte Pad bytes used for polling respone frame */ | ||
453 | |||
454 | /* | ||
455 | * Configuration byte: | ||
456 | * - bit 0: define the default NFCID2 entry used when the | ||
457 | * system code is equal to 'FFFF' | ||
458 | * - bit 1: use a random value for lowest 6 bytes of | ||
459 | * NFCID2 value | ||
460 | * - bit 2: ignore polling request frame if request code | ||
461 | * is equal to '01' | ||
462 | * - Other bits are RFU | ||
463 | */ | ||
464 | param[18] = 0x01; | ||
465 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
466 | ST21NFCA_RF_CARD_F_NFCID2_LIST, param, | ||
467 | 19); | ||
468 | if (r < 0) | ||
469 | return r; | ||
470 | |||
471 | param[0] = 0x02; | ||
472 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
473 | ST21NFCA_RF_CARD_F_MODE, param, 1); | ||
474 | } | ||
475 | |||
357 | return r; | 476 | return r; |
358 | } | 477 | } |
359 | 478 | ||
@@ -458,6 +577,26 @@ exit: | |||
458 | return r; | 577 | return r; |
459 | } | 578 | } |
460 | 579 | ||
580 | static int st21nfca_hci_dep_link_up(struct nfc_hci_dev *hdev, | ||
581 | struct nfc_target *target, u8 comm_mode, | ||
582 | u8 *gb, size_t gb_len) | ||
583 | { | ||
584 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
585 | |||
586 | info->dep_info.idx = target->idx; | ||
587 | return st21nfca_im_send_atr_req(hdev, gb, gb_len); | ||
588 | } | ||
589 | |||
590 | static int st21nfca_hci_dep_link_down(struct nfc_hci_dev *hdev) | ||
591 | { | ||
592 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
593 | |||
594 | info->state = ST21NFCA_ST_READY; | ||
595 | |||
596 | return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, | ||
597 | ST21NFCA_DM_DISCONNECT, NULL, 0, NULL); | ||
598 | } | ||
599 | |||
461 | static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | 600 | static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, |
462 | struct nfc_target *target) | 601 | struct nfc_target *target) |
463 | { | 602 | { |
@@ -512,6 +651,69 @@ static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | |||
512 | return 0; | 651 | return 0; |
513 | } | 652 | } |
514 | 653 | ||
654 | static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev, | ||
655 | u8 gate, | ||
656 | struct nfc_target *target) | ||
657 | { | ||
658 | int r; | ||
659 | struct sk_buff *nfcid2_skb = NULL, *nfcid1_skb; | ||
660 | |||
661 | if (gate == ST21NFCA_RF_READER_F_GATE) { | ||
662 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE, | ||
663 | ST21NFCA_RF_READER_F_NFCID2, &nfcid2_skb); | ||
664 | if (r < 0) | ||
665 | goto exit; | ||
666 | |||
667 | if (nfcid2_skb->len > NFC_SENSF_RES_MAXSIZE) { | ||
668 | r = -EPROTO; | ||
669 | goto exit; | ||
670 | } | ||
671 | |||
672 | /* | ||
673 | * - After the recepton of polling response for type F frame | ||
674 | * at 212 or 424 Kbit/s, NFCID2 registry parameters will be | ||
675 | * updated. | ||
676 | * - After the reception of SEL_RES with NFCIP-1 compliant bit | ||
677 | * set for type A frame NFCID1 will be updated | ||
678 | */ | ||
679 | if (nfcid2_skb->len > 0) { | ||
680 | /* P2P in type F */ | ||
681 | memcpy(target->sensf_res, nfcid2_skb->data, | ||
682 | nfcid2_skb->len); | ||
683 | target->sensf_res_len = nfcid2_skb->len; | ||
684 | /* NFC Forum Digital Protocol Table 44 */ | ||
685 | if (target->sensf_res[0] == 0x01 && | ||
686 | target->sensf_res[1] == 0xfe) | ||
687 | target->supported_protocols = | ||
688 | NFC_PROTO_NFC_DEP_MASK; | ||
689 | else | ||
690 | target->supported_protocols = | ||
691 | NFC_PROTO_FELICA_MASK; | ||
692 | } else { | ||
693 | /* P2P in type A */ | ||
694 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE, | ||
695 | ST21NFCA_RF_READER_F_NFCID1, | ||
696 | &nfcid1_skb); | ||
697 | if (r < 0) | ||
698 | goto exit; | ||
699 | |||
700 | if (nfcid1_skb->len > NFC_NFCID1_MAXSIZE) { | ||
701 | r = -EPROTO; | ||
702 | goto exit; | ||
703 | } | ||
704 | memcpy(target->sensf_res, nfcid1_skb->data, | ||
705 | nfcid1_skb->len); | ||
706 | target->sensf_res_len = nfcid1_skb->len; | ||
707 | target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | ||
708 | } | ||
709 | target->hci_reader_gate = ST21NFCA_RF_READER_F_GATE; | ||
710 | } | ||
711 | r = 1; | ||
712 | exit: | ||
713 | kfree_skb(nfcid2_skb); | ||
714 | return r; | ||
715 | } | ||
716 | |||
515 | #define ST21NFCA_CB_TYPE_READER_ISO15693 1 | 717 | #define ST21NFCA_CB_TYPE_READER_ISO15693 1 |
516 | static void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb, | 718 | static void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb, |
517 | int err) | 719 | int err) |
@@ -548,6 +750,9 @@ static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev, | |||
548 | 750 | ||
549 | switch (target->hci_reader_gate) { | 751 | switch (target->hci_reader_gate) { |
550 | case ST21NFCA_RF_READER_F_GATE: | 752 | case ST21NFCA_RF_READER_F_GATE: |
753 | if (target->supported_protocols == NFC_PROTO_NFC_DEP_MASK) | ||
754 | return st21nfca_im_send_dep_req(hdev, skb); | ||
755 | |||
551 | *skb_push(skb, 1) = 0x1a; | 756 | *skb_push(skb, 1) = 0x1a; |
552 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | 757 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, |
553 | ST21NFCA_WR_XCHG_DATA, skb->data, | 758 | ST21NFCA_WR_XCHG_DATA, skb->data, |
@@ -576,6 +781,11 @@ static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev, | |||
576 | } | 781 | } |
577 | } | 782 | } |
578 | 783 | ||
784 | static int st21nfca_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) | ||
785 | { | ||
786 | return st21nfca_tm_send_dep_res(hdev, skb); | ||
787 | } | ||
788 | |||
579 | static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, | 789 | static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, |
580 | struct nfc_target *target) | 790 | struct nfc_target *target) |
581 | { | 791 | { |
@@ -601,6 +811,50 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, | |||
601 | } | 811 | } |
602 | } | 812 | } |
603 | 813 | ||
814 | /* | ||
815 | * Returns: | ||
816 | * <= 0: driver handled the event, skb consumed | ||
817 | * 1: driver does not handle the event, please do standard processing | ||
818 | */ | ||
819 | static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, | ||
820 | u8 event, struct sk_buff *skb) | ||
821 | { | ||
822 | int r; | ||
823 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
824 | |||
825 | pr_debug("hci event: %d\n", event); | ||
826 | |||
827 | switch (event) { | ||
828 | case ST21NFCA_EVT_CARD_ACTIVATED: | ||
829 | if (gate == ST21NFCA_RF_CARD_F_GATE) | ||
830 | info->dep_info.curr_nfc_dep_pni = 0; | ||
831 | break; | ||
832 | case ST21NFCA_EVT_CARD_DEACTIVATED: | ||
833 | break; | ||
834 | case ST21NFCA_EVT_FIELD_ON: | ||
835 | break; | ||
836 | case ST21NFCA_EVT_FIELD_OFF: | ||
837 | break; | ||
838 | case ST21NFCA_EVT_SEND_DATA: | ||
839 | if (gate == ST21NFCA_RF_CARD_F_GATE) { | ||
840 | r = st21nfca_tm_event_send_data(hdev, skb, gate); | ||
841 | if (r < 0) | ||
842 | goto exit; | ||
843 | return 0; | ||
844 | } else { | ||
845 | info->dep_info.curr_nfc_dep_pni = 0; | ||
846 | return 1; | ||
847 | } | ||
848 | break; | ||
849 | default: | ||
850 | return 1; | ||
851 | } | ||
852 | kfree_skb(skb); | ||
853 | return 0; | ||
854 | exit: | ||
855 | return r; | ||
856 | } | ||
857 | |||
604 | static struct nfc_hci_ops st21nfca_hci_ops = { | 858 | static struct nfc_hci_ops st21nfca_hci_ops = { |
605 | .open = st21nfca_hci_open, | 859 | .open = st21nfca_hci_open, |
606 | .close = st21nfca_hci_close, | 860 | .close = st21nfca_hci_close, |
@@ -609,9 +863,14 @@ static struct nfc_hci_ops st21nfca_hci_ops = { | |||
609 | .xmit = st21nfca_hci_xmit, | 863 | .xmit = st21nfca_hci_xmit, |
610 | .start_poll = st21nfca_hci_start_poll, | 864 | .start_poll = st21nfca_hci_start_poll, |
611 | .stop_poll = st21nfca_hci_stop_poll, | 865 | .stop_poll = st21nfca_hci_stop_poll, |
866 | .dep_link_up = st21nfca_hci_dep_link_up, | ||
867 | .dep_link_down = st21nfca_hci_dep_link_down, | ||
612 | .target_from_gate = st21nfca_hci_target_from_gate, | 868 | .target_from_gate = st21nfca_hci_target_from_gate, |
869 | .complete_target_discovered = st21nfca_hci_complete_target_discovered, | ||
613 | .im_transceive = st21nfca_hci_im_transceive, | 870 | .im_transceive = st21nfca_hci_im_transceive, |
871 | .tm_send = st21nfca_hci_tm_send, | ||
614 | .check_presence = st21nfca_hci_check_presence, | 872 | .check_presence = st21nfca_hci_check_presence, |
873 | .event_received = st21nfca_hci_event_received, | ||
615 | }; | 874 | }; |
616 | 875 | ||
617 | int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | 876 | int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, |
@@ -656,7 +915,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | |||
656 | NFC_PROTO_FELICA_MASK | | 915 | NFC_PROTO_FELICA_MASK | |
657 | NFC_PROTO_ISO14443_MASK | | 916 | NFC_PROTO_ISO14443_MASK | |
658 | NFC_PROTO_ISO14443_B_MASK | | 917 | NFC_PROTO_ISO14443_B_MASK | |
659 | NFC_PROTO_ISO15693_MASK; | 918 | NFC_PROTO_ISO15693_MASK | |
919 | NFC_PROTO_NFC_DEP_MASK; | ||
660 | 920 | ||
661 | set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); | 921 | set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); |
662 | 922 | ||
@@ -679,6 +939,7 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | |||
679 | goto err_regdev; | 939 | goto err_regdev; |
680 | 940 | ||
681 | *hdev = info->hdev; | 941 | *hdev = info->hdev; |
942 | st21nfca_dep_init(info->hdev); | ||
682 | 943 | ||
683 | return 0; | 944 | return 0; |
684 | 945 | ||
@@ -696,6 +957,7 @@ void st21nfca_hci_remove(struct nfc_hci_dev *hdev) | |||
696 | { | 957 | { |
697 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | 958 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
698 | 959 | ||
960 | st21nfca_dep_deinit(hdev); | ||
699 | nfc_hci_unregister_device(hdev); | 961 | nfc_hci_unregister_device(hdev); |
700 | nfc_hci_free_device(hdev); | 962 | nfc_hci_free_device(hdev); |
701 | kfree(info); | 963 | kfree(info); |
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h index 334cd90bcc8c..96fe5a62dc0d 100644 --- a/drivers/nfc/st21nfca/st21nfca.h +++ b/drivers/nfc/st21nfca/st21nfca.h | |||
@@ -19,6 +19,8 @@ | |||
19 | 19 | ||
20 | #include <net/nfc/hci.h> | 20 | #include <net/nfc/hci.h> |
21 | 21 | ||
22 | #include "st21nfca_dep.h" | ||
23 | |||
22 | #define HCI_MODE 0 | 24 | #define HCI_MODE 0 |
23 | 25 | ||
24 | /* framing in HCI mode */ | 26 | /* framing in HCI mode */ |
@@ -73,7 +75,8 @@ struct st21nfca_hci_info { | |||
73 | data_exchange_cb_t async_cb; | 75 | data_exchange_cb_t async_cb; |
74 | void *async_cb_context; | 76 | void *async_cb_context; |
75 | 77 | ||
76 | } __packed; | 78 | struct st21nfca_dep_info dep_info; |
79 | }; | ||
77 | 80 | ||
78 | /* Reader RF commands */ | 81 | /* Reader RF commands */ |
79 | #define ST21NFCA_WR_XCHG_DATA 0x10 | 82 | #define ST21NFCA_WR_XCHG_DATA 0x10 |
@@ -83,5 +86,26 @@ struct st21nfca_hci_info { | |||
83 | #define ST21NFCA_RF_READER_F_DATARATE_106 0x01 | 86 | #define ST21NFCA_RF_READER_F_DATARATE_106 0x01 |
84 | #define ST21NFCA_RF_READER_F_DATARATE_212 0x02 | 87 | #define ST21NFCA_RF_READER_F_DATARATE_212 0x02 |
85 | #define ST21NFCA_RF_READER_F_DATARATE_424 0x04 | 88 | #define ST21NFCA_RF_READER_F_DATARATE_424 0x04 |
89 | #define ST21NFCA_RF_READER_F_POL_REQ 0x02 | ||
90 | #define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT 0xffff0000 | ||
91 | #define ST21NFCA_RF_READER_F_NFCID2 0x03 | ||
92 | #define ST21NFCA_RF_READER_F_NFCID1 0x04 | ||
93 | #define ST21NFCA_RF_READER_F_SENS_RES 0x05 | ||
94 | |||
95 | #define ST21NFCA_RF_CARD_F_GATE 0x24 | ||
96 | #define ST21NFCA_RF_CARD_F_MODE 0x01 | ||
97 | #define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04 | ||
98 | #define ST21NFCA_RF_CARD_F_NFCID1 0x05 | ||
99 | #define ST21NFCA_RF_CARD_F_SENS_RES 0x06 | ||
100 | #define ST21NFCA_RF_CARD_F_SEL_RES 0x07 | ||
101 | #define ST21NFCA_RF_CARD_F_DATARATE 0x08 | ||
102 | #define ST21NFCA_RF_CARD_F_DATARATE_106 0x00 | ||
103 | #define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01 | ||
104 | |||
105 | #define ST21NFCA_EVT_SEND_DATA 0x10 | ||
106 | #define ST21NFCA_EVT_FIELD_ON 0x11 | ||
107 | #define ST21NFCA_EVT_CARD_DEACTIVATED 0x12 | ||
108 | #define ST21NFCA_EVT_CARD_ACTIVATED 0x13 | ||
109 | #define ST21NFCA_EVT_FIELD_OFF 0x14 | ||
86 | 110 | ||
87 | #endif /* __LOCAL_ST21NFCA_H_ */ | 111 | #endif /* __LOCAL_ST21NFCA_H_ */ |
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c new file mode 100644 index 000000000000..b2d9957b57f8 --- /dev/null +++ b/drivers/nfc/st21nfca/st21nfca_dep.c | |||
@@ -0,0 +1,661 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <net/nfc/hci.h> | ||
18 | |||
19 | #include "st21nfca.h" | ||
20 | #include "st21nfca_dep.h" | ||
21 | |||
22 | #define ST21NFCA_NFCIP1_INITIATOR 0x00 | ||
23 | #define ST21NFCA_NFCIP1_REQ 0xd4 | ||
24 | #define ST21NFCA_NFCIP1_RES 0xd5 | ||
25 | #define ST21NFCA_NFCIP1_ATR_REQ 0x00 | ||
26 | #define ST21NFCA_NFCIP1_ATR_RES 0x01 | ||
27 | #define ST21NFCA_NFCIP1_PSL_REQ 0x04 | ||
28 | #define ST21NFCA_NFCIP1_PSL_RES 0x05 | ||
29 | #define ST21NFCA_NFCIP1_DEP_REQ 0x06 | ||
30 | #define ST21NFCA_NFCIP1_DEP_RES 0x07 | ||
31 | |||
32 | #define ST21NFCA_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03) | ||
33 | #define ST21NFCA_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) | ||
34 | #define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ | ||
35 | ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT) | ||
36 | #define ST21NFCA_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04) | ||
37 | #define ST21NFCA_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08) | ||
38 | #define ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT 0x10 | ||
39 | |||
40 | #define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ | ||
41 | ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT) | ||
42 | |||
43 | #define ST21NFCA_NFC_DEP_PFB_I_PDU 0x00 | ||
44 | #define ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU 0x40 | ||
45 | #define ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU 0x80 | ||
46 | |||
47 | #define ST21NFCA_ATR_REQ_MIN_SIZE 17 | ||
48 | #define ST21NFCA_ATR_REQ_MAX_SIZE 65 | ||
49 | #define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30 | ||
50 | #define ST21NFCA_GB_BIT 0x02 | ||
51 | |||
52 | #define ST21NFCA_EVT_CARD_F_BITRATE 0x16 | ||
53 | #define ST21NFCA_EVT_READER_F_BITRATE 0x13 | ||
54 | #define ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38) | ||
55 | #define ST21NFCA_PSL_REQ_RECV_SPEED(brs) (brs & 0x07) | ||
56 | #define ST21NFCA_PP2LRI(pp) ((pp & 0x30) >> 4) | ||
57 | #define ST21NFCA_CARD_BITRATE_212 0x01 | ||
58 | #define ST21NFCA_CARD_BITRATE_424 0x02 | ||
59 | |||
60 | #define ST21NFCA_DEFAULT_TIMEOUT 0x0a | ||
61 | |||
62 | |||
63 | #define PROTOCOL_ERR(req) pr_err("%d: ST21NFCA Protocol error: %s\n", \ | ||
64 | __LINE__, req) | ||
65 | |||
66 | struct st21nfca_atr_req { | ||
67 | u8 length; | ||
68 | u8 cmd0; | ||
69 | u8 cmd1; | ||
70 | u8 nfcid3[NFC_NFCID3_MAXSIZE]; | ||
71 | u8 did; | ||
72 | u8 bsi; | ||
73 | u8 bri; | ||
74 | u8 ppi; | ||
75 | u8 gbi[0]; | ||
76 | } __packed; | ||
77 | |||
78 | struct st21nfca_atr_res { | ||
79 | u8 length; | ||
80 | u8 cmd0; | ||
81 | u8 cmd1; | ||
82 | u8 nfcid3[NFC_NFCID3_MAXSIZE]; | ||
83 | u8 did; | ||
84 | u8 bsi; | ||
85 | u8 bri; | ||
86 | u8 to; | ||
87 | u8 ppi; | ||
88 | u8 gbi[0]; | ||
89 | } __packed; | ||
90 | |||
91 | struct st21nfca_psl_req { | ||
92 | u8 length; | ||
93 | u8 cmd0; | ||
94 | u8 cmd1; | ||
95 | u8 did; | ||
96 | u8 brs; | ||
97 | u8 fsl; | ||
98 | } __packed; | ||
99 | |||
100 | struct st21nfca_psl_res { | ||
101 | u8 length; | ||
102 | u8 cmd0; | ||
103 | u8 cmd1; | ||
104 | u8 did; | ||
105 | } __packed; | ||
106 | |||
107 | struct st21nfca_dep_req_res { | ||
108 | u8 length; | ||
109 | u8 cmd0; | ||
110 | u8 cmd1; | ||
111 | u8 pfb; | ||
112 | u8 did; | ||
113 | u8 nad; | ||
114 | } __packed; | ||
115 | |||
116 | static void st21nfca_tx_work(struct work_struct *work) | ||
117 | { | ||
118 | struct st21nfca_hci_info *info = container_of(work, | ||
119 | struct st21nfca_hci_info, | ||
120 | dep_info.tx_work); | ||
121 | |||
122 | struct nfc_dev *dev; | ||
123 | struct sk_buff *skb; | ||
124 | if (info) { | ||
125 | dev = info->hdev->ndev; | ||
126 | skb = info->dep_info.tx_pending; | ||
127 | |||
128 | device_lock(&dev->dev); | ||
129 | |||
130 | nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE, | ||
131 | ST21NFCA_WR_XCHG_DATA, | ||
132 | skb->data, skb->len, | ||
133 | info->async_cb, info); | ||
134 | device_unlock(&dev->dev); | ||
135 | kfree_skb(skb); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static void st21nfca_im_send_pdu(struct st21nfca_hci_info *info, | ||
140 | struct sk_buff *skb) | ||
141 | { | ||
142 | info->dep_info.tx_pending = skb; | ||
143 | schedule_work(&info->dep_info.tx_work); | ||
144 | } | ||
145 | |||
146 | static int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev, | ||
147 | struct st21nfca_atr_req *atr_req) | ||
148 | { | ||
149 | struct st21nfca_atr_res *atr_res; | ||
150 | struct sk_buff *skb; | ||
151 | size_t gb_len; | ||
152 | int r; | ||
153 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
154 | |||
155 | gb_len = atr_req->length - sizeof(struct st21nfca_atr_req); | ||
156 | skb = alloc_skb(atr_req->length + 1, GFP_KERNEL); | ||
157 | if (!skb) | ||
158 | return -ENOMEM; | ||
159 | |||
160 | skb_put(skb, sizeof(struct st21nfca_atr_res)); | ||
161 | |||
162 | atr_res = (struct st21nfca_atr_res *)skb->data; | ||
163 | memset(atr_res, 0, sizeof(struct st21nfca_atr_res)); | ||
164 | |||
165 | atr_res->length = atr_req->length + 1; | ||
166 | atr_res->cmd0 = ST21NFCA_NFCIP1_RES; | ||
167 | atr_res->cmd1 = ST21NFCA_NFCIP1_ATR_RES; | ||
168 | |||
169 | memcpy(atr_res->nfcid3, atr_req->nfcid3, 6); | ||
170 | atr_res->bsi = 0x00; | ||
171 | atr_res->bri = 0x00; | ||
172 | atr_res->to = ST21NFCA_DEFAULT_TIMEOUT; | ||
173 | atr_res->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B; | ||
174 | |||
175 | if (gb_len) { | ||
176 | skb_put(skb, gb_len); | ||
177 | |||
178 | atr_res->ppi |= ST21NFCA_GB_BIT; | ||
179 | memcpy(atr_res->gbi, atr_req->gbi, gb_len); | ||
180 | r = nfc_set_remote_general_bytes(hdev->ndev, atr_res->gbi, | ||
181 | gb_len); | ||
182 | if (r < 0) | ||
183 | return r; | ||
184 | } | ||
185 | |||
186 | info->dep_info.curr_nfc_dep_pni = 0; | ||
187 | |||
188 | return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
189 | ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); | ||
190 | } | ||
191 | |||
192 | static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev, | ||
193 | struct sk_buff *skb) | ||
194 | { | ||
195 | struct st21nfca_atr_req *atr_req; | ||
196 | size_t gb_len; | ||
197 | int r; | ||
198 | |||
199 | skb_trim(skb, skb->len - 1); | ||
200 | if (IS_ERR(skb)) { | ||
201 | r = PTR_ERR(skb); | ||
202 | goto exit; | ||
203 | } | ||
204 | |||
205 | if (!skb->len) { | ||
206 | r = -EIO; | ||
207 | goto exit; | ||
208 | } | ||
209 | |||
210 | if (skb->len < ST21NFCA_ATR_REQ_MIN_SIZE) { | ||
211 | r = -EPROTO; | ||
212 | goto exit; | ||
213 | } | ||
214 | |||
215 | atr_req = (struct st21nfca_atr_req *)skb->data; | ||
216 | |||
217 | r = st21nfca_tm_send_atr_res(hdev, atr_req); | ||
218 | if (r) | ||
219 | goto exit; | ||
220 | |||
221 | gb_len = skb->len - sizeof(struct st21nfca_atr_req); | ||
222 | |||
223 | r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, | ||
224 | NFC_COMM_PASSIVE, atr_req->gbi, gb_len); | ||
225 | if (r) | ||
226 | goto exit; | ||
227 | |||
228 | r = 0; | ||
229 | |||
230 | exit: | ||
231 | return r; | ||
232 | } | ||
233 | |||
234 | static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev, | ||
235 | struct st21nfca_psl_req *psl_req) | ||
236 | { | ||
237 | struct st21nfca_psl_res *psl_res; | ||
238 | struct sk_buff *skb; | ||
239 | u8 bitrate[2] = {0, 0}; | ||
240 | |||
241 | int r; | ||
242 | |||
243 | skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL); | ||
244 | if (!skb) | ||
245 | return -ENOMEM; | ||
246 | skb_put(skb, sizeof(struct st21nfca_psl_res)); | ||
247 | |||
248 | psl_res = (struct st21nfca_psl_res *)skb->data; | ||
249 | |||
250 | psl_res->length = sizeof(struct st21nfca_psl_res); | ||
251 | psl_res->cmd0 = ST21NFCA_NFCIP1_RES; | ||
252 | psl_res->cmd1 = ST21NFCA_NFCIP1_PSL_RES; | ||
253 | psl_res->did = psl_req->did; | ||
254 | |||
255 | r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
256 | ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); | ||
257 | |||
258 | /* | ||
259 | * ST21NFCA only support P2P passive. | ||
260 | * PSL_REQ BRS value != 0 has only a meaning to | ||
261 | * change technology to type F. | ||
262 | * We change to BITRATE 424Kbits. | ||
263 | * In other case switch to BITRATE 106Kbits. | ||
264 | */ | ||
265 | if (ST21NFCA_PSL_REQ_SEND_SPEED(psl_req->brs) && | ||
266 | ST21NFCA_PSL_REQ_RECV_SPEED(psl_req->brs)) { | ||
267 | bitrate[0] = ST21NFCA_CARD_BITRATE_424; | ||
268 | bitrate[1] = ST21NFCA_CARD_BITRATE_424; | ||
269 | } | ||
270 | |||
271 | /* Send an event to change bitrate change event to card f */ | ||
272 | return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
273 | ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2); | ||
274 | } | ||
275 | |||
276 | static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev, | ||
277 | struct sk_buff *skb) | ||
278 | { | ||
279 | struct st21nfca_psl_req *psl_req; | ||
280 | int r; | ||
281 | |||
282 | skb_trim(skb, skb->len - 1); | ||
283 | if (IS_ERR(skb)) { | ||
284 | r = PTR_ERR(skb); | ||
285 | skb = NULL; | ||
286 | goto exit; | ||
287 | } | ||
288 | |||
289 | if (!skb->len) { | ||
290 | r = -EIO; | ||
291 | goto exit; | ||
292 | } | ||
293 | |||
294 | psl_req = (struct st21nfca_psl_req *)skb->data; | ||
295 | |||
296 | if (skb->len < sizeof(struct st21nfca_psl_req)) { | ||
297 | r = -EIO; | ||
298 | goto exit; | ||
299 | } | ||
300 | |||
301 | r = st21nfca_tm_send_psl_res(hdev, psl_req); | ||
302 | exit: | ||
303 | return r; | ||
304 | } | ||
305 | |||
306 | int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb) | ||
307 | { | ||
308 | int r; | ||
309 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
310 | |||
311 | *skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni; | ||
312 | *skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_RES; | ||
313 | *skb_push(skb, 1) = ST21NFCA_NFCIP1_RES; | ||
314 | *skb_push(skb, 1) = skb->len; | ||
315 | |||
316 | r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, | ||
317 | ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); | ||
318 | kfree_skb(skb); | ||
319 | |||
320 | return r; | ||
321 | } | ||
322 | EXPORT_SYMBOL(st21nfca_tm_send_dep_res); | ||
323 | |||
324 | static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev, | ||
325 | struct sk_buff *skb) | ||
326 | { | ||
327 | struct st21nfca_dep_req_res *dep_req; | ||
328 | u8 size; | ||
329 | int r; | ||
330 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
331 | |||
332 | skb_trim(skb, skb->len - 1); | ||
333 | if (IS_ERR(skb)) { | ||
334 | r = PTR_ERR(skb); | ||
335 | skb = NULL; | ||
336 | goto exit; | ||
337 | } | ||
338 | |||
339 | size = 4; | ||
340 | |||
341 | dep_req = (struct st21nfca_dep_req_res *)skb->data; | ||
342 | if (skb->len < size) { | ||
343 | r = -EIO; | ||
344 | goto exit; | ||
345 | } | ||
346 | |||
347 | if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_req->pfb)) | ||
348 | size++; | ||
349 | if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_req->pfb)) | ||
350 | size++; | ||
351 | |||
352 | if (skb->len < size) { | ||
353 | r = -EIO; | ||
354 | goto exit; | ||
355 | } | ||
356 | |||
357 | /* Receiving DEP_REQ - Decoding */ | ||
358 | switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_req->pfb)) { | ||
359 | case ST21NFCA_NFC_DEP_PFB_I_PDU: | ||
360 | info->dep_info.curr_nfc_dep_pni = | ||
361 | ST21NFCA_NFC_DEP_PFB_PNI(dep_req->pfb); | ||
362 | break; | ||
363 | case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU: | ||
364 | pr_err("Received a ACK/NACK PDU\n"); | ||
365 | break; | ||
366 | case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU: | ||
367 | pr_err("Received a SUPERVISOR PDU\n"); | ||
368 | break; | ||
369 | } | ||
370 | |||
371 | if (IS_ERR(skb)) { | ||
372 | r = PTR_ERR(skb); | ||
373 | skb = NULL; | ||
374 | goto exit; | ||
375 | } | ||
376 | |||
377 | skb_pull(skb, size); | ||
378 | |||
379 | return nfc_tm_data_received(hdev->ndev, skb); | ||
380 | exit: | ||
381 | return r; | ||
382 | } | ||
383 | |||
384 | int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb, | ||
385 | u8 gate) | ||
386 | { | ||
387 | u8 cmd0, cmd1; | ||
388 | int r; | ||
389 | |||
390 | cmd0 = skb->data[1]; | ||
391 | switch (cmd0) { | ||
392 | case ST21NFCA_NFCIP1_REQ: | ||
393 | cmd1 = skb->data[2]; | ||
394 | switch (cmd1) { | ||
395 | case ST21NFCA_NFCIP1_ATR_REQ: | ||
396 | r = st21nfca_tm_recv_atr_req(hdev, skb); | ||
397 | break; | ||
398 | case ST21NFCA_NFCIP1_PSL_REQ: | ||
399 | r = st21nfca_tm_recv_psl_req(hdev, skb); | ||
400 | break; | ||
401 | case ST21NFCA_NFCIP1_DEP_REQ: | ||
402 | r = st21nfca_tm_recv_dep_req(hdev, skb); | ||
403 | break; | ||
404 | default: | ||
405 | return 1; | ||
406 | } | ||
407 | default: | ||
408 | return 1; | ||
409 | } | ||
410 | return r; | ||
411 | } | ||
412 | EXPORT_SYMBOL(st21nfca_tm_event_send_data); | ||
413 | |||
414 | static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi, | ||
415 | u8 bri, u8 lri) | ||
416 | { | ||
417 | struct sk_buff *skb; | ||
418 | struct st21nfca_psl_req *psl_req; | ||
419 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
420 | |||
421 | skb = | ||
422 | alloc_skb(sizeof(struct st21nfca_psl_req) + 1, GFP_KERNEL); | ||
423 | if (!skb) | ||
424 | return; | ||
425 | skb_reserve(skb, 1); | ||
426 | |||
427 | skb_put(skb, sizeof(struct st21nfca_psl_req)); | ||
428 | psl_req = (struct st21nfca_psl_req *) skb->data; | ||
429 | |||
430 | psl_req->length = sizeof(struct st21nfca_psl_req); | ||
431 | psl_req->cmd0 = ST21NFCA_NFCIP1_REQ; | ||
432 | psl_req->cmd1 = ST21NFCA_NFCIP1_PSL_REQ; | ||
433 | psl_req->did = did; | ||
434 | psl_req->brs = (0x30 & bsi << 4) | (bri & 0x03); | ||
435 | psl_req->fsl = lri; | ||
436 | |||
437 | *skb_push(skb, 1) = info->dep_info.to | 0x10; | ||
438 | |||
439 | st21nfca_im_send_pdu(info, skb); | ||
440 | |||
441 | kfree_skb(skb); | ||
442 | } | ||
443 | |||
444 | #define ST21NFCA_CB_TYPE_READER_F 1 | ||
445 | static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb, | ||
446 | int err) | ||
447 | { | ||
448 | struct st21nfca_hci_info *info = context; | ||
449 | struct st21nfca_atr_res *atr_res; | ||
450 | int r; | ||
451 | |||
452 | if (err != 0) | ||
453 | return; | ||
454 | |||
455 | if (IS_ERR(skb)) | ||
456 | return; | ||
457 | |||
458 | switch (info->async_cb_type) { | ||
459 | case ST21NFCA_CB_TYPE_READER_F: | ||
460 | skb_trim(skb, skb->len - 1); | ||
461 | atr_res = (struct st21nfca_atr_res *)skb->data; | ||
462 | r = nfc_set_remote_general_bytes(info->hdev->ndev, | ||
463 | atr_res->gbi, | ||
464 | skb->len - sizeof(struct st21nfca_atr_res)); | ||
465 | if (r < 0) | ||
466 | return; | ||
467 | |||
468 | if (atr_res->to >= 0x0e) | ||
469 | info->dep_info.to = 0x0e; | ||
470 | else | ||
471 | info->dep_info.to = atr_res->to + 1; | ||
472 | |||
473 | info->dep_info.to |= 0x10; | ||
474 | |||
475 | r = nfc_dep_link_is_up(info->hdev->ndev, info->dep_info.idx, | ||
476 | NFC_COMM_PASSIVE, NFC_RF_INITIATOR); | ||
477 | if (r < 0) | ||
478 | return; | ||
479 | |||
480 | info->dep_info.curr_nfc_dep_pni = 0; | ||
481 | if (ST21NFCA_PP2LRI(atr_res->ppi) != info->dep_info.lri) | ||
482 | st21nfca_im_send_psl_req(info->hdev, atr_res->did, | ||
483 | atr_res->bsi, atr_res->bri, | ||
484 | ST21NFCA_PP2LRI(atr_res->ppi)); | ||
485 | break; | ||
486 | default: | ||
487 | if (err == 0) | ||
488 | kfree_skb(skb); | ||
489 | break; | ||
490 | } | ||
491 | } | ||
492 | |||
493 | int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len) | ||
494 | { | ||
495 | struct sk_buff *skb; | ||
496 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
497 | struct st21nfca_atr_req *atr_req; | ||
498 | struct nfc_target *target; | ||
499 | uint size; | ||
500 | |||
501 | info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT; | ||
502 | size = ST21NFCA_ATR_REQ_MIN_SIZE + gb_len; | ||
503 | if (size > ST21NFCA_ATR_REQ_MAX_SIZE) { | ||
504 | PROTOCOL_ERR("14.6.1.1"); | ||
505 | return -EINVAL; | ||
506 | } | ||
507 | |||
508 | skb = | ||
509 | alloc_skb(sizeof(struct st21nfca_atr_req) + gb_len + 1, GFP_KERNEL); | ||
510 | if (!skb) | ||
511 | return -ENOMEM; | ||
512 | |||
513 | skb_reserve(skb, 1); | ||
514 | |||
515 | skb_put(skb, sizeof(struct st21nfca_atr_req)); | ||
516 | |||
517 | atr_req = (struct st21nfca_atr_req *)skb->data; | ||
518 | memset(atr_req, 0, sizeof(struct st21nfca_atr_req)); | ||
519 | |||
520 | atr_req->cmd0 = ST21NFCA_NFCIP1_REQ; | ||
521 | atr_req->cmd1 = ST21NFCA_NFCIP1_ATR_REQ; | ||
522 | memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE); | ||
523 | target = hdev->ndev->targets; | ||
524 | |||
525 | if (target->sensf_res) | ||
526 | memcpy(atr_req->nfcid3, target->sensf_res, | ||
527 | target->sensf_res_len); | ||
528 | else | ||
529 | get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE); | ||
530 | |||
531 | atr_req->did = 0x0; | ||
532 | |||
533 | atr_req->bsi = 0x00; | ||
534 | atr_req->bri = 0x00; | ||
535 | atr_req->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B; | ||
536 | if (gb_len) { | ||
537 | atr_req->ppi |= ST21NFCA_GB_BIT; | ||
538 | memcpy(skb_put(skb, gb_len), gb, gb_len); | ||
539 | } | ||
540 | atr_req->length = sizeof(struct st21nfca_atr_req) + hdev->gb_len; | ||
541 | |||
542 | *skb_push(skb, 1) = info->dep_info.to | 0x10; /* timeout */ | ||
543 | |||
544 | info->async_cb_type = ST21NFCA_CB_TYPE_READER_F; | ||
545 | info->async_cb_context = info; | ||
546 | info->async_cb = st21nfca_im_recv_atr_res_cb; | ||
547 | info->dep_info.bri = atr_req->bri; | ||
548 | info->dep_info.bsi = atr_req->bsi; | ||
549 | info->dep_info.lri = ST21NFCA_PP2LRI(atr_req->ppi); | ||
550 | |||
551 | return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE, | ||
552 | ST21NFCA_WR_XCHG_DATA, skb->data, | ||
553 | skb->len, info->async_cb, info); | ||
554 | } | ||
555 | EXPORT_SYMBOL(st21nfca_im_send_atr_req); | ||
556 | |||
557 | static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb, | ||
558 | int err) | ||
559 | { | ||
560 | struct st21nfca_hci_info *info = context; | ||
561 | struct st21nfca_dep_req_res *dep_res; | ||
562 | |||
563 | int size; | ||
564 | |||
565 | if (err != 0) | ||
566 | return; | ||
567 | |||
568 | if (IS_ERR(skb)) | ||
569 | return; | ||
570 | |||
571 | switch (info->async_cb_type) { | ||
572 | case ST21NFCA_CB_TYPE_READER_F: | ||
573 | dep_res = (struct st21nfca_dep_req_res *)skb->data; | ||
574 | |||
575 | size = 3; | ||
576 | if (skb->len < size) | ||
577 | goto exit; | ||
578 | |||
579 | if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_res->pfb)) | ||
580 | size++; | ||
581 | if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_res->pfb)) | ||
582 | size++; | ||
583 | |||
584 | if (skb->len < size) | ||
585 | goto exit; | ||
586 | |||
587 | skb_trim(skb, skb->len - 1); | ||
588 | |||
589 | /* Receiving DEP_REQ - Decoding */ | ||
590 | switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) { | ||
591 | case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU: | ||
592 | pr_err("Received a ACK/NACK PDU\n"); | ||
593 | case ST21NFCA_NFC_DEP_PFB_I_PDU: | ||
594 | info->dep_info.curr_nfc_dep_pni = | ||
595 | ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1); | ||
596 | size++; | ||
597 | skb_pull(skb, size); | ||
598 | nfc_tm_data_received(info->hdev->ndev, skb); | ||
599 | break; | ||
600 | case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU: | ||
601 | pr_err("Received a SUPERVISOR PDU\n"); | ||
602 | skb_pull(skb, size); | ||
603 | *skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ; | ||
604 | *skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ; | ||
605 | *skb_push(skb, 1) = skb->len; | ||
606 | *skb_push(skb, 1) = info->dep_info.to | 0x10; | ||
607 | |||
608 | st21nfca_im_send_pdu(info, skb); | ||
609 | break; | ||
610 | } | ||
611 | |||
612 | return; | ||
613 | default: | ||
614 | break; | ||
615 | } | ||
616 | |||
617 | exit: | ||
618 | if (err == 0) | ||
619 | kfree_skb(skb); | ||
620 | } | ||
621 | |||
622 | int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb) | ||
623 | { | ||
624 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
625 | |||
626 | info->async_cb_type = ST21NFCA_CB_TYPE_READER_F; | ||
627 | info->async_cb_context = info; | ||
628 | info->async_cb = st21nfca_im_recv_dep_res_cb; | ||
629 | |||
630 | *skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni; | ||
631 | *skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ; | ||
632 | *skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ; | ||
633 | *skb_push(skb, 1) = skb->len; | ||
634 | |||
635 | *skb_push(skb, 1) = info->dep_info.to | 0x10; | ||
636 | |||
637 | return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE, | ||
638 | ST21NFCA_WR_XCHG_DATA, | ||
639 | skb->data, skb->len, | ||
640 | info->async_cb, info); | ||
641 | } | ||
642 | EXPORT_SYMBOL(st21nfca_im_send_dep_req); | ||
643 | |||
644 | void st21nfca_dep_init(struct nfc_hci_dev *hdev) | ||
645 | { | ||
646 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
647 | |||
648 | INIT_WORK(&info->dep_info.tx_work, st21nfca_tx_work); | ||
649 | info->dep_info.curr_nfc_dep_pni = 0; | ||
650 | info->dep_info.idx = 0; | ||
651 | info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT; | ||
652 | } | ||
653 | EXPORT_SYMBOL(st21nfca_dep_init); | ||
654 | |||
655 | void st21nfca_dep_deinit(struct nfc_hci_dev *hdev) | ||
656 | { | ||
657 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
658 | |||
659 | cancel_work_sync(&info->dep_info.tx_work); | ||
660 | } | ||
661 | EXPORT_SYMBOL(st21nfca_dep_deinit); | ||
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.h b/drivers/nfc/st21nfca/st21nfca_dep.h new file mode 100644 index 000000000000..ca213dee9c6e --- /dev/null +++ b/drivers/nfc/st21nfca/st21nfca_dep.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #ifndef __ST21NFCA_DEP_H | ||
18 | #define __ST21NFCA_DEP_H | ||
19 | |||
20 | #include <linux/skbuff.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | |||
23 | struct st21nfca_dep_info { | ||
24 | struct sk_buff *tx_pending; | ||
25 | struct work_struct tx_work; | ||
26 | u8 curr_nfc_dep_pni; | ||
27 | u32 idx; | ||
28 | u8 to; | ||
29 | u8 did; | ||
30 | u8 bsi; | ||
31 | u8 bri; | ||
32 | u8 lri; | ||
33 | } __packed; | ||
34 | |||
35 | int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb, | ||
36 | u8 gate); | ||
37 | int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb); | ||
38 | |||
39 | int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len); | ||
40 | int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb); | ||
41 | void st21nfca_dep_init(struct nfc_hci_dev *hdev); | ||
42 | void st21nfca_dep_deinit(struct nfc_hci_dev *hdev); | ||
43 | #endif /* __ST21NFCA_DEP_H */ | ||