diff options
25 files changed, 2228 insertions, 29 deletions
diff --git a/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt new file mode 100644 index 000000000000..3b58ae480344 --- /dev/null +++ b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt | |||
@@ -0,0 +1,33 @@ | |||
1 | * STMicroelectronics SAS. ST21NFCB NFC Controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "st,st21nfcb_i2c". | ||
5 | - clock-frequency: I²C work frequency. | ||
6 | - reg: address on the bus | ||
7 | - interrupt-parent: phandle for the interrupt gpio controller | ||
8 | - interrupts: GPIO interrupt to which the chip is connected | ||
9 | - reset-gpios: Output GPIO pin used to reset the ST21NFCB | ||
10 | |||
11 | Optional SoC Specific Properties: | ||
12 | - pinctrl-names: Contains only one value - "default". | ||
13 | - pintctrl-0: Specifies the pin control groups used for this controller. | ||
14 | |||
15 | Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2): | ||
16 | |||
17 | &i2c2 { | ||
18 | |||
19 | status = "okay"; | ||
20 | |||
21 | st21nfcb: st21nfcb@8 { | ||
22 | |||
23 | compatible = "st,st21nfcb_i2c"; | ||
24 | |||
25 | reg = <0x08>; | ||
26 | clock-frequency = <400000>; | ||
27 | |||
28 | interrupt-parent = <&gpio5>; | ||
29 | interrupts = <2 IRQ_TYPE_LEVEL_LOW>; | ||
30 | |||
31 | reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; | ||
32 | }; | ||
33 | }; | ||
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 26c66a126551..7929fac13e1c 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig | |||
@@ -72,5 +72,5 @@ source "drivers/nfc/pn544/Kconfig" | |||
72 | source "drivers/nfc/microread/Kconfig" | 72 | source "drivers/nfc/microread/Kconfig" |
73 | source "drivers/nfc/nfcmrvl/Kconfig" | 73 | source "drivers/nfc/nfcmrvl/Kconfig" |
74 | source "drivers/nfc/st21nfca/Kconfig" | 74 | source "drivers/nfc/st21nfca/Kconfig" |
75 | 75 | source "drivers/nfc/st21nfcb/Kconfig" | |
76 | endmenu | 76 | endmenu |
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index 23225b0287fd..6b23a2c6e34a 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_NFC_SIM) += nfcsim.o | |||
11 | obj-$(CONFIG_NFC_PORT100) += port100.o | 11 | obj-$(CONFIG_NFC_PORT100) += port100.o |
12 | obj-$(CONFIG_NFC_MRVL) += nfcmrvl/ | 12 | obj-$(CONFIG_NFC_MRVL) += nfcmrvl/ |
13 | obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o | 13 | obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o |
14 | obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/ | 14 | obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/ |
15 | obj-$(CONFIG_NFC_ST21NFCB) += st21nfcb/ | ||
15 | 16 | ||
16 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG | 17 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG |
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/i2c.c b/drivers/nfc/st21nfca/i2c.c index 3f954ed86d98..ff31939978ae 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c | |||
@@ -93,7 +93,7 @@ struct st21nfca_i2c_phy { | |||
93 | int hard_fault; | 93 | int hard_fault; |
94 | struct mutex phy_lock; | 94 | struct mutex phy_lock; |
95 | }; | 95 | }; |
96 | static u8 len_seq[] = { 13, 24, 15, 29 }; | 96 | static u8 len_seq[] = { 16, 24, 12, 29 }; |
97 | static u16 wait_tab[] = { 2, 3, 5, 15, 20, 40}; | 97 | static u16 wait_tab[] = { 2, 3, 5, 15, 20, 40}; |
98 | 98 | ||
99 | #define I2C_DUMP_SKB(info, skb) \ | 99 | #define I2C_DUMP_SKB(info, skb) \ |
@@ -397,12 +397,11 @@ static int st21nfca_hci_i2c_read(struct st21nfca_i2c_phy *phy, | |||
397 | * The first read sequence does not start with SOF. | 397 | * The first read sequence does not start with SOF. |
398 | * Data is corrupeted so we drop it. | 398 | * Data is corrupeted so we drop it. |
399 | */ | 399 | */ |
400 | if (!phy->current_read_len && buf[0] != ST21NFCA_SOF_EOF) { | 400 | if (!phy->current_read_len && !IS_START_OF_FRAME(buf)) { |
401 | skb_trim(skb, 0); | 401 | skb_trim(skb, 0); |
402 | phy->current_read_len = 0; | 402 | phy->current_read_len = 0; |
403 | return -EIO; | 403 | return -EIO; |
404 | } else if (phy->current_read_len && | 404 | } else if (phy->current_read_len && IS_START_OF_FRAME(buf)) { |
405 | IS_START_OF_FRAME(buf)) { | ||
406 | /* | 405 | /* |
407 | * Previous frame transmission was interrupted and | 406 | * Previous frame transmission was interrupted and |
408 | * the frame got repeated. | 407 | * the frame got repeated. |
@@ -487,6 +486,8 @@ static irqreturn_t st21nfca_hci_irq_thread_fn(int irq, void *phy_id) | |||
487 | */ | 486 | */ |
488 | nfc_hci_recv_frame(phy->hdev, phy->pending_skb); | 487 | nfc_hci_recv_frame(phy->hdev, phy->pending_skb); |
489 | phy->crc_trials = 0; | 488 | phy->crc_trials = 0; |
489 | } else { | ||
490 | kfree_skb(phy->pending_skb); | ||
490 | } | 491 | } |
491 | 492 | ||
492 | phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL); | 493 | phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL); |
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index 51e0f00b3a4f..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 | ||
@@ -53,6 +54,7 @@ | |||
53 | #define ST21NFCA_DM_PIPE_CREATED 0x02 | 54 | #define ST21NFCA_DM_PIPE_CREATED 0x02 |
54 | #define ST21NFCA_DM_PIPE_OPEN 0x04 | 55 | #define ST21NFCA_DM_PIPE_OPEN 0x04 |
55 | #define ST21NFCA_DM_RF_ACTIVE 0x80 | 56 | #define ST21NFCA_DM_RF_ACTIVE 0x80 |
57 | #define ST21NFCA_DM_DISCONNECT 0x30 | ||
56 | 58 | ||
57 | #define ST21NFCA_DM_IS_PIPE_OPEN(p) \ | 59 | #define ST21NFCA_DM_IS_PIPE_OPEN(p) \ |
58 | ((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN)) | 60 | ((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN)) |
@@ -72,6 +74,7 @@ static struct nfc_hci_gate st21nfca_gates[] = { | |||
72 | {ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, | 74 | {ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, |
73 | {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, | 75 | {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, |
74 | {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}, | ||
75 | }; | 78 | }; |
76 | 79 | ||
77 | struct st21nfca_pipe_info { | 80 | struct st21nfca_pipe_info { |
@@ -299,6 +302,9 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, | |||
299 | u32 im_protocols, u32 tm_protocols) | 302 | u32 im_protocols, u32 tm_protocols) |
300 | { | 303 | { |
301 | int r; | 304 | int r; |
305 | u32 pol_req; | ||
306 | u8 param[19]; | ||
307 | struct sk_buff *datarate_skb; | ||
302 | 308 | ||
303 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", | 309 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", |
304 | __func__, im_protocols, tm_protocols); | 310 | __func__, im_protocols, tm_protocols); |
@@ -331,6 +337,31 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, | |||
331 | ST21NFCA_RF_READER_F_GATE); | 337 | ST21NFCA_RF_READER_F_GATE); |
332 | if (r < 0) | 338 | if (r < 0) |
333 | 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; | ||
334 | } | 365 | } |
335 | 366 | ||
336 | if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) { | 367 | if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) { |
@@ -353,9 +384,104 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, | |||
353 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 384 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
354 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | 385 | NFC_HCI_EVT_END_OPERATION, NULL, 0); |
355 | } | 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 | |||
356 | return r; | 476 | return r; |
357 | } | 477 | } |
358 | 478 | ||
479 | static void st21nfca_hci_stop_poll(struct nfc_hci_dev *hdev) | ||
480 | { | ||
481 | nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, | ||
482 | ST21NFCA_DM_DISCONNECT, NULL, 0, NULL); | ||
483 | } | ||
484 | |||
359 | static int st21nfca_get_iso14443_3_atqa(struct nfc_hci_dev *hdev, u16 *atqa) | 485 | static int st21nfca_get_iso14443_3_atqa(struct nfc_hci_dev *hdev, u16 *atqa) |
360 | { | 486 | { |
361 | int r; | 487 | int r; |
@@ -451,6 +577,26 @@ exit: | |||
451 | return r; | 577 | return r; |
452 | } | 578 | } |
453 | 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 | |||
454 | 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, |
455 | struct nfc_target *target) | 601 | struct nfc_target *target) |
456 | { | 602 | { |
@@ -505,6 +651,69 @@ static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | |||
505 | return 0; | 651 | return 0; |
506 | } | 652 | } |
507 | 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 | |||
508 | #define ST21NFCA_CB_TYPE_READER_ISO15693 1 | 717 | #define ST21NFCA_CB_TYPE_READER_ISO15693 1 |
509 | 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, |
510 | int err) | 719 | int err) |
@@ -541,6 +750,9 @@ static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev, | |||
541 | 750 | ||
542 | switch (target->hci_reader_gate) { | 751 | switch (target->hci_reader_gate) { |
543 | 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 | |||
544 | *skb_push(skb, 1) = 0x1a; | 756 | *skb_push(skb, 1) = 0x1a; |
545 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | 757 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, |
546 | ST21NFCA_WR_XCHG_DATA, skb->data, | 758 | ST21NFCA_WR_XCHG_DATA, skb->data, |
@@ -569,6 +781,11 @@ static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev, | |||
569 | } | 781 | } |
570 | } | 782 | } |
571 | 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 | |||
572 | static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, | 789 | static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, |
573 | struct nfc_target *target) | 790 | struct nfc_target *target) |
574 | { | 791 | { |
@@ -594,6 +811,50 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, | |||
594 | } | 811 | } |
595 | } | 812 | } |
596 | 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 | |||
597 | static struct nfc_hci_ops st21nfca_hci_ops = { | 858 | static struct nfc_hci_ops st21nfca_hci_ops = { |
598 | .open = st21nfca_hci_open, | 859 | .open = st21nfca_hci_open, |
599 | .close = st21nfca_hci_close, | 860 | .close = st21nfca_hci_close, |
@@ -601,9 +862,15 @@ static struct nfc_hci_ops st21nfca_hci_ops = { | |||
601 | .hci_ready = st21nfca_hci_ready, | 862 | .hci_ready = st21nfca_hci_ready, |
602 | .xmit = st21nfca_hci_xmit, | 863 | .xmit = st21nfca_hci_xmit, |
603 | .start_poll = st21nfca_hci_start_poll, | 864 | .start_poll = st21nfca_hci_start_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, | ||
604 | .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, | ||
605 | .im_transceive = st21nfca_hci_im_transceive, | 870 | .im_transceive = st21nfca_hci_im_transceive, |
871 | .tm_send = st21nfca_hci_tm_send, | ||
606 | .check_presence = st21nfca_hci_check_presence, | 872 | .check_presence = st21nfca_hci_check_presence, |
873 | .event_received = st21nfca_hci_event_received, | ||
607 | }; | 874 | }; |
608 | 875 | ||
609 | 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, |
@@ -648,7 +915,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | |||
648 | NFC_PROTO_FELICA_MASK | | 915 | NFC_PROTO_FELICA_MASK | |
649 | NFC_PROTO_ISO14443_MASK | | 916 | NFC_PROTO_ISO14443_MASK | |
650 | NFC_PROTO_ISO14443_B_MASK | | 917 | NFC_PROTO_ISO14443_B_MASK | |
651 | NFC_PROTO_ISO15693_MASK; | 918 | NFC_PROTO_ISO15693_MASK | |
919 | NFC_PROTO_NFC_DEP_MASK; | ||
652 | 920 | ||
653 | set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); | 921 | set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); |
654 | 922 | ||
@@ -671,6 +939,7 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | |||
671 | goto err_regdev; | 939 | goto err_regdev; |
672 | 940 | ||
673 | *hdev = info->hdev; | 941 | *hdev = info->hdev; |
942 | st21nfca_dep_init(info->hdev); | ||
674 | 943 | ||
675 | return 0; | 944 | return 0; |
676 | 945 | ||
@@ -688,6 +957,7 @@ void st21nfca_hci_remove(struct nfc_hci_dev *hdev) | |||
688 | { | 957 | { |
689 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | 958 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
690 | 959 | ||
960 | st21nfca_dep_deinit(hdev); | ||
691 | nfc_hci_unregister_device(hdev); | 961 | nfc_hci_unregister_device(hdev); |
692 | nfc_hci_free_device(hdev); | 962 | nfc_hci_free_device(hdev); |
693 | 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 */ | ||
diff --git a/drivers/nfc/st21nfcb/Kconfig b/drivers/nfc/st21nfcb/Kconfig new file mode 100644 index 000000000000..e0322dd03a70 --- /dev/null +++ b/drivers/nfc/st21nfcb/Kconfig | |||
@@ -0,0 +1,22 @@ | |||
1 | config NFC_ST21NFCB | ||
2 | tristate "STMicroelectronics ST21NFCB NFC driver" | ||
3 | depends on NFC_NCI | ||
4 | default n | ||
5 | ---help--- | ||
6 | STMicroelectronics ST21NFCB core driver. It implements the chipset | ||
7 | NCI logic and hooks into the NFC kernel APIs. Physical layers will | ||
8 | register against it. | ||
9 | |||
10 | To compile this driver as a module, choose m here. The module will | ||
11 | be called st21nfcb. | ||
12 | Say N if unsure. | ||
13 | |||
14 | config NFC_ST21NFCB_I2C | ||
15 | tristate "NFC ST21NFCB i2c support" | ||
16 | depends on NFC_ST21NFCB && I2C | ||
17 | ---help--- | ||
18 | This module adds support for the STMicroelectronics st21nfcb i2c interface. | ||
19 | Select this if your platform is using the i2c bus. | ||
20 | |||
21 | If you choose to build a module, it'll be called st21nfcb_i2c. | ||
22 | Say N if unsure. | ||
diff --git a/drivers/nfc/st21nfcb/Makefile b/drivers/nfc/st21nfcb/Makefile new file mode 100644 index 000000000000..13d9f03b2fea --- /dev/null +++ b/drivers/nfc/st21nfcb/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for ST21NFCB NCI based NFC driver | ||
3 | # | ||
4 | |||
5 | st21nfcb_i2c-objs = i2c.o | ||
6 | |||
7 | obj-$(CONFIG_NFC_ST21NFCB) += st21nfcb.o ndlc.o | ||
8 | obj-$(CONFIG_NFC_ST21NFCB_I2C) += st21nfcb_i2c.o | ||
diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c new file mode 100644 index 000000000000..8af880ead5db --- /dev/null +++ b/drivers/nfc/st21nfcb/i2c.c | |||
@@ -0,0 +1,462 @@ | |||
1 | /* | ||
2 | * I2C Link Layer for ST21NFCB NCI based Driver | ||
3 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
19 | |||
20 | #include <linux/crc-ccitt.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/of_irq.h> | ||
25 | #include <linux/of_gpio.h> | ||
26 | #include <linux/miscdevice.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/nfc.h> | ||
30 | #include <linux/firmware.h> | ||
31 | #include <linux/unaligned/access_ok.h> | ||
32 | #include <linux/platform_data/st21nfcb.h> | ||
33 | |||
34 | #include <net/nfc/nci.h> | ||
35 | #include <net/nfc/llc.h> | ||
36 | #include <net/nfc/nfc.h> | ||
37 | |||
38 | #include "ndlc.h" | ||
39 | |||
40 | #define DRIVER_DESC "NCI NFC driver for ST21NFCB" | ||
41 | |||
42 | /* ndlc header */ | ||
43 | #define ST21NFCB_FRAME_HEADROOM 1 | ||
44 | #define ST21NFCB_FRAME_TAILROOM 0 | ||
45 | |||
46 | #define ST21NFCB_NCI_I2C_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */ | ||
47 | #define ST21NFCB_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */ | ||
48 | |||
49 | #define ST21NFCB_NCI_I2C_DRIVER_NAME "st21nfcb_nci_i2c" | ||
50 | |||
51 | static struct i2c_device_id st21nfcb_nci_i2c_id_table[] = { | ||
52 | {ST21NFCB_NCI_DRIVER_NAME, 0}, | ||
53 | {} | ||
54 | }; | ||
55 | MODULE_DEVICE_TABLE(i2c, st21nfcb_nci_i2c_id_table); | ||
56 | |||
57 | struct st21nfcb_i2c_phy { | ||
58 | struct i2c_client *i2c_dev; | ||
59 | struct llt_ndlc *ndlc; | ||
60 | |||
61 | unsigned int gpio_irq; | ||
62 | unsigned int gpio_reset; | ||
63 | unsigned int irq_polarity; | ||
64 | |||
65 | int powered; | ||
66 | |||
67 | /* | ||
68 | * < 0 if hardware error occured (e.g. i2c err) | ||
69 | * and prevents normal operation. | ||
70 | */ | ||
71 | int hard_fault; | ||
72 | }; | ||
73 | |||
74 | #define I2C_DUMP_SKB(info, skb) \ | ||
75 | do { \ | ||
76 | pr_debug("%s:\n", info); \ | ||
77 | print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \ | ||
78 | 16, 1, (skb)->data, (skb)->len, 0); \ | ||
79 | } while (0) | ||
80 | |||
81 | static int st21nfcb_nci_i2c_enable(void *phy_id) | ||
82 | { | ||
83 | struct st21nfcb_i2c_phy *phy = phy_id; | ||
84 | |||
85 | gpio_set_value(phy->gpio_reset, 0); | ||
86 | usleep_range(10000, 15000); | ||
87 | gpio_set_value(phy->gpio_reset, 1); | ||
88 | phy->powered = 1; | ||
89 | usleep_range(80000, 85000); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static void st21nfcb_nci_i2c_disable(void *phy_id) | ||
95 | { | ||
96 | struct st21nfcb_i2c_phy *phy = phy_id; | ||
97 | |||
98 | pr_info("\n"); | ||
99 | |||
100 | phy->powered = 0; | ||
101 | /* reset chip in order to flush clf */ | ||
102 | gpio_set_value(phy->gpio_reset, 0); | ||
103 | usleep_range(10000, 15000); | ||
104 | gpio_set_value(phy->gpio_reset, 1); | ||
105 | } | ||
106 | |||
107 | static void st21nfcb_nci_remove_header(struct sk_buff *skb) | ||
108 | { | ||
109 | skb_pull(skb, ST21NFCB_FRAME_HEADROOM); | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Writing a frame must not return the number of written bytes. | ||
114 | * It must return either zero for success, or <0 for error. | ||
115 | * In addition, it must not alter the skb | ||
116 | */ | ||
117 | static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb) | ||
118 | { | ||
119 | int r = -1; | ||
120 | struct st21nfcb_i2c_phy *phy = phy_id; | ||
121 | struct i2c_client *client = phy->i2c_dev; | ||
122 | |||
123 | I2C_DUMP_SKB("st21nfcb_nci_i2c_write", skb); | ||
124 | |||
125 | if (phy->hard_fault != 0) | ||
126 | return phy->hard_fault; | ||
127 | |||
128 | r = i2c_master_send(client, skb->data, skb->len); | ||
129 | if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | ||
130 | usleep_range(1000, 4000); | ||
131 | r = i2c_master_send(client, skb->data, skb->len); | ||
132 | } | ||
133 | |||
134 | if (r >= 0) { | ||
135 | if (r != skb->len) | ||
136 | r = -EREMOTEIO; | ||
137 | else | ||
138 | r = 0; | ||
139 | } | ||
140 | |||
141 | st21nfcb_nci_remove_header(skb); | ||
142 | |||
143 | return r; | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * Reads an ndlc frame and returns it in a newly allocated sk_buff. | ||
148 | * returns: | ||
149 | * frame size : if received frame is complete (find ST21NFCB_SOF_EOF at | ||
150 | * end of read) | ||
151 | * -EAGAIN : if received frame is incomplete (not find ST21NFCB_SOF_EOF | ||
152 | * at end of read) | ||
153 | * -EREMOTEIO : i2c read error (fatal) | ||
154 | * -EBADMSG : frame was incorrect and discarded | ||
155 | * (value returned from st21nfcb_nci_i2c_repack) | ||
156 | * -EIO : if no ST21NFCB_SOF_EOF is found after reaching | ||
157 | * the read length end sequence | ||
158 | */ | ||
159 | static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy, | ||
160 | struct sk_buff **skb) | ||
161 | { | ||
162 | int r; | ||
163 | u8 len; | ||
164 | u8 buf[ST21NFCB_NCI_I2C_MAX_SIZE]; | ||
165 | struct i2c_client *client = phy->i2c_dev; | ||
166 | |||
167 | r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE); | ||
168 | if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | ||
169 | usleep_range(1000, 4000); | ||
170 | r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE); | ||
171 | } else if (r != ST21NFCB_NCI_I2C_MIN_SIZE) { | ||
172 | nfc_err(&client->dev, "cannot read ndlc & nci header\n"); | ||
173 | return -EREMOTEIO; | ||
174 | } | ||
175 | |||
176 | len = be16_to_cpu(*(__be16 *) (buf + 2)); | ||
177 | if (len > ST21NFCB_NCI_I2C_MAX_SIZE) { | ||
178 | nfc_err(&client->dev, "invalid frame len\n"); | ||
179 | return -EBADMSG; | ||
180 | } | ||
181 | |||
182 | *skb = alloc_skb(ST21NFCB_NCI_I2C_MIN_SIZE + len, GFP_KERNEL); | ||
183 | if (*skb == NULL) | ||
184 | return -ENOMEM; | ||
185 | |||
186 | skb_reserve(*skb, ST21NFCB_NCI_I2C_MIN_SIZE); | ||
187 | skb_put(*skb, ST21NFCB_NCI_I2C_MIN_SIZE); | ||
188 | memcpy((*skb)->data, buf, ST21NFCB_NCI_I2C_MIN_SIZE); | ||
189 | |||
190 | if (!len) | ||
191 | return 0; | ||
192 | |||
193 | r = i2c_master_recv(client, buf, len); | ||
194 | if (r != len) { | ||
195 | kfree_skb(*skb); | ||
196 | return -EREMOTEIO; | ||
197 | } | ||
198 | |||
199 | skb_put(*skb, len); | ||
200 | memcpy((*skb)->data + ST21NFCB_NCI_I2C_MIN_SIZE, buf, len); | ||
201 | |||
202 | I2C_DUMP_SKB("i2c frame read", *skb); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Reads an ndlc frame from the chip. | ||
209 | * | ||
210 | * On ST21NFCB, IRQ goes in idle state when read starts. | ||
211 | */ | ||
212 | static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id) | ||
213 | { | ||
214 | struct st21nfcb_i2c_phy *phy = phy_id; | ||
215 | struct i2c_client *client; | ||
216 | struct sk_buff *skb = NULL; | ||
217 | int r; | ||
218 | |||
219 | if (!phy || irq != phy->i2c_dev->irq) { | ||
220 | WARN_ON_ONCE(1); | ||
221 | return IRQ_NONE; | ||
222 | } | ||
223 | |||
224 | client = phy->i2c_dev; | ||
225 | dev_dbg(&client->dev, "IRQ\n"); | ||
226 | |||
227 | if (phy->hard_fault) | ||
228 | return IRQ_HANDLED; | ||
229 | |||
230 | if (!phy->powered) { | ||
231 | st21nfcb_nci_i2c_disable(phy); | ||
232 | return IRQ_HANDLED; | ||
233 | } | ||
234 | |||
235 | r = st21nfcb_nci_i2c_read(phy, &skb); | ||
236 | if (r == -EREMOTEIO) { | ||
237 | phy->hard_fault = r; | ||
238 | ndlc_recv(phy->ndlc, NULL); | ||
239 | return IRQ_HANDLED; | ||
240 | } else if (r == -ENOMEM || r == -EBADMSG) { | ||
241 | return IRQ_HANDLED; | ||
242 | } | ||
243 | |||
244 | ndlc_recv(phy->ndlc, skb); | ||
245 | |||
246 | return IRQ_HANDLED; | ||
247 | } | ||
248 | |||
249 | static struct nfc_phy_ops i2c_phy_ops = { | ||
250 | .write = st21nfcb_nci_i2c_write, | ||
251 | .enable = st21nfcb_nci_i2c_enable, | ||
252 | .disable = st21nfcb_nci_i2c_disable, | ||
253 | }; | ||
254 | |||
255 | #ifdef CONFIG_OF | ||
256 | static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client) | ||
257 | { | ||
258 | struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client); | ||
259 | struct device_node *pp; | ||
260 | int gpio; | ||
261 | int r; | ||
262 | |||
263 | pp = client->dev.of_node; | ||
264 | if (!pp) | ||
265 | return -ENODEV; | ||
266 | |||
267 | /* Get GPIO from device tree */ | ||
268 | gpio = of_get_named_gpio(pp, "reset-gpios", 0); | ||
269 | if (gpio < 0) { | ||
270 | nfc_err(&client->dev, | ||
271 | "Failed to retrieve reset-gpios from device tree\n"); | ||
272 | return gpio; | ||
273 | } | ||
274 | |||
275 | /* GPIO request and configuration */ | ||
276 | r = devm_gpio_request(&client->dev, gpio, "clf_reset"); | ||
277 | if (r) { | ||
278 | nfc_err(&client->dev, "Failed to request reset pin\n"); | ||
279 | return -ENODEV; | ||
280 | } | ||
281 | |||
282 | r = gpio_direction_output(gpio, 1); | ||
283 | if (r) { | ||
284 | nfc_err(&client->dev, | ||
285 | "Failed to set reset pin direction as output\n"); | ||
286 | return -ENODEV; | ||
287 | } | ||
288 | phy->gpio_reset = gpio; | ||
289 | |||
290 | /* IRQ */ | ||
291 | r = irq_of_parse_and_map(pp, 0); | ||
292 | if (r < 0) { | ||
293 | nfc_err(&client->dev, | ||
294 | "Unable to get irq, error: %d\n", r); | ||
295 | return r; | ||
296 | } | ||
297 | |||
298 | phy->irq_polarity = irq_get_trigger_type(r); | ||
299 | client->irq = r; | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | #else | ||
304 | static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client) | ||
305 | { | ||
306 | return -ENODEV; | ||
307 | } | ||
308 | #endif | ||
309 | |||
310 | static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client) | ||
311 | { | ||
312 | struct st21nfcb_nfc_platform_data *pdata; | ||
313 | struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client); | ||
314 | int r; | ||
315 | int irq; | ||
316 | |||
317 | pdata = client->dev.platform_data; | ||
318 | if (pdata == NULL) { | ||
319 | nfc_err(&client->dev, "No platform data\n"); | ||
320 | return -EINVAL; | ||
321 | } | ||
322 | |||
323 | /* store for later use */ | ||
324 | phy->gpio_irq = pdata->gpio_irq; | ||
325 | phy->gpio_reset = pdata->gpio_reset; | ||
326 | phy->irq_polarity = pdata->irq_polarity; | ||
327 | |||
328 | r = devm_gpio_request(&client->dev, phy->gpio_irq, "wake_up"); | ||
329 | if (r) { | ||
330 | pr_err("%s : gpio_request failed\n", __FILE__); | ||
331 | return -ENODEV; | ||
332 | } | ||
333 | |||
334 | r = gpio_direction_input(phy->gpio_irq); | ||
335 | if (r) { | ||
336 | pr_err("%s : gpio_direction_input failed\n", __FILE__); | ||
337 | return -ENODEV; | ||
338 | } | ||
339 | |||
340 | r = devm_gpio_request(&client->dev, | ||
341 | phy->gpio_reset, "clf_reset"); | ||
342 | if (r) { | ||
343 | pr_err("%s : reset gpio_request failed\n", __FILE__); | ||
344 | return -ENODEV; | ||
345 | } | ||
346 | |||
347 | r = gpio_direction_output(phy->gpio_reset, 1); | ||
348 | if (r) { | ||
349 | pr_err("%s : reset gpio_direction_output failed\n", | ||
350 | __FILE__); | ||
351 | return -ENODEV; | ||
352 | } | ||
353 | |||
354 | /* IRQ */ | ||
355 | irq = gpio_to_irq(phy->gpio_irq); | ||
356 | if (irq < 0) { | ||
357 | nfc_err(&client->dev, | ||
358 | "Unable to get irq number for GPIO %d error %d\n", | ||
359 | phy->gpio_irq, r); | ||
360 | return -ENODEV; | ||
361 | } | ||
362 | client->irq = irq; | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int st21nfcb_nci_i2c_probe(struct i2c_client *client, | ||
368 | const struct i2c_device_id *id) | ||
369 | { | ||
370 | struct st21nfcb_i2c_phy *phy; | ||
371 | struct st21nfcb_nfc_platform_data *pdata; | ||
372 | int r; | ||
373 | |||
374 | dev_dbg(&client->dev, "%s\n", __func__); | ||
375 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | ||
376 | |||
377 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
378 | nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); | ||
379 | return -ENODEV; | ||
380 | } | ||
381 | |||
382 | phy = devm_kzalloc(&client->dev, sizeof(struct st21nfcb_i2c_phy), | ||
383 | GFP_KERNEL); | ||
384 | if (!phy) { | ||
385 | nfc_err(&client->dev, | ||
386 | "Cannot allocate memory for st21nfcb i2c phy.\n"); | ||
387 | return -ENOMEM; | ||
388 | } | ||
389 | |||
390 | phy->i2c_dev = client; | ||
391 | |||
392 | i2c_set_clientdata(client, phy); | ||
393 | |||
394 | pdata = client->dev.platform_data; | ||
395 | if (!pdata && client->dev.of_node) { | ||
396 | r = st21nfcb_nci_i2c_of_request_resources(client); | ||
397 | if (r) { | ||
398 | nfc_err(&client->dev, "No platform data\n"); | ||
399 | return r; | ||
400 | } | ||
401 | } else if (pdata) { | ||
402 | r = st21nfcb_nci_i2c_request_resources(client); | ||
403 | if (r) { | ||
404 | nfc_err(&client->dev, | ||
405 | "Cannot get platform resources\n"); | ||
406 | return r; | ||
407 | } | ||
408 | } else { | ||
409 | nfc_err(&client->dev, | ||
410 | "st21nfcb platform resources not available\n"); | ||
411 | return -ENODEV; | ||
412 | } | ||
413 | |||
414 | r = devm_request_threaded_irq(&client->dev, client->irq, NULL, | ||
415 | st21nfcb_nci_irq_thread_fn, | ||
416 | phy->irq_polarity | IRQF_ONESHOT, | ||
417 | ST21NFCB_NCI_DRIVER_NAME, phy); | ||
418 | if (r < 0) { | ||
419 | nfc_err(&client->dev, "Unable to register IRQ handler\n"); | ||
420 | return r; | ||
421 | } | ||
422 | |||
423 | return ndlc_probe(phy, &i2c_phy_ops, &client->dev, | ||
424 | ST21NFCB_FRAME_HEADROOM, ST21NFCB_FRAME_TAILROOM, | ||
425 | &phy->ndlc); | ||
426 | } | ||
427 | |||
428 | static int st21nfcb_nci_i2c_remove(struct i2c_client *client) | ||
429 | { | ||
430 | struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client); | ||
431 | |||
432 | dev_dbg(&client->dev, "%s\n", __func__); | ||
433 | |||
434 | ndlc_remove(phy->ndlc); | ||
435 | |||
436 | if (phy->powered) | ||
437 | st21nfcb_nci_i2c_disable(phy); | ||
438 | |||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static const struct of_device_id of_st21nfcb_i2c_match[] = { | ||
443 | { .compatible = "st,st21nfcb_i2c", }, | ||
444 | {} | ||
445 | }; | ||
446 | |||
447 | static struct i2c_driver st21nfcb_nci_i2c_driver = { | ||
448 | .driver = { | ||
449 | .owner = THIS_MODULE, | ||
450 | .name = ST21NFCB_NCI_I2C_DRIVER_NAME, | ||
451 | .owner = THIS_MODULE, | ||
452 | .of_match_table = of_match_ptr(of_st21nfcb_i2c_match), | ||
453 | }, | ||
454 | .probe = st21nfcb_nci_i2c_probe, | ||
455 | .id_table = st21nfcb_nci_i2c_id_table, | ||
456 | .remove = st21nfcb_nci_i2c_remove, | ||
457 | }; | ||
458 | |||
459 | module_i2c_driver(st21nfcb_nci_i2c_driver); | ||
460 | |||
461 | MODULE_LICENSE("GPL"); | ||
462 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/nfc/st21nfcb/ndlc.c b/drivers/nfc/st21nfcb/ndlc.c new file mode 100644 index 000000000000..83c97c36112b --- /dev/null +++ b/drivers/nfc/st21nfcb/ndlc.c | |||
@@ -0,0 +1,298 @@ | |||
1 | /* | ||
2 | * Low Level Transport (NDLC) Driver for STMicroelectronics NFC Chip | ||
3 | * | ||
4 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/sched.h> | ||
20 | #include <net/nfc/nci_core.h> | ||
21 | |||
22 | #include "ndlc.h" | ||
23 | #include "st21nfcb.h" | ||
24 | |||
25 | #define NDLC_TIMER_T1 100 | ||
26 | #define NDLC_TIMER_T1_WAIT 400 | ||
27 | #define NDLC_TIMER_T2 1200 | ||
28 | |||
29 | #define PCB_TYPE_DATAFRAME 0x80 | ||
30 | #define PCB_TYPE_SUPERVISOR 0xc0 | ||
31 | #define PCB_TYPE_MASK PCB_TYPE_SUPERVISOR | ||
32 | |||
33 | #define PCB_SYNC_ACK 0x20 | ||
34 | #define PCB_SYNC_NACK 0x10 | ||
35 | #define PCB_SYNC_WAIT 0x30 | ||
36 | #define PCB_SYNC_NOINFO 0x00 | ||
37 | #define PCB_SYNC_MASK PCB_SYNC_WAIT | ||
38 | |||
39 | #define PCB_DATAFRAME_RETRANSMIT_YES 0x00 | ||
40 | #define PCB_DATAFRAME_RETRANSMIT_NO 0x04 | ||
41 | #define PCB_DATAFRAME_RETRANSMIT_MASK PCB_DATAFRAME_RETRANSMIT_NO | ||
42 | |||
43 | #define PCB_SUPERVISOR_RETRANSMIT_YES 0x00 | ||
44 | #define PCB_SUPERVISOR_RETRANSMIT_NO 0x02 | ||
45 | #define PCB_SUPERVISOR_RETRANSMIT_MASK PCB_SUPERVISOR_RETRANSMIT_NO | ||
46 | |||
47 | #define PCB_FRAME_CRC_INFO_PRESENT 0x08 | ||
48 | #define PCB_FRAME_CRC_INFO_NOTPRESENT 0x00 | ||
49 | #define PCB_FRAME_CRC_INFO_MASK PCB_FRAME_CRC_INFO_PRESENT | ||
50 | |||
51 | #define NDLC_DUMP_SKB(info, skb) \ | ||
52 | do { \ | ||
53 | pr_debug("%s:\n", info); \ | ||
54 | print_hex_dump(KERN_DEBUG, "ndlc: ", DUMP_PREFIX_OFFSET, \ | ||
55 | 16, 1, skb->data, skb->len, 0); \ | ||
56 | } while (0) | ||
57 | |||
58 | int ndlc_open(struct llt_ndlc *ndlc) | ||
59 | { | ||
60 | /* toggle reset pin */ | ||
61 | ndlc->ops->enable(ndlc->phy_id); | ||
62 | return 0; | ||
63 | } | ||
64 | EXPORT_SYMBOL(ndlc_open); | ||
65 | |||
66 | void ndlc_close(struct llt_ndlc *ndlc) | ||
67 | { | ||
68 | /* toggle reset pin */ | ||
69 | ndlc->ops->disable(ndlc->phy_id); | ||
70 | } | ||
71 | EXPORT_SYMBOL(ndlc_close); | ||
72 | |||
73 | int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb) | ||
74 | { | ||
75 | /* add ndlc header */ | ||
76 | u8 pcb = PCB_TYPE_DATAFRAME | PCB_DATAFRAME_RETRANSMIT_NO | | ||
77 | PCB_FRAME_CRC_INFO_NOTPRESENT; | ||
78 | |||
79 | *skb_push(skb, 1) = pcb; | ||
80 | skb_queue_tail(&ndlc->send_q, skb); | ||
81 | |||
82 | schedule_work(&ndlc->sm_work); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | EXPORT_SYMBOL(ndlc_send); | ||
87 | |||
88 | static void llt_ndlc_send_queue(struct llt_ndlc *ndlc) | ||
89 | { | ||
90 | struct sk_buff *skb; | ||
91 | int r; | ||
92 | unsigned long time_sent; | ||
93 | |||
94 | if (ndlc->send_q.qlen) | ||
95 | pr_debug("sendQlen=%d unackQlen=%d\n", | ||
96 | ndlc->send_q.qlen, ndlc->ack_pending_q.qlen); | ||
97 | |||
98 | while (ndlc->send_q.qlen) { | ||
99 | skb = skb_dequeue(&ndlc->send_q); | ||
100 | NDLC_DUMP_SKB("ndlc frame written", skb); | ||
101 | r = ndlc->ops->write(ndlc->phy_id, skb); | ||
102 | if (r < 0) { | ||
103 | ndlc->hard_fault = r; | ||
104 | break; | ||
105 | } | ||
106 | time_sent = jiffies; | ||
107 | *(unsigned long *)skb->cb = time_sent; | ||
108 | |||
109 | skb_queue_tail(&ndlc->ack_pending_q, skb); | ||
110 | |||
111 | /* start timer t1 for ndlc aknowledge */ | ||
112 | ndlc->t1_active = true; | ||
113 | mod_timer(&ndlc->t1_timer, time_sent + | ||
114 | msecs_to_jiffies(NDLC_TIMER_T1)); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static void llt_ndlc_requeue_data_pending(struct llt_ndlc *ndlc) | ||
119 | { | ||
120 | struct sk_buff *skb; | ||
121 | u8 pcb; | ||
122 | |||
123 | while ((skb = skb_dequeue_tail(&ndlc->ack_pending_q))) { | ||
124 | pcb = skb->data[0]; | ||
125 | switch (pcb & PCB_TYPE_MASK) { | ||
126 | case PCB_TYPE_SUPERVISOR: | ||
127 | skb->data[0] = (pcb & ~PCB_SUPERVISOR_RETRANSMIT_MASK) | | ||
128 | PCB_SUPERVISOR_RETRANSMIT_YES; | ||
129 | break; | ||
130 | case PCB_TYPE_DATAFRAME: | ||
131 | skb->data[0] = (pcb & ~PCB_DATAFRAME_RETRANSMIT_MASK) | | ||
132 | PCB_DATAFRAME_RETRANSMIT_YES; | ||
133 | break; | ||
134 | default: | ||
135 | pr_err("UNKNOWN Packet Control Byte=%d\n", pcb); | ||
136 | kfree_skb(skb); | ||
137 | break; | ||
138 | } | ||
139 | skb_queue_head(&ndlc->send_q, skb); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static void llt_ndlc_rcv_queue(struct llt_ndlc *ndlc) | ||
144 | { | ||
145 | struct sk_buff *skb; | ||
146 | u8 pcb; | ||
147 | unsigned long time_sent; | ||
148 | |||
149 | if (ndlc->rcv_q.qlen) | ||
150 | pr_debug("rcvQlen=%d\n", ndlc->rcv_q.qlen); | ||
151 | |||
152 | while ((skb = skb_dequeue(&ndlc->rcv_q)) != NULL) { | ||
153 | pcb = skb->data[0]; | ||
154 | skb_pull(skb, 1); | ||
155 | if ((pcb & PCB_TYPE_MASK) == PCB_TYPE_SUPERVISOR) { | ||
156 | switch (pcb & PCB_SYNC_MASK) { | ||
157 | case PCB_SYNC_ACK: | ||
158 | del_timer_sync(&ndlc->t1_timer); | ||
159 | del_timer_sync(&ndlc->t2_timer); | ||
160 | ndlc->t2_active = false; | ||
161 | ndlc->t1_active = false; | ||
162 | break; | ||
163 | case PCB_SYNC_NACK: | ||
164 | llt_ndlc_requeue_data_pending(ndlc); | ||
165 | llt_ndlc_send_queue(ndlc); | ||
166 | /* start timer t1 for ndlc aknowledge */ | ||
167 | time_sent = jiffies; | ||
168 | ndlc->t1_active = true; | ||
169 | mod_timer(&ndlc->t1_timer, time_sent + | ||
170 | msecs_to_jiffies(NDLC_TIMER_T1)); | ||
171 | break; | ||
172 | case PCB_SYNC_WAIT: | ||
173 | time_sent = jiffies; | ||
174 | ndlc->t1_active = true; | ||
175 | mod_timer(&ndlc->t1_timer, time_sent + | ||
176 | msecs_to_jiffies(NDLC_TIMER_T1_WAIT)); | ||
177 | break; | ||
178 | default: | ||
179 | pr_err("UNKNOWN Packet Control Byte=%d\n", pcb); | ||
180 | kfree_skb(skb); | ||
181 | break; | ||
182 | } | ||
183 | } else { | ||
184 | nci_recv_frame(ndlc->ndev, skb); | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | |||
189 | static void llt_ndlc_sm_work(struct work_struct *work) | ||
190 | { | ||
191 | struct llt_ndlc *ndlc = container_of(work, struct llt_ndlc, sm_work); | ||
192 | |||
193 | llt_ndlc_send_queue(ndlc); | ||
194 | llt_ndlc_rcv_queue(ndlc); | ||
195 | |||
196 | if (ndlc->t1_active && timer_pending(&ndlc->t1_timer) == 0) { | ||
197 | pr_debug | ||
198 | ("Handle T1(recv SUPERVISOR) elapsed (T1 now inactive)\n"); | ||
199 | ndlc->t1_active = false; | ||
200 | |||
201 | llt_ndlc_requeue_data_pending(ndlc); | ||
202 | llt_ndlc_send_queue(ndlc); | ||
203 | } | ||
204 | |||
205 | if (ndlc->t2_active && timer_pending(&ndlc->t2_timer) == 0) { | ||
206 | pr_debug("Handle T2(recv DATA) elapsed (T2 now inactive)\n"); | ||
207 | ndlc->t2_active = false; | ||
208 | ndlc->t1_active = false; | ||
209 | del_timer_sync(&ndlc->t1_timer); | ||
210 | |||
211 | ndlc_close(ndlc); | ||
212 | ndlc->hard_fault = -EREMOTEIO; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb) | ||
217 | { | ||
218 | if (skb == NULL) { | ||
219 | pr_err("NULL Frame -> link is dead\n"); | ||
220 | ndlc->hard_fault = -EREMOTEIO; | ||
221 | ndlc_close(ndlc); | ||
222 | } else { | ||
223 | NDLC_DUMP_SKB("incoming frame", skb); | ||
224 | skb_queue_tail(&ndlc->rcv_q, skb); | ||
225 | } | ||
226 | |||
227 | schedule_work(&ndlc->sm_work); | ||
228 | } | ||
229 | EXPORT_SYMBOL(ndlc_recv); | ||
230 | |||
231 | static void ndlc_t1_timeout(unsigned long data) | ||
232 | { | ||
233 | struct llt_ndlc *ndlc = (struct llt_ndlc *)data; | ||
234 | |||
235 | pr_debug("\n"); | ||
236 | |||
237 | schedule_work(&ndlc->sm_work); | ||
238 | } | ||
239 | |||
240 | static void ndlc_t2_timeout(unsigned long data) | ||
241 | { | ||
242 | struct llt_ndlc *ndlc = (struct llt_ndlc *)data; | ||
243 | |||
244 | pr_debug("\n"); | ||
245 | |||
246 | schedule_work(&ndlc->sm_work); | ||
247 | } | ||
248 | |||
249 | int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev, | ||
250 | int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id) | ||
251 | { | ||
252 | struct llt_ndlc *ndlc; | ||
253 | |||
254 | ndlc = devm_kzalloc(dev, sizeof(struct llt_ndlc), GFP_KERNEL); | ||
255 | if (!ndlc) { | ||
256 | nfc_err(dev, "Cannot allocate memory for ndlc.\n"); | ||
257 | return -ENOMEM; | ||
258 | } | ||
259 | ndlc->ops = phy_ops; | ||
260 | ndlc->phy_id = phy_id; | ||
261 | ndlc->dev = dev; | ||
262 | |||
263 | *ndlc_id = ndlc; | ||
264 | |||
265 | /* start timers */ | ||
266 | init_timer(&ndlc->t1_timer); | ||
267 | ndlc->t1_timer.data = (unsigned long)ndlc; | ||
268 | ndlc->t1_timer.function = ndlc_t1_timeout; | ||
269 | |||
270 | init_timer(&ndlc->t2_timer); | ||
271 | ndlc->t2_timer.data = (unsigned long)ndlc; | ||
272 | ndlc->t2_timer.function = ndlc_t2_timeout; | ||
273 | |||
274 | skb_queue_head_init(&ndlc->rcv_q); | ||
275 | skb_queue_head_init(&ndlc->send_q); | ||
276 | skb_queue_head_init(&ndlc->ack_pending_q); | ||
277 | |||
278 | INIT_WORK(&ndlc->sm_work, llt_ndlc_sm_work); | ||
279 | |||
280 | return st21nfcb_nci_probe(ndlc, phy_headroom, phy_tailroom); | ||
281 | } | ||
282 | EXPORT_SYMBOL(ndlc_probe); | ||
283 | |||
284 | void ndlc_remove(struct llt_ndlc *ndlc) | ||
285 | { | ||
286 | /* cancel timers */ | ||
287 | del_timer_sync(&ndlc->t1_timer); | ||
288 | del_timer_sync(&ndlc->t2_timer); | ||
289 | ndlc->t2_active = false; | ||
290 | ndlc->t1_active = false; | ||
291 | |||
292 | skb_queue_purge(&ndlc->rcv_q); | ||
293 | skb_queue_purge(&ndlc->send_q); | ||
294 | |||
295 | st21nfcb_nci_remove(ndlc->ndev); | ||
296 | kfree(ndlc); | ||
297 | } | ||
298 | EXPORT_SYMBOL(ndlc_remove); | ||
diff --git a/drivers/nfc/st21nfcb/ndlc.h b/drivers/nfc/st21nfcb/ndlc.h new file mode 100644 index 000000000000..c30a2f0faa5f --- /dev/null +++ b/drivers/nfc/st21nfcb/ndlc.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * NCI based Driver for STMicroelectronics NFC Chip | ||
3 | * | ||
4 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #ifndef __LOCAL_NDLC_H_ | ||
20 | #define __LOCAL_NDLC_H_ | ||
21 | |||
22 | #include <linux/skbuff.h> | ||
23 | #include <net/nfc/nfc.h> | ||
24 | |||
25 | /* Low Level Transport description */ | ||
26 | struct llt_ndlc { | ||
27 | struct nci_dev *ndev; | ||
28 | struct nfc_phy_ops *ops; | ||
29 | void *phy_id; | ||
30 | |||
31 | struct timer_list t1_timer; | ||
32 | bool t1_active; | ||
33 | |||
34 | struct timer_list t2_timer; | ||
35 | bool t2_active; | ||
36 | |||
37 | struct sk_buff_head rcv_q; | ||
38 | struct sk_buff_head send_q; | ||
39 | struct sk_buff_head ack_pending_q; | ||
40 | |||
41 | struct work_struct sm_work; | ||
42 | |||
43 | struct device *dev; | ||
44 | |||
45 | int hard_fault; | ||
46 | }; | ||
47 | |||
48 | int ndlc_open(struct llt_ndlc *ndlc); | ||
49 | void ndlc_close(struct llt_ndlc *ndlc); | ||
50 | int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb); | ||
51 | void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb); | ||
52 | int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev, | ||
53 | int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id); | ||
54 | void ndlc_remove(struct llt_ndlc *ndlc); | ||
55 | #endif /* __LOCAL_NDLC_H__ */ | ||
diff --git a/drivers/nfc/st21nfcb/st21nfcb.c b/drivers/nfc/st21nfcb/st21nfcb.c new file mode 100644 index 000000000000..4d95863e3063 --- /dev/null +++ b/drivers/nfc/st21nfcb/st21nfcb.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * NCI based Driver for STMicroelectronics NFC Chip | ||
3 | * | ||
4 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/nfc.h> | ||
21 | #include <net/nfc/nci.h> | ||
22 | #include <net/nfc/nci_core.h> | ||
23 | |||
24 | #include "st21nfcb.h" | ||
25 | #include "ndlc.h" | ||
26 | |||
27 | #define DRIVER_DESC "NCI NFC driver for ST21NFCB" | ||
28 | |||
29 | static int st21nfcb_nci_open(struct nci_dev *ndev) | ||
30 | { | ||
31 | struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); | ||
32 | int r; | ||
33 | |||
34 | if (test_and_set_bit(ST21NFCB_NCI_RUNNING, &info->flags)) | ||
35 | return 0; | ||
36 | |||
37 | r = ndlc_open(info->ndlc); | ||
38 | if (r) | ||
39 | clear_bit(ST21NFCB_NCI_RUNNING, &info->flags); | ||
40 | |||
41 | return r; | ||
42 | } | ||
43 | |||
44 | static int st21nfcb_nci_close(struct nci_dev *ndev) | ||
45 | { | ||
46 | struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); | ||
47 | |||
48 | if (!test_and_clear_bit(ST21NFCB_NCI_RUNNING, &info->flags)) | ||
49 | return 0; | ||
50 | |||
51 | ndlc_close(info->ndlc); | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int st21nfcb_nci_send(struct nci_dev *ndev, struct sk_buff *skb) | ||
57 | { | ||
58 | struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); | ||
59 | |||
60 | skb->dev = (void *)ndev; | ||
61 | |||
62 | if (!test_bit(ST21NFCB_NCI_RUNNING, &info->flags)) | ||
63 | return -EBUSY; | ||
64 | |||
65 | return ndlc_send(info->ndlc, skb); | ||
66 | } | ||
67 | |||
68 | static struct nci_ops st21nfcb_nci_ops = { | ||
69 | .open = st21nfcb_nci_open, | ||
70 | .close = st21nfcb_nci_close, | ||
71 | .send = st21nfcb_nci_send, | ||
72 | }; | ||
73 | |||
74 | int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom, | ||
75 | int phy_tailroom) | ||
76 | { | ||
77 | struct st21nfcb_nci_info *info; | ||
78 | int r; | ||
79 | u32 protocols; | ||
80 | |||
81 | info = devm_kzalloc(ndlc->dev, | ||
82 | sizeof(struct st21nfcb_nci_info), GFP_KERNEL); | ||
83 | if (!info) | ||
84 | return -ENOMEM; | ||
85 | |||
86 | protocols = NFC_PROTO_JEWEL_MASK | ||
87 | | NFC_PROTO_MIFARE_MASK | ||
88 | | NFC_PROTO_FELICA_MASK | ||
89 | | NFC_PROTO_ISO14443_MASK | ||
90 | | NFC_PROTO_ISO14443_B_MASK | ||
91 | | NFC_PROTO_NFC_DEP_MASK; | ||
92 | |||
93 | ndlc->ndev = nci_allocate_device(&st21nfcb_nci_ops, protocols, | ||
94 | phy_headroom, phy_tailroom); | ||
95 | if (!ndlc->ndev) { | ||
96 | pr_err("Cannot allocate nfc ndev\n"); | ||
97 | r = -ENOMEM; | ||
98 | goto err_alloc_ndev; | ||
99 | } | ||
100 | info->ndlc = ndlc; | ||
101 | |||
102 | nci_set_drvdata(ndlc->ndev, info); | ||
103 | |||
104 | r = nci_register_device(ndlc->ndev); | ||
105 | if (r) | ||
106 | goto err_regdev; | ||
107 | |||
108 | return r; | ||
109 | err_regdev: | ||
110 | nci_free_device(ndlc->ndev); | ||
111 | |||
112 | err_alloc_ndev: | ||
113 | kfree(info); | ||
114 | return r; | ||
115 | } | ||
116 | EXPORT_SYMBOL_GPL(st21nfcb_nci_probe); | ||
117 | |||
118 | void st21nfcb_nci_remove(struct nci_dev *ndev) | ||
119 | { | ||
120 | struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); | ||
121 | |||
122 | nci_unregister_device(ndev); | ||
123 | nci_free_device(ndev); | ||
124 | kfree(info); | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(st21nfcb_nci_remove); | ||
127 | |||
128 | MODULE_LICENSE("GPL"); | ||
129 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/nfc/st21nfcb/st21nfcb.h b/drivers/nfc/st21nfcb/st21nfcb.h new file mode 100644 index 000000000000..4bbbebb9f34d --- /dev/null +++ b/drivers/nfc/st21nfcb/st21nfcb.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * NCI based Driver for STMicroelectronics NFC Chip | ||
3 | * | ||
4 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #ifndef __LOCAL_ST21NFCB_H_ | ||
20 | #define __LOCAL_ST21NFCB_H_ | ||
21 | |||
22 | #include <net/nfc/nci_core.h> | ||
23 | |||
24 | #include "ndlc.h" | ||
25 | |||
26 | /* Define private flags: */ | ||
27 | #define ST21NFCB_NCI_RUNNING 1 | ||
28 | |||
29 | struct st21nfcb_nci_info { | ||
30 | struct llt_ndlc *ndlc; | ||
31 | unsigned long flags; | ||
32 | }; | ||
33 | |||
34 | void st21nfcb_nci_remove(struct nci_dev *ndev); | ||
35 | int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom, | ||
36 | int phy_tailroom); | ||
37 | |||
38 | #endif /* __LOCAL_ST21NFCB_H_ */ | ||
diff --git a/include/linux/platform_data/st21nfcb.h b/include/linux/platform_data/st21nfcb.h new file mode 100644 index 000000000000..2d11f1f5efab --- /dev/null +++ b/include/linux/platform_data/st21nfcb.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Driver include for the ST21NFCB NFC chip. | ||
3 | * | ||
4 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #ifndef _ST21NFCB_NCI_H_ | ||
20 | #define _ST21NFCB_NCI_H_ | ||
21 | |||
22 | #include <linux/i2c.h> | ||
23 | |||
24 | #define ST21NFCB_NCI_DRIVER_NAME "st21nfcb_nci" | ||
25 | |||
26 | struct st21nfcb_nfc_platform_data { | ||
27 | unsigned int gpio_irq; | ||
28 | unsigned int gpio_reset; | ||
29 | unsigned int irq_polarity; | ||
30 | }; | ||
31 | |||
32 | #endif /* _ST21NFCA_HCI_H_ */ | ||
diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h index bdf55c3b7a19..d9a5cf7ac1c4 100644 --- a/include/net/nfc/digital.h +++ b/include/net/nfc/digital.h | |||
@@ -49,6 +49,7 @@ enum { | |||
49 | NFC_DIGITAL_FRAMING_NFCA_SHORT = 0, | 49 | NFC_DIGITAL_FRAMING_NFCA_SHORT = 0, |
50 | NFC_DIGITAL_FRAMING_NFCA_STANDARD, | 50 | NFC_DIGITAL_FRAMING_NFCA_STANDARD, |
51 | NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A, | 51 | NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A, |
52 | NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE, | ||
52 | 53 | ||
53 | NFC_DIGITAL_FRAMING_NFCA_T1T, | 54 | NFC_DIGITAL_FRAMING_NFCA_T1T, |
54 | NFC_DIGITAL_FRAMING_NFCA_T2T, | 55 | NFC_DIGITAL_FRAMING_NFCA_T2T, |
@@ -126,6 +127,15 @@ typedef void (*nfc_digital_cmd_complete_t)(struct nfc_digital_dev *ddev, | |||
126 | * the NFC-DEP ATR_REQ command through cb. The digital stack deducts the RF | 127 | * the NFC-DEP ATR_REQ command through cb. The digital stack deducts the RF |
127 | * tech by analyzing the SoD of the frame containing the ATR_REQ command. | 128 | * tech by analyzing the SoD of the frame containing the ATR_REQ command. |
128 | * This is an asynchronous function. | 129 | * This is an asynchronous function. |
130 | * @tg_listen_md: If supported, put the device in automatic listen mode with | ||
131 | * mode detection but without automatic anti-collision. In this mode, the | ||
132 | * device automatically detects the RF technology. What the actual | ||
133 | * RF technology is can be retrieved by calling @tg_get_rf_tech. | ||
134 | * The digital stack will then perform the appropriate anti-collision | ||
135 | * sequence. This is an asynchronous function. | ||
136 | * @tg_get_rf_tech: Required when @tg_listen_md is supported, unused otherwise. | ||
137 | * Return the RF Technology that was detected by the @tg_listen_md call. | ||
138 | * This is a synchronous function. | ||
129 | * | 139 | * |
130 | * @switch_rf: Turns device radio on or off. The stack does not call explicitly | 140 | * @switch_rf: Turns device radio on or off. The stack does not call explicitly |
131 | * switch_rf to turn the radio on. A call to in|tg_configure_hw must turn | 141 | * switch_rf to turn the radio on. A call to in|tg_configure_hw must turn |
@@ -160,6 +170,9 @@ struct nfc_digital_ops { | |||
160 | struct digital_tg_mdaa_params *mdaa_params, | 170 | struct digital_tg_mdaa_params *mdaa_params, |
161 | u16 timeout, nfc_digital_cmd_complete_t cb, | 171 | u16 timeout, nfc_digital_cmd_complete_t cb, |
162 | void *arg); | 172 | void *arg); |
173 | int (*tg_listen_md)(struct nfc_digital_dev *ddev, u16 timeout, | ||
174 | nfc_digital_cmd_complete_t cb, void *arg); | ||
175 | int (*tg_get_rf_tech)(struct nfc_digital_dev *ddev, u8 *rf_tech); | ||
163 | 176 | ||
164 | int (*switch_rf)(struct nfc_digital_dev *ddev, bool on); | 177 | int (*switch_rf)(struct nfc_digital_dev *ddev, bool on); |
165 | void (*abort_cmd)(struct nfc_digital_dev *ddev); | 178 | void (*abort_cmd)(struct nfc_digital_dev *ddev); |
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 61286db54388..7ee8f4cc610b 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h | |||
@@ -37,6 +37,7 @@ struct nfc_hci_ops { | |||
37 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); | 37 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); |
38 | int (*start_poll) (struct nfc_hci_dev *hdev, | 38 | int (*start_poll) (struct nfc_hci_dev *hdev, |
39 | u32 im_protocols, u32 tm_protocols); | 39 | u32 im_protocols, u32 tm_protocols); |
40 | void (*stop_poll) (struct nfc_hci_dev *hdev); | ||
40 | int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target, | 41 | int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target, |
41 | u8 comm_mode, u8 *gb, size_t gb_len); | 42 | u8 comm_mode, u8 *gb, size_t gb_len); |
42 | int (*dep_link_down)(struct nfc_hci_dev *hdev); | 43 | int (*dep_link_down)(struct nfc_hci_dev *hdev); |
diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 71ad7eefddd4..3c39c72eb038 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define DIGITAL_CMD_TG_SEND 1 | 29 | #define DIGITAL_CMD_TG_SEND 1 |
30 | #define DIGITAL_CMD_TG_LISTEN 2 | 30 | #define DIGITAL_CMD_TG_LISTEN 2 |
31 | #define DIGITAL_CMD_TG_LISTEN_MDAA 3 | 31 | #define DIGITAL_CMD_TG_LISTEN_MDAA 3 |
32 | #define DIGITAL_CMD_TG_LISTEN_MD 4 | ||
32 | 33 | ||
33 | #define DIGITAL_MAX_HEADER_LEN 7 | 34 | #define DIGITAL_MAX_HEADER_LEN 7 |
34 | #define DIGITAL_CRC_LEN 2 | 35 | #define DIGITAL_CRC_LEN 2 |
@@ -121,6 +122,8 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb); | |||
121 | 122 | ||
122 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech); | 123 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech); |
123 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech); | 124 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech); |
125 | void digital_tg_recv_md_req(struct nfc_digital_dev *ddev, void *arg, | ||
126 | struct sk_buff *resp); | ||
124 | 127 | ||
125 | typedef u16 (*crc_func_t)(u16, const u8 *, size_t); | 128 | typedef u16 (*crc_func_t)(u16, const u8 *, size_t); |
126 | 129 | ||
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index a6ce3c627e4e..009bcf317101 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c | |||
@@ -201,6 +201,11 @@ static void digital_wq_cmd(struct work_struct *work) | |||
201 | digital_send_cmd_complete, cmd); | 201 | digital_send_cmd_complete, cmd); |
202 | break; | 202 | break; |
203 | 203 | ||
204 | case DIGITAL_CMD_TG_LISTEN_MD: | ||
205 | rc = ddev->ops->tg_listen_md(ddev, cmd->timeout, | ||
206 | digital_send_cmd_complete, cmd); | ||
207 | break; | ||
208 | |||
204 | default: | 209 | default: |
205 | pr_err("Unknown cmd type %d\n", cmd->type); | 210 | pr_err("Unknown cmd type %d\n", cmd->type); |
206 | return; | 211 | return; |
@@ -293,12 +298,19 @@ static int digital_tg_listen_mdaa(struct nfc_digital_dev *ddev, u8 rf_tech) | |||
293 | 500, digital_tg_recv_atr_req, NULL); | 298 | 500, digital_tg_recv_atr_req, NULL); |
294 | } | 299 | } |
295 | 300 | ||
301 | static int digital_tg_listen_md(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
302 | { | ||
303 | return digital_send_cmd(ddev, DIGITAL_CMD_TG_LISTEN_MD, NULL, NULL, 500, | ||
304 | digital_tg_recv_md_req, NULL); | ||
305 | } | ||
306 | |||
296 | int digital_target_found(struct nfc_digital_dev *ddev, | 307 | int digital_target_found(struct nfc_digital_dev *ddev, |
297 | struct nfc_target *target, u8 protocol) | 308 | struct nfc_target *target, u8 protocol) |
298 | { | 309 | { |
299 | int rc; | 310 | int rc; |
300 | u8 framing; | 311 | u8 framing; |
301 | u8 rf_tech; | 312 | u8 rf_tech; |
313 | u8 poll_tech_count; | ||
302 | int (*check_crc)(struct sk_buff *skb); | 314 | int (*check_crc)(struct sk_buff *skb); |
303 | void (*add_crc)(struct sk_buff *skb); | 315 | void (*add_crc)(struct sk_buff *skb); |
304 | 316 | ||
@@ -375,12 +387,16 @@ int digital_target_found(struct nfc_digital_dev *ddev, | |||
375 | return rc; | 387 | return rc; |
376 | 388 | ||
377 | target->supported_protocols = (1 << protocol); | 389 | target->supported_protocols = (1 << protocol); |
378 | rc = nfc_targets_found(ddev->nfc_dev, target, 1); | ||
379 | if (rc) | ||
380 | return rc; | ||
381 | 390 | ||
391 | poll_tech_count = ddev->poll_tech_count; | ||
382 | ddev->poll_tech_count = 0; | 392 | ddev->poll_tech_count = 0; |
383 | 393 | ||
394 | rc = nfc_targets_found(ddev->nfc_dev, target, 1); | ||
395 | if (rc) { | ||
396 | ddev->poll_tech_count = poll_tech_count; | ||
397 | return rc; | ||
398 | } | ||
399 | |||
384 | return 0; | 400 | return 0; |
385 | } | 401 | } |
386 | 402 | ||
@@ -505,6 +521,9 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | |||
505 | if (ddev->ops->tg_listen_mdaa) { | 521 | if (ddev->ops->tg_listen_mdaa) { |
506 | digital_add_poll_tech(ddev, 0, | 522 | digital_add_poll_tech(ddev, 0, |
507 | digital_tg_listen_mdaa); | 523 | digital_tg_listen_mdaa); |
524 | } else if (ddev->ops->tg_listen_md) { | ||
525 | digital_add_poll_tech(ddev, 0, | ||
526 | digital_tg_listen_md); | ||
508 | } else { | 527 | } else { |
509 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | 528 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, |
510 | digital_tg_listen_nfca); | 529 | digital_tg_listen_nfca); |
@@ -732,7 +751,7 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | |||
732 | 751 | ||
733 | if (!ops->in_configure_hw || !ops->in_send_cmd || !ops->tg_listen || | 752 | if (!ops->in_configure_hw || !ops->in_send_cmd || !ops->tg_listen || |
734 | !ops->tg_configure_hw || !ops->tg_send_cmd || !ops->abort_cmd || | 753 | !ops->tg_configure_hw || !ops->tg_send_cmd || !ops->abort_cmd || |
735 | !ops->switch_rf) | 754 | !ops->switch_rf || (ops->tg_listen_md && !ops->tg_get_rf_tech)) |
736 | return NULL; | 755 | return NULL; |
737 | 756 | ||
738 | ddev = kzalloc(sizeof(struct nfc_digital_dev), GFP_KERNEL); | 757 | ddev = kzalloc(sizeof(struct nfc_digital_dev), GFP_KERNEL); |
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c index 171cb9949ab5..7cc1830633cc 100644 --- a/net/nfc/digital_dep.c +++ b/net/nfc/digital_dep.c | |||
@@ -673,6 +673,7 @@ void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | |||
673 | int rc; | 673 | int rc; |
674 | struct digital_atr_req *atr_req; | 674 | struct digital_atr_req *atr_req; |
675 | size_t gb_len, min_size; | 675 | size_t gb_len, min_size; |
676 | u8 poll_tech_count; | ||
676 | 677 | ||
677 | if (IS_ERR(resp)) { | 678 | if (IS_ERR(resp)) { |
678 | rc = PTR_ERR(resp); | 679 | rc = PTR_ERR(resp); |
@@ -730,12 +731,16 @@ void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | |||
730 | goto exit; | 731 | goto exit; |
731 | 732 | ||
732 | gb_len = resp->len - sizeof(struct digital_atr_req); | 733 | gb_len = resp->len - sizeof(struct digital_atr_req); |
734 | |||
735 | poll_tech_count = ddev->poll_tech_count; | ||
736 | ddev->poll_tech_count = 0; | ||
737 | |||
733 | rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | 738 | rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, |
734 | NFC_COMM_PASSIVE, atr_req->gb, gb_len); | 739 | NFC_COMM_PASSIVE, atr_req->gb, gb_len); |
735 | if (rc) | 740 | if (rc) { |
741 | ddev->poll_tech_count = poll_tech_count; | ||
736 | goto exit; | 742 | goto exit; |
737 | 743 | } | |
738 | ddev->poll_tech_count = 0; | ||
739 | 744 | ||
740 | rc = 0; | 745 | rc = 0; |
741 | exit: | 746 | exit: |
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index c2c1c0189b7c..fb58ed2dd41d 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c | |||
@@ -318,6 +318,8 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
318 | 318 | ||
319 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { | 319 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { |
320 | nfc_proto = NFC_PROTO_MIFARE; | 320 | nfc_proto = NFC_PROTO_MIFARE; |
321 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { | ||
322 | nfc_proto = NFC_PROTO_NFC_DEP; | ||
321 | } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) { | 323 | } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) { |
322 | rc = digital_in_send_rats(ddev, target); | 324 | rc = digital_in_send_rats(ddev, target); |
323 | if (rc) | 325 | if (rc) |
@@ -327,8 +329,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
327 | * done when receiving the ATS | 329 | * done when receiving the ATS |
328 | */ | 330 | */ |
329 | goto exit_free_skb; | 331 | goto exit_free_skb; |
330 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { | ||
331 | nfc_proto = NFC_PROTO_NFC_DEP; | ||
332 | } else { | 332 | } else { |
333 | rc = -EOPNOTSUPP; | 333 | rc = -EOPNOTSUPP; |
334 | goto exit; | 334 | goto exit; |
@@ -944,6 +944,13 @@ static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) | |||
944 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) | 944 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) |
945 | digital_skb_add_crc_a(skb); | 945 | digital_skb_add_crc_a(skb); |
946 | 946 | ||
947 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
948 | NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE); | ||
949 | if (rc) { | ||
950 | kfree_skb(skb); | ||
951 | return rc; | ||
952 | } | ||
953 | |||
947 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_atr_req, | 954 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_atr_req, |
948 | NULL); | 955 | NULL); |
949 | if (rc) | 956 | if (rc) |
@@ -1002,6 +1009,13 @@ static int digital_tg_send_sdd_res(struct nfc_digital_dev *ddev) | |||
1002 | for (i = 0; i < 4; i++) | 1009 | for (i = 0; i < 4; i++) |
1003 | sdd_res->bcc ^= sdd_res->nfcid1[i]; | 1010 | sdd_res->bcc ^= sdd_res->nfcid1[i]; |
1004 | 1011 | ||
1012 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
1013 | NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A); | ||
1014 | if (rc) { | ||
1015 | kfree_skb(skb); | ||
1016 | return rc; | ||
1017 | } | ||
1018 | |||
1005 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sel_req, | 1019 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sel_req, |
1006 | NULL); | 1020 | NULL); |
1007 | if (rc) | 1021 | if (rc) |
@@ -1054,6 +1068,13 @@ static int digital_tg_send_sens_res(struct nfc_digital_dev *ddev) | |||
1054 | sens_res[0] = (DIGITAL_SENS_RES_NFC_DEP >> 8) & 0xFF; | 1068 | sens_res[0] = (DIGITAL_SENS_RES_NFC_DEP >> 8) & 0xFF; |
1055 | sens_res[1] = DIGITAL_SENS_RES_NFC_DEP & 0xFF; | 1069 | sens_res[1] = DIGITAL_SENS_RES_NFC_DEP & 0xFF; |
1056 | 1070 | ||
1071 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
1072 | NFC_DIGITAL_FRAMING_NFCA_STANDARD); | ||
1073 | if (rc) { | ||
1074 | kfree_skb(skb); | ||
1075 | return rc; | ||
1076 | } | ||
1077 | |||
1057 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sdd_req, | 1078 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sdd_req, |
1058 | NULL); | 1079 | NULL); |
1059 | if (rc) | 1080 | if (rc) |
@@ -1197,33 +1218,48 @@ exit: | |||
1197 | dev_kfree_skb(resp); | 1218 | dev_kfree_skb(resp); |
1198 | } | 1219 | } |
1199 | 1220 | ||
1200 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech) | 1221 | static int digital_tg_config_nfca(struct nfc_digital_dev *ddev) |
1201 | { | 1222 | { |
1202 | int rc; | 1223 | int rc; |
1203 | 1224 | ||
1204 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | 1225 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, |
1226 | NFC_DIGITAL_RF_TECH_106A); | ||
1205 | if (rc) | 1227 | if (rc) |
1206 | return rc; | 1228 | return rc; |
1207 | 1229 | ||
1208 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | 1230 | return digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, |
1209 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); | 1231 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); |
1232 | } | ||
1233 | |||
1234 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
1235 | { | ||
1236 | int rc; | ||
1237 | |||
1238 | rc = digital_tg_config_nfca(ddev); | ||
1210 | if (rc) | 1239 | if (rc) |
1211 | return rc; | 1240 | return rc; |
1212 | 1241 | ||
1213 | return digital_tg_listen(ddev, 300, digital_tg_recv_sens_req, NULL); | 1242 | return digital_tg_listen(ddev, 300, digital_tg_recv_sens_req, NULL); |
1214 | } | 1243 | } |
1215 | 1244 | ||
1216 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | 1245 | static int digital_tg_config_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) |
1217 | { | 1246 | { |
1218 | int rc; | 1247 | int rc; |
1219 | u8 *nfcid2; | ||
1220 | 1248 | ||
1221 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | 1249 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); |
1222 | if (rc) | 1250 | if (rc) |
1223 | return rc; | 1251 | return rc; |
1224 | 1252 | ||
1225 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | 1253 | return digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, |
1226 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP); | 1254 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP); |
1255 | } | ||
1256 | |||
1257 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
1258 | { | ||
1259 | int rc; | ||
1260 | u8 *nfcid2; | ||
1261 | |||
1262 | rc = digital_tg_config_nfcf(ddev, rf_tech); | ||
1227 | if (rc) | 1263 | if (rc) |
1228 | return rc; | 1264 | return rc; |
1229 | 1265 | ||
@@ -1237,3 +1273,43 @@ int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | |||
1237 | 1273 | ||
1238 | return digital_tg_listen(ddev, 300, digital_tg_recv_sensf_req, nfcid2); | 1274 | return digital_tg_listen(ddev, 300, digital_tg_recv_sensf_req, nfcid2); |
1239 | } | 1275 | } |
1276 | |||
1277 | void digital_tg_recv_md_req(struct nfc_digital_dev *ddev, void *arg, | ||
1278 | struct sk_buff *resp) | ||
1279 | { | ||
1280 | u8 rf_tech; | ||
1281 | int rc; | ||
1282 | |||
1283 | if (IS_ERR(resp)) { | ||
1284 | resp = NULL; | ||
1285 | goto exit_free_skb; | ||
1286 | } | ||
1287 | |||
1288 | rc = ddev->ops->tg_get_rf_tech(ddev, &rf_tech); | ||
1289 | if (rc) | ||
1290 | goto exit_free_skb; | ||
1291 | |||
1292 | switch (rf_tech) { | ||
1293 | case NFC_DIGITAL_RF_TECH_106A: | ||
1294 | rc = digital_tg_config_nfca(ddev); | ||
1295 | if (rc) | ||
1296 | goto exit_free_skb; | ||
1297 | digital_tg_recv_sens_req(ddev, arg, resp); | ||
1298 | break; | ||
1299 | case NFC_DIGITAL_RF_TECH_212F: | ||
1300 | case NFC_DIGITAL_RF_TECH_424F: | ||
1301 | rc = digital_tg_config_nfcf(ddev, rf_tech); | ||
1302 | if (rc) | ||
1303 | goto exit_free_skb; | ||
1304 | digital_tg_recv_sensf_req(ddev, arg, resp); | ||
1305 | break; | ||
1306 | default: | ||
1307 | goto exit_free_skb; | ||
1308 | } | ||
1309 | |||
1310 | return; | ||
1311 | |||
1312 | exit_free_skb: | ||
1313 | digital_poll_next_tech(ddev); | ||
1314 | dev_kfree_skb(resp); | ||
1315 | } | ||
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 47403705197e..117708263ced 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -553,8 +553,11 @@ static void hci_stop_poll(struct nfc_dev *nfc_dev) | |||
553 | { | 553 | { |
554 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 554 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
555 | 555 | ||
556 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 556 | if (hdev->ops->stop_poll) |
557 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | 557 | hdev->ops->stop_poll(hdev); |
558 | else | ||
559 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
560 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
558 | } | 561 | } |
559 | 562 | ||
560 | static int hci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | 563 | static int hci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index f8f6af231381..df91bb95b12a 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
@@ -166,7 +166,9 @@ static int nci_add_new_protocol(struct nci_dev *ndev, | |||
166 | struct rf_tech_specific_params_nfcf_poll *nfcf_poll; | 166 | struct rf_tech_specific_params_nfcf_poll *nfcf_poll; |
167 | __u32 protocol; | 167 | __u32 protocol; |
168 | 168 | ||
169 | if (rf_protocol == NCI_RF_PROTOCOL_T2T) | 169 | if (rf_protocol == NCI_RF_PROTOCOL_T1T) |
170 | protocol = NFC_PROTO_JEWEL_MASK; | ||
171 | else if (rf_protocol == NCI_RF_PROTOCOL_T2T) | ||
170 | protocol = NFC_PROTO_MIFARE_MASK; | 172 | protocol = NFC_PROTO_MIFARE_MASK; |
171 | else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) | 173 | else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) |
172 | if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) | 174 | if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) |