aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/digital_dep.c
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2013-09-19 11:55:30 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-09-24 20:02:28 -0400
commit1c7a4c24fbfd99442cc6e14dc80fcb00f118e8b8 (patch)
treed8115482922f1d4b5c7da4a6aa76faca7f77c032 /net/nfc/digital_dep.c
parent7d0911c02fa2a448a28d7844d2a0c439ff8397b1 (diff)
NFC Digital: Add target NFC-DEP support
This adds support for NFC-DEP target mode for NFC-A and NFC-F technologies. If the driver provides it, the stack uses an automatic mode for technology detection and automatic anti-collision. Otherwise the stack tries to use non-automatic synchronization and listens for SENS_REQ and SENSF_REQ commands. The detection, activation, and data exchange procedures work exactly the same way as in initiator mode, as described in the previous commits, except that the digital stack waits for commands and sends responses back to the peer device. Signed-off-by: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc/digital_dep.c')
-rw-r--r--net/nfc/digital_dep.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index be984c4204d2..810d00c9cd5d 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -379,3 +379,349 @@ int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
379 return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, 379 return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
380 data_exch); 380 data_exch);
381} 381}
382
383static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
384 struct sk_buff *resp)
385{
386 int rc;
387 struct digital_dep_req_res *dep_req;
388 size_t size;
389
390 if (IS_ERR(resp)) {
391 rc = PTR_ERR(resp);
392 resp = NULL;
393 goto exit;
394 }
395
396 rc = ddev->skb_check_crc(resp);
397 if (rc) {
398 PROTOCOL_ERR("14.4.1.6");
399 goto exit;
400 }
401
402 rc = digital_skb_pull_dep_sod(ddev, resp);
403 if (rc) {
404 PROTOCOL_ERR("14.4.1.2");
405 goto exit;
406 }
407
408 size = sizeof(struct digital_dep_req_res);
409 dep_req = (struct digital_dep_req_res *)resp->data;
410
411 if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
412 dep_req->cmd != DIGITAL_CMD_DEP_REQ) {
413 rc = -EIO;
414 goto exit;
415 }
416
417 if (DIGITAL_NFC_DEP_DID_BIT_SET(dep_req->pfb))
418 size++;
419
420 if (resp->len < size) {
421 rc = -EIO;
422 goto exit;
423 }
424
425 switch (DIGITAL_NFC_DEP_PFB_TYPE(dep_req->pfb)) {
426 case DIGITAL_NFC_DEP_PFB_I_PDU:
427 PR_DBG("DIGITAL_NFC_DEP_PFB_I_PDU");
428 ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(dep_req->pfb);
429 break;
430 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
431 PR_ERR("Received a ACK/NACK PDU");
432 rc = -EINVAL;
433 goto exit;
434 break;
435 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
436 PR_ERR("Received a SUPERVISOR PDU");
437 rc = -EINVAL;
438 goto exit;
439 break;
440 }
441
442 skb_pull(resp, size);
443
444 rc = nfc_tm_data_received(ddev->nfc_dev, resp);
445
446exit:
447 if (rc)
448 kfree_skb(resp);
449}
450
451int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
452{
453 struct digital_dep_req_res *dep_res;
454
455 skb_push(skb, sizeof(struct digital_dep_req_res));
456 dep_res = (struct digital_dep_req_res *)skb->data;
457
458 dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
459 dep_res->cmd = DIGITAL_CMD_DEP_RES;
460 dep_res->pfb = ddev->curr_nfc_dep_pni;
461
462 digital_skb_push_dep_sod(ddev, skb);
463
464 ddev->skb_add_crc(skb);
465
466 return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
467 NULL);
468}
469
470static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
471 void *arg, struct sk_buff *resp)
472{
473 u8 rf_tech = PTR_ERR(arg);
474
475 if (IS_ERR(resp))
476 return;
477
478 digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
479
480 digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL);
481
482 dev_kfree_skb(resp);
483}
484
485static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did,
486 u8 rf_tech)
487{
488 struct digital_psl_res *psl_res;
489 struct sk_buff *skb;
490 int rc;
491
492 skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res));
493 if (!skb)
494 return -ENOMEM;
495
496 skb_put(skb, sizeof(struct digital_psl_res));
497
498 psl_res = (struct digital_psl_res *)skb->data;
499
500 psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
501 psl_res->cmd = DIGITAL_CMD_PSL_RES;
502 psl_res->did = did;
503
504 digital_skb_push_dep_sod(ddev, skb);
505
506 ddev->skb_add_crc(skb);
507
508 rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
509 ERR_PTR(rf_tech));
510
511 if (rc)
512 kfree_skb(skb);
513
514 return rc;
515}
516
517static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
518 struct sk_buff *resp)
519{
520 int rc;
521 struct digital_psl_req *psl_req;
522 u8 rf_tech;
523 u8 dsi;
524
525 if (IS_ERR(resp)) {
526 rc = PTR_ERR(resp);
527 resp = NULL;
528 goto exit;
529 }
530
531 rc = ddev->skb_check_crc(resp);
532 if (rc) {
533 PROTOCOL_ERR("14.4.1.6");
534 goto exit;
535 }
536
537 rc = digital_skb_pull_dep_sod(ddev, resp);
538 if (rc) {
539 PROTOCOL_ERR("14.4.1.2");
540 goto exit;
541 }
542
543 psl_req = (struct digital_psl_req *)resp->data;
544
545 if (resp->len != sizeof(struct digital_psl_req) ||
546 psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
547 psl_req->cmd != DIGITAL_CMD_PSL_REQ) {
548 rc = -EIO;
549 goto exit;
550 }
551
552 dsi = (psl_req->brs >> 3) & 0x07;
553 switch (dsi) {
554 case 0:
555 rf_tech = NFC_DIGITAL_RF_TECH_106A;
556 break;
557 case 1:
558 rf_tech = NFC_DIGITAL_RF_TECH_212F;
559 break;
560 case 2:
561 rf_tech = NFC_DIGITAL_RF_TECH_424F;
562 break;
563 default:
564 PR_ERR("Unsuported dsi value %d", dsi);
565 goto exit;
566 }
567
568 rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
569
570exit:
571 kfree_skb(resp);
572}
573
574static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev,
575 void *arg, struct sk_buff *resp)
576{
577 int offset;
578
579 if (IS_ERR(resp)) {
580 digital_poll_next_tech(ddev);
581 return;
582 }
583
584 offset = 2;
585 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
586 offset++;
587
588 if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
589 digital_tg_recv_psl_req(ddev, arg, resp);
590 else
591 digital_tg_recv_dep_req(ddev, arg, resp);
592}
593
594static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
595 struct digital_atr_req *atr_req)
596{
597 struct digital_atr_res *atr_res;
598 struct sk_buff *skb;
599 u8 *gb;
600 size_t gb_len;
601 int rc;
602
603 gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len);
604 if (!gb)
605 gb_len = 0;
606
607 skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len);
608 if (!skb)
609 return -ENOMEM;
610
611 skb_put(skb, sizeof(struct digital_atr_res));
612 atr_res = (struct digital_atr_res *)skb->data;
613
614 memset(atr_res, 0, sizeof(struct digital_atr_res));
615
616 atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
617 atr_res->cmd = DIGITAL_CMD_ATR_RES;
618 memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
619 atr_res->to = 8;
620 atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
621 if (gb_len) {
622 skb_put(skb, gb_len);
623
624 atr_res->pp |= DIGITAL_GB_BIT;
625 memcpy(atr_res->gb, gb, gb_len);
626 }
627
628 digital_skb_push_dep_sod(ddev, skb);
629
630 ddev->skb_add_crc(skb);
631
632 rc = digital_tg_send_cmd(ddev, skb, 999,
633 digital_tg_send_atr_res_complete, NULL);
634 if (rc) {
635 kfree_skb(skb);
636 return rc;
637 }
638
639 return rc;
640}
641
642void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
643 struct sk_buff *resp)
644{
645 int rc;
646 struct digital_atr_req *atr_req;
647 size_t gb_len, min_size;
648
649 if (IS_ERR(resp)) {
650 rc = PTR_ERR(resp);
651 resp = NULL;
652 goto exit;
653 }
654
655 if (!resp->len) {
656 rc = -EIO;
657 goto exit;
658 }
659
660 if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) {
661 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2;
662
663 ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_106A;
664 ddev->skb_add_crc = digital_skb_add_crc_a;
665 ddev->skb_check_crc = digital_skb_check_crc_a;
666 } else {
667 min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1;
668
669 ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_212F;
670 ddev->skb_add_crc = digital_skb_add_crc_f;
671 ddev->skb_check_crc = digital_skb_check_crc_f;
672 }
673
674 if (resp->len < min_size) {
675 rc = -EIO;
676 goto exit;
677 }
678
679 if (DIGITAL_DRV_CAPS_TG_CRC(ddev)) {
680 ddev->skb_add_crc = digital_skb_add_crc_none;
681 ddev->skb_check_crc = digital_skb_check_crc_none;
682 }
683
684 rc = ddev->skb_check_crc(resp);
685 if (rc) {
686 PROTOCOL_ERR("14.4.1.6");
687 goto exit;
688 }
689
690 rc = digital_skb_pull_dep_sod(ddev, resp);
691 if (rc) {
692 PROTOCOL_ERR("14.4.1.2");
693 goto exit;
694 }
695
696 atr_req = (struct digital_atr_req *)resp->data;
697
698 if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
699 atr_req->cmd != DIGITAL_CMD_ATR_REQ) {
700 rc = -EINVAL;
701 goto exit;
702 }
703
704 rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
705 NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
706 if (rc)
707 goto exit;
708
709 rc = digital_tg_send_atr_res(ddev, atr_req);
710 if (rc)
711 goto exit;
712
713 gb_len = resp->len - sizeof(struct digital_atr_req);
714 rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
715 NFC_COMM_PASSIVE, atr_req->gb, gb_len);
716 if (rc)
717 goto exit;
718
719 ddev->poll_tech_count = 0;
720
721 rc = 0;
722exit:
723 if (rc)
724 digital_poll_next_tech(ddev);
725
726 dev_kfree_skb(resp);
727}