diff options
author | LiveboxAndy <liveboxandy@gmail.com> | 2018-08-04 18:02:21 +0100 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2020-07-09 18:02:07 +0000 |
commit | 77f8c9c9f12f1a520467868047574fe0af7a1556 (patch) | |
tree | 2ae699fbdeca5aed4e28a1d5bc69915d5f6f5838 /apps/iap/iap-lingo0.c | |
parent | dcdf2713f610cb3cfaa615ab9b8d4b9412e7a8b6 (diff) | |
download | rockbox-77f8c9c9f12f1a520467868047574fe0af7a1556.tar.gz rockbox-77f8c9c9f12f1a520467868047574fe0af7a1556.zip |
Update to allow the Apple Radio Remote to function on iPod Video 5G.
This was broken when the major update to iap was comitted.
ia-lingo7.c created and various iap related files modified.
On 4G, 6G and Nano 1/2Gen iPods the remote will function
even though the radio won't.
Tested on 4G Greyscale, 4G Color, 4G Photo, 4G Mini 1st Gen,
4G Mini 2Gen, Nano 1G, Nano 2G, Video 5G, Video 5.5G
Change-Id: Ia74e3d07d9ab5edc6da8eafa96801ede722be331
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 | } |