summaryrefslogtreecommitdiff
path: root/apps/iap/iap-lingo0.c
diff options
context:
space:
mode:
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 }