diff options
Diffstat (limited to 'apps/iap/iap-lingo0.c')
-rw-r--r-- | apps/iap/iap-lingo0.c | 263 |
1 files changed, 176 insertions, 87 deletions
diff --git a/apps/iap/iap-lingo0.c b/apps/iap/iap-lingo0.c index e69b42beae..a0c74ce053 100644 --- a/apps/iap/iap-lingo0.c +++ b/apps/iap/iap-lingo0.c | |||
@@ -21,6 +21,10 @@ | |||
21 | #include "iap-lingo.h" | 21 | #include "iap-lingo.h" |
22 | #include "kernel.h" | 22 | #include "kernel.h" |
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "tuner.h" | ||
25 | #if CONFIG_TUNER | ||
26 | #include "ipod_remote_tuner.h" | ||
27 | #endif | ||
24 | 28 | ||
25 | /* | 29 | /* |
26 | * This macro is meant to be used inside an IAP mode message handler. | 30 | * This macro is meant to be used inside an IAP mode message handler. |
@@ -45,10 +49,13 @@ | |||
45 | 49 | ||
46 | static void cmd_ack(const unsigned char cmd, const unsigned char status) | 50 | static void cmd_ack(const unsigned char cmd, const unsigned char status) |
47 | { | 51 | { |
48 | IAP_TX_INIT(0x00, 0x02); | 52 | if (cmd != 0){ |
49 | IAP_TX_PUT(status); | 53 | IAP_TX_INIT(0x00, 0x02); |
50 | IAP_TX_PUT(cmd); | 54 | IAP_TX_PUT(status); |
51 | iap_send_tx(); | 55 | IAP_TX_PUT(cmd); |
56 | |||
57 | iap_send_tx(); | ||
58 | } | ||
52 | } | 59 | } |
53 | 60 | ||
54 | #define cmd_ok(cmd) cmd_ack((cmd), IAP_ACK_OK) | 61 | #define cmd_ok(cmd) cmd_ack((cmd), IAP_ACK_OK) |
@@ -59,6 +66,7 @@ static void cmd_pending(const unsigned char cmd, const uint32_t msdelay) | |||
59 | IAP_TX_PUT(0x06); | 66 | IAP_TX_PUT(0x06); |
60 | IAP_TX_PUT(cmd); | 67 | IAP_TX_PUT(cmd); |
61 | IAP_TX_PUT_U32(msdelay); | 68 | IAP_TX_PUT_U32(msdelay); |
69 | |||
62 | iap_send_tx(); | 70 | iap_send_tx(); |
63 | } | 71 | } |
64 | 72 | ||
@@ -387,7 +395,7 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf) | |||
387 | { | 395 | { |
388 | IAP_TX_INIT(0x00, 0x0E); | 396 | IAP_TX_INIT(0x00, 0x0E); |
389 | IAP_TX_PUT_U32(IAP_IPOD_MODEL); | 397 | IAP_TX_PUT_U32(IAP_IPOD_MODEL); |
390 | IAP_TX_PUT_STRING("ROCKBOX"); | 398 | IAP_TX_PUT_STRING(IAP_IPOD_VARIANT); |
391 | 399 | ||
392 | iap_send_tx(); | 400 | iap_send_tx(); |
393 | break; | 401 | break; |
@@ -476,6 +484,59 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf) | |||
476 | /* Issuing this command exits any extended interface states */ | 484 | /* Issuing this command exits any extended interface states */ |
477 | iap_interface_state_change(IST_STANDARD); | 485 | iap_interface_state_change(IST_STANDARD); |
478 | 486 | ||
487 | /* | ||
488 | * Actions by remote listed Apple Firmware Rockbox Firmware | ||
489 | * Apple remote on Radio pause/play - Mutes Mutes | ||
490 | * vol up/down - Vol Up/Dn Vol Up/Dn | ||
491 | * FF/FR - Station Up/Dn Station Up/Dn | ||
492 | * iPod Pause/Play - Mutes Mutes | ||
493 | * Vol up/down - Vol Up/Dn Vol Up/Dn | ||
494 | * FF/FR - Station Up/Dn Station Up/Dn | ||
495 | * Remote pause/play - Pause/Play Pause/Play | ||
496 | * vol up/down - Vol Up/Dn Vol Up/Dn | ||
497 | * FF/FR - Next/Prev Track Next/Prev Track | ||
498 | * iPod Pause/Play - Pause/Play Pause/Play | ||
499 | * Vol up/down - Vol Up/Dn Vol Up/Dn | ||
500 | * FF/FR - Next/Prev Track Next/Prev Track | ||
501 | * | ||
502 | * The following bytes are returned by the accessories listed | ||
503 | * FF 55 0E 00 13 00 00 00 3D 00 00 00 04 00 00 00 00 9E robi DAB Radio Remote | ||
504 | * FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??) FM Transmitter | ||
505 | * FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 Apple Radio Remote | ||
506 | * | ||
507 | * Bytes 9-12 = Options 11111100 0000 00 00 | ||
508 | * 54321098 7654 32 10 | ||
509 | * 00000004 = 00000000 00000000 00000000 0000 01 00 Bits 2 | ||
510 | * 00000004 = 00000000 00000000 00000000 0000 01 00 Bits 2 | ||
511 | * 0000000E = 00000000 00000000 00000000 0000 01 10 Bits 12 | ||
512 | * | ||
513 | * Bit 0: Authentication 00 = No Authentication | ||
514 | * 01 = Defer Auth until required (V1) | ||
515 | * Bit 1: 10 = Authenticate Immediately (V2) | ||
516 | * 11 = Reserved | ||
517 | * Bit 2: Power Requirements 00 = Low Power Only 10 = Reserved | ||
518 | * Bit 3: 01 = Int High Power 11 = Reserved | ||
519 | * | ||
520 | * Bytes 13-16 = Device ID | ||
521 | * 00000000 | ||
522 | * 00000000 | ||
523 | * 00000003 | ||
524 | * | ||
525 | * Bytes 5-8 = lingoes spoken 11111100 00000000 | ||
526 | * 54321098 76543210 | ||
527 | * 0000003D = 00000000 00000000 00000000 00111101 Bits 2345 | ||
528 | * 00000035 = 00000000 00000000 00000000 00110101 Bits 245 | ||
529 | * 0000008D = 00000000 00000000 00000000 10001101 Bits 237 | ||
530 | * | ||
531 | * | ||
532 | * Bit 0: Must be set by all devices. See above | ||
533 | * Bit 1: Microphone Lingo | ||
534 | * Bit 2: Simple Remote | ||
535 | * Bit 3: Display Remote | ||
536 | * Bit 4: Extended Remote | ||
537 | * Bit 5: RF Transmitter lingo | ||
538 | */ | ||
539 | |||
479 | /* Loop through the lingoes advertised by the device. | 540 | /* Loop through the lingoes advertised by the device. |
480 | * If it tries to use a lingo we do not support, return | 541 | * If it tries to use a lingo we do not support, return |
481 | * a Command Failed ACK. | 542 | * a Command Failed ACK. |
@@ -531,33 +592,49 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf) | |||
531 | 592 | ||
532 | cmd_ok(cmd); | 593 | cmd_ok(cmd); |
533 | 594 | ||
595 | /* Bit 0: Must be set by all devices. See above*/ | ||
596 | /* Bit 1: Microphone Lingo */ | ||
597 | /* Bit 2: Simple Remote */ | ||
598 | /* Bit 3: Display Remote */ | ||
599 | /* Bit 4: Extended Remote */ | ||
534 | /* Bit 5: RF Transmitter lingo */ | 600 | /* Bit 5: RF Transmitter lingo */ |
535 | if (lingoes & (1 << 5)) | 601 | if (lingoes & (1 << 5)) |
536 | { | 602 | { |
537 | /* FM transmitter sends this: */ | 603 | /* FM transmitter sends this: */ |
538 | /* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/ | 604 | /* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/ |
539 | 605 | /* 0x00000035 = 00000000 00000000 00000000 00110101 */ | |
606 | /* 1<<5 1 */ | ||
540 | /* GetAccessoryInfo */ | 607 | /* GetAccessoryInfo */ |
541 | unsigned char data2[] = {0x00, 0x27, 0x00}; | 608 | IAP_TX_INIT(0x00, 0x27); |
542 | iap_send_pkt(data2, sizeof(data2)); | 609 | IAP_TX_PUT(0x00); |
543 | /* RF Transmitter: Begin transmission */ | ||
544 | unsigned char data3[] = {0x05, 0x02}; | ||
545 | iap_send_pkt(data3, sizeof(data3)); | ||
546 | } | ||
547 | 610 | ||
611 | iap_send_tx(); | ||
548 | 612 | ||
549 | #if 0 | 613 | /* RF Transmitter: Begin transmission */ |
614 | IAP_TX_INIT(0x05, 0x02); | ||
615 | |||
616 | iap_send_tx(); | ||
617 | } | ||
618 | /* Bit 6: USB Host Control */ | ||
550 | /* Bit 7: RF Tuner lingo */ | 619 | /* Bit 7: RF Tuner lingo */ |
620 | #if CONFIG_TUNER | ||
551 | if (lingoes & (1 << 7)) | 621 | if (lingoes & (1 << 7)) |
552 | { | 622 | { |
553 | /* ipod fm remote sends this: */ | 623 | /* ipod fm radio remote sends this: */ |
554 | /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 */ | 624 | /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 */ |
625 | /* 0x0000008D = 00000000 00000000 00000000 00011101 */ | ||
626 | /* 1<<7 */ | ||
555 | radio_present = 1; | 627 | radio_present = 1; |
556 | /* GetDevAuthenticationInfo */ | ||
557 | unsigned char data4[] = {0x00, 0x14}; | ||
558 | iap_send_pkt(data4, sizeof(data4)); | ||
559 | } | 628 | } |
560 | #endif | 629 | #endif |
630 | /* Bit 8: Accessory Equalizer Lingo */ | ||
631 | /* Bit 9: Reserved */ | ||
632 | /* Bit 10: Digial Audio Lingo */ | ||
633 | /* Bit 11: Reserved */ | ||
634 | /* Bit 12: Storage Lingo */ | ||
635 | /* Bit 13: Reserved */ | ||
636 | /* .................*/ | ||
637 | /* Bit 31: Reserved */ | ||
561 | break; | 638 | break; |
562 | } | 639 | } |
563 | 640 | ||
@@ -594,7 +671,8 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf) | |||
594 | { | 671 | { |
595 | /* There are two formats of this packet. One with only | 672 | /* There are two formats of this packet. One with only |
596 | * the version information bytes (for Auth version 1.0) | 673 | * the version information bytes (for Auth version 1.0) |
597 | * and the long form shown above | 674 | * and the long form shown above but it must be at least 4 |
675 | * bytes long | ||
598 | */ | 676 | */ |
599 | CHECKLEN(4); | 677 | CHECKLEN(4); |
600 | 678 | ||
@@ -605,25 +683,8 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf) | |||
605 | 683 | ||
606 | device.auth.version = (buf[2] << 8) | buf[3]; | 684 | device.auth.version = (buf[2] << 8) | buf[3]; |
607 | 685 | ||
608 | /* We support authentication versions 1.0 and 2.0 */ | 686 | /* We only support authentication versions 1.0 and 2.0 */ |
609 | if (device.auth.version == 0x100) { | 687 | if ((device.auth.version != 0x100) && (device.auth.version != 0x200)) { |
610 | /* If we could really do authentication we'd have to | ||
611 | * check the certificate here. Since we can't, just acknowledge | ||
612 | * the packet with an "everything OK" AckDevAuthenticationInfo | ||
613 | * | ||
614 | * Skip GetAccessoryInfo process, this command together with | ||
615 | * authentication level 2 were added in iAP release 24, it is | ||
616 | * not be supported by devices authenticating at level 1. | ||
617 | */ | ||
618 | IAP_TX_INIT(0x00, 0x16); | ||
619 | IAP_TX_PUT(0x00); | ||
620 | |||
621 | iap_send_tx(); | ||
622 | device.auth.state = AUST_CERTDONE; | ||
623 | break; | ||
624 | } | ||
625 | |||
626 | if (device.auth.version != 0x200) { | ||
627 | /* Version mismatches are signalled by AckDevAuthenticationInfo | 688 | /* Version mismatches are signalled by AckDevAuthenticationInfo |
628 | * with the status set to Authentication Information unsupported | 689 | * with the status set to Authentication Information unsupported |
629 | */ | 690 | */ |
@@ -635,61 +696,77 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf) | |||
635 | iap_send_tx(); | 696 | iap_send_tx(); |
636 | break; | 697 | break; |
637 | } | 698 | } |
638 | 699 | if (device.auth.version == 0x100) { | |
639 | /* There must be at least one byte of certificate data | 700 | /* If we could really do authentication we'd have to |
640 | * in the packet | 701 | * check the certificate here. Since we can't, just acknowledge |
641 | */ | 702 | * the packet later with an "everything OK" AckDevAuthenticationInfo |
642 | CHECKLEN(7); | 703 | * and change device.auth.state to AuthenticateState_CertificateDone |
643 | |||
644 | switch (device.auth.state) | ||
645 | { | ||
646 | /* This is the first packet. Note the maximum section number | ||
647 | * so we can check it later. | ||
648 | */ | 704 | */ |
649 | case AUST_CERTREQ: | 705 | device.auth.state = AUST_CERTALLRECEIVED; |
706 | } else { | ||
707 | /* Version 2.00 requires at least one byte of certificate data | ||
708 | * in the packet | ||
709 | */ | ||
710 | CHECKLEN(7); | ||
711 | switch (device.auth.state) | ||
650 | { | 712 | { |
651 | device.auth.max_section = buf[5]; | 713 | /* This is the first packet. Note the maximum section number |
652 | device.auth.state = AUST_CERTBEG; | 714 | * so we can check it later. |
715 | */ | ||
716 | case AUST_CERTREQ: | ||
717 | { | ||
718 | device.auth.max_section = buf[5]; | ||
719 | device.auth.state = AUST_CERTBEG; | ||
653 | 720 | ||
654 | /* Intentional fall-through */ | 721 | /* Intentional fall-through */ |
655 | } | 722 | } |
656 | /* All following packets */ | 723 | /* All following packets */ |
657 | case AUST_CERTBEG: | 724 | case AUST_CERTBEG: |
658 | { | 725 | { |
659 | /* Check if this is the expected section */ | 726 | /* Check if this is the expected section */ |
660 | if (buf[4] != device.auth.next_section) { | 727 | if (buf[4] != device.auth.next_section) { |
661 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); | 728 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); |
729 | break; | ||
730 | } | ||
731 | |||
732 | /* Is this the last section? */ | ||
733 | if (device.auth.next_section == device.auth.max_section) { | ||
734 | /* If we could really do authentication we'd have to | ||
735 | * check the certificate here. Since we can't, just acknowledge | ||
736 | * the packet later with an "everything OK" AckDevAuthenticationInfo | ||
737 | * and change device.auth.state to AuthenticateState_CertificateDone | ||
738 | */ | ||
739 | device.auth.state = AUST_CERTALLRECEIVED; | ||
740 | } else { | ||
741 | device.auth.next_section++; | ||
742 | cmd_ok(cmd); | ||
743 | } | ||
662 | break; | 744 | break; |
663 | } | 745 | } |
664 | 746 | default: | |
665 | /* Is this the last section? */ | 747 | { |
666 | if (device.auth.next_section == device.auth.max_section) { | 748 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); |
667 | /* If we could really do authentication we'd have to | 749 | break; |
668 | * check the certificate here. Since we can't, just acknowledge | ||
669 | * the packet with an "everything OK" AckDevAuthenticationInfo | ||
670 | * | ||
671 | * Also, start GetAccessoryInfo process | ||
672 | */ | ||
673 | IAP_TX_INIT(0x00, 0x16); | ||
674 | IAP_TX_PUT(0x00); | ||
675 | |||
676 | iap_send_tx(); | ||
677 | device.auth.state = AUST_CERTDONE; | ||
678 | device.accinfo = ACCST_INIT; | ||
679 | } else { | ||
680 | device.auth.next_section++; | ||
681 | cmd_ok(cmd); | ||
682 | } | 750 | } |
683 | break; | ||
684 | } | ||
685 | |||
686 | default: | ||
687 | { | ||
688 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); | ||
689 | break; | ||
690 | } | 751 | } |
691 | } | 752 | } |
753 | if (device.auth.state == AUST_CERTALLRECEIVED) { | ||
754 | /* We've received all the certificate data so just | ||
755 | *Acknowledge everything OK | ||
756 | */ | ||
757 | IAP_TX_INIT(0x00, 0x16); | ||
758 | IAP_TX_PUT(0x00); | ||
759 | |||
760 | iap_send_tx(); | ||
761 | |||
762 | /* GetAccessoryInfo*/ | ||
763 | IAP_TX_INIT(0x00, 0x27); | ||
764 | IAP_TX_PUT(0x00); | ||
765 | |||
766 | iap_send_tx(); | ||
692 | 767 | ||
768 | device.auth.state = AUST_CERTDONE; | ||
769 | } | ||
693 | break; | 770 | break; |
694 | } | 771 | } |
695 | 772 | ||
@@ -744,6 +821,17 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf) | |||
744 | 821 | ||
745 | iap_send_tx(); | 822 | iap_send_tx(); |
746 | device.auth.state = AUST_AUTH; | 823 | device.auth.state = AUST_AUTH; |
824 | #if CONFIG_TUNER | ||
825 | if (radio_present == 1) | ||
826 | { | ||
827 | /* GetTunerCaps */ | ||
828 | IAP_TX_INIT(0x07, 0x01); | ||
829 | |||
830 | iap_send_tx(); | ||
831 | } | ||
832 | #endif | ||
833 | iap_set_remote_volume(); | ||
834 | |||
747 | break; | 835 | break; |
748 | } | 836 | } |
749 | 837 | ||
@@ -926,7 +1014,9 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf) | |||
926 | CHECKLEN(7); | 1014 | CHECKLEN(7); |
927 | 1015 | ||
928 | device.capabilities = get_u32(&buf[0x03]); | 1016 | device.capabilities = get_u32(&buf[0x03]); |
929 | /* Type 0x00 was already queried, that's where this information comes from */ | 1017 | /* Type 0x00 was already queried, that's where this |
1018 | * information comes from | ||
1019 | */ | ||
930 | device.capabilities_queried = 0x01; | 1020 | device.capabilities_queried = 0x01; |
931 | device.capabilities &= ~0x01; | 1021 | device.capabilities &= ~0x01; |
932 | break; | 1022 | break; |
@@ -1045,9 +1135,8 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf) | |||
1045 | { | 1135 | { |
1046 | #ifdef LOGF_ENABLE | 1136 | #ifdef LOGF_ENABLE |
1047 | logf("iap: Unsupported Mode00 Command"); | 1137 | logf("iap: Unsupported Mode00 Command"); |
1048 | #else | ||
1049 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); | ||
1050 | #endif | 1138 | #endif |
1139 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); | ||
1051 | break; | 1140 | break; |
1052 | } | 1141 | } |
1053 | } | 1142 | } |