summaryrefslogtreecommitdiff
path: root/apps/iap/iap-lingo0.c
diff options
context:
space:
mode:
authorLiveboxAndy <liveboxandy@gmail.com>2018-08-04 18:02:21 +0100
committerSolomon Peachy <pizza@shaftnet.org>2020-07-09 18:02:07 +0000
commit77f8c9c9f12f1a520467868047574fe0af7a1556 (patch)
tree2ae699fbdeca5aed4e28a1d5bc69915d5f6f5838 /apps/iap/iap-lingo0.c
parentdcdf2713f610cb3cfaa615ab9b8d4b9412e7a8b6 (diff)
downloadrockbox-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.c263
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
46static void cmd_ack(const unsigned char cmd, const unsigned char status) 50static 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 }