summaryrefslogtreecommitdiffstats
path: root/apps/iap
diff options
context:
space:
mode:
Diffstat (limited to 'apps/iap')
-rw-r--r--apps/iap/iap-core.c115
-rw-r--r--apps/iap/iap-core.h19
-rw-r--r--apps/iap/iap-lingo.h3
-rw-r--r--apps/iap/iap-lingo0.c263
-rw-r--r--apps/iap/iap-lingo1.c1
-rw-r--r--apps/iap/iap-lingo2.c34
-rw-r--r--apps/iap/iap-lingo3.c75
-rw-r--r--apps/iap/iap-lingo4.c11
-rw-r--r--apps/iap/iap-lingo7.c491
9 files changed, 834 insertions, 178 deletions
diff --git a/apps/iap/iap-core.c b/apps/iap/iap-core.c
index f8373bab83..885ba2c188 100644
--- a/apps/iap/iap-core.c
+++ b/apps/iap/iap-core.c
@@ -45,7 +45,9 @@
#include "usb.h"
#include "tuner.h"
+#if CONFIG_TUNER
#include "ipod_remote_tuner.h"
+#endif
/* MS_TO_TICKS converts a milisecond time period into the
@@ -164,7 +166,13 @@ unsigned char lingo_versions[32][2] = {
{1, 5}, /* Display remote lingo, 0x03 */
{1, 12}, /* Extended Interface lingo, 0x04 */
{1, 1}, /* RF/BT Transmitter lingo, 0x05 */
- {} /* All others are unsupported */
+ {0, 0}, /* USB Host lingo, 0x06, disabled */
+#if CONFIG_TUNER
+ {1, 0}, /* RF Receiver lingo, 0x07 */
+#else
+ {0, 0}, /* RF Receiver lingo, 0x07 disabled */
+#endif
+ {} /* every other lingo, disabled */
};
/* states of the iap de-framing state machine */
@@ -308,6 +316,17 @@ static int iap_task(struct timeout *tmo)
return MS_TO_TICKS(100);
}
+
+void iap_set_remote_volume(void)
+{
+ IAP_TX_INIT(0x03, 0x0D);
+ IAP_TX_PUT(0x04);
+ IAP_TX_PUT(0x00);
+ IAP_TX_PUT(0xFF & (int)((global_settings.volume + 90) * 2.65625));
+ iap_send_tx();
+}
+
+
/* This thread is waiting for events posted to iap_queue and calls
* the appropriate subroutines in response
*/
@@ -859,11 +878,15 @@ void iap_periodic(void)
/* Volume change notifications are sent every 100ms */
if (device.notifications & (BIT_N(4) | BIT_N(16))) {
- /* Currently we do not track volume changes, so this is
- * never sent.
+ /* Currently we do not track volume changes for BIT_N(16),
*
- * TODO: Fix volume tracking
*/
+ IAP_TX_INIT(0x03, 0x09);
+ IAP_TX_PUT(0x04);
+ IAP_TX_PUT(0x00);
+ IAP_TX_PUT(0xFF &(int)((global_settings.volume + 90) * 2.65625));
+ device.changed_notifications |= BIT_N(4);
+ iap_send_tx();
}
/* All other events are sent every 500ms */
@@ -972,9 +995,15 @@ void iap_periodic(void)
unsigned char play_status;
play_status = audio_status();
-
if (device.play_status != play_status)
{
+ /* If play_status = PAUSE/STOP we should mute else
+ * we should unmute
+ * 0 = Stopped
+ * 1 = Playing
+ * 2 = Pause
+ * 3 = Play/Pause
+ */
IAP_TX_INIT(0x03, 0x09);
IAP_TX_PUT(0x03);
if (play_status & AUDIO_STATUS_PLAY) {
@@ -994,6 +1023,23 @@ void iap_periodic(void)
iap_send_tx();
device.play_status = play_status;
+ if (play_status != 1) {
+ /* Not Playing */
+ audio_pause();
+#if CONFIG_TUNER
+ if (radio_present==1) {
+ tuner_set(RADIO_MUTE,1);
+ }
+#endif
+ } else {
+ /* Playing */
+ audio_resume();
+#if CONFIG_TUNER
+ if (radio_present==1) {
+ tuner_set(RADIO_MUTE,0);
+ }
+#endif
+ }
}
}
@@ -1212,43 +1258,6 @@ static void iap_handlepkt_mode5(const unsigned int len, const unsigned char *buf
}
}
-#if 0
-static void iap_handlepkt_mode7(const unsigned int len, const unsigned char *buf)
-{
- unsigned int cmd = buf[1];
- switch (cmd)
- {
- /* RetTunerCaps */
- case 0x02:
- {
- /* do nothing */
-
- /* GetAccessoryInfo */
- unsigned char data[] = {0x00, 0x27, 0x00};
- iap_send_pkt(data, sizeof(data));
- break;
- }
-
- /* RetTunerFreq */
- case 0x0A:
- /* fall through */
- /* TunerSeekDone */
- case 0x13:
- {
- rmt_tuner_freq(len, buf);
- break;
- }
-
- /* RdsReadyNotify, RDS station name 0x21 1E 00 + ASCII text*/
- case 0x21:
- {
- rmt_tuner_rds_data(len, buf);
- break;
- }
- }
-}
-#endif
-
void iap_handlepkt(void)
{
int level;
@@ -1271,17 +1280,21 @@ void iap_handlepkt(void)
logf("R: %s", hexstring(iap_rxstart+2, (length)));
#endif
- unsigned char mode = *(iap_rxstart+2);
- switch (mode) {
- case 0: iap_handlepkt_mode0(length, iap_rxstart+2); break;
+ if (length != 0) {
+ unsigned char mode = *(iap_rxstart+2);
+ switch (mode) {
+ case 0: iap_handlepkt_mode0(length, iap_rxstart+2); break;
#ifdef HAVE_LINE_REC
- case 1: iap_handlepkt_mode1(length, iap_rxstart+2); break;
+ case 1: iap_handlepkt_mode1(length, iap_rxstart+2); break;
#endif
- case 2: iap_handlepkt_mode2(length, iap_rxstart+2); break;
- case 3: iap_handlepkt_mode3(length, iap_rxstart+2); break;
- case 4: iap_handlepkt_mode4(length, iap_rxstart+2); break;
- case 5: iap_handlepkt_mode5(length, iap_rxstart+2); break;
- /* case 7: iap_handlepkt_mode7(length, iap_rxstart+2); break; */
+ case 2: iap_handlepkt_mode2(length, iap_rxstart+2); break;
+ case 3: iap_handlepkt_mode3(length, iap_rxstart+2); break;
+ case 4: iap_handlepkt_mode4(length, iap_rxstart+2); break;
+ case 5: iap_handlepkt_mode5(length, iap_rxstart+2); break;
+#if CONFIG_TUNER
+ case 7: iap_handlepkt_mode7(length, iap_rxstart+2); break;
+#endif
+ }
}
/* Remove the handled packet from the RX buffer
diff --git a/apps/iap/iap-core.h b/apps/iap/iap-core.h
index 61b72d4ca2..b558e1cc0f 100644
--- a/apps/iap/iap-core.h
+++ b/apps/iap/iap-core.h
@@ -34,6 +34,7 @@
/* The Model ID of the iPod we emulate. Currently a 160GB classic */
#define IAP_IPOD_MODEL (0x00130200U)
+#define IAP_IPOD_VARIANT "MC293"
/* The firmware version we emulate. Currently 2.0.3 */
#define IAP_IPOD_FIRMWARE_MAJOR (2)
@@ -73,14 +74,15 @@ enum interface_state {
/* States of the authentication state machine */
enum authen_state {
- AUST_NONE, /* Initial state, no message sent */
- AUST_INIT, /* Remote side has requested authentication */
- AUST_CERTREQ, /* Remote certificate requested */
- AUST_CERTBEG, /* Certificate is being received */
- AUST_CERTDONE, /* Certificate received */
- AUST_CHASENT, /* Challenge sent */
- AUST_CHADONE, /* Challenge response received */
- AUST_AUTH, /* Authentication complete */
+ AUST_NONE, /* Initial state, no message sent */
+ AUST_INIT, /* Remote side has requested authentication */
+ AUST_CERTREQ, /* Remote certificate requested */
+ AUST_CERTBEG, /* Certificate is being received */
+ AUST_CERTALLRECEIVED, /* Certificate all Received */
+ AUST_CERTDONE, /* Certificate all Done */
+ AUST_CHASENT, /* Challenge sent */
+ AUST_CHADONE, /* Challenge response received */
+ AUST_AUTH, /* Authentication complete */
};
/* State of authentication */
@@ -237,6 +239,7 @@ void iap_repeat_next(void);
void iap_fill_power_state(void);
void iap_send_tx(void);
+void iap_set_remote_volume(void);
extern enum interface_state interface_state;
void iap_interface_state_change(const enum interface_state new);
diff --git a/apps/iap/iap-lingo.h b/apps/iap/iap-lingo.h
index 888490c26a..982a62173f 100644
--- a/apps/iap/iap-lingo.h
+++ b/apps/iap/iap-lingo.h
@@ -24,3 +24,6 @@ void iap_handlepkt_mode1(const unsigned int len, const unsigned char *buf);
void iap_handlepkt_mode2(const unsigned int len, const unsigned char *buf);
void iap_handlepkt_mode3(const unsigned int len, const unsigned char *buf);
void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf);
+#if CONFIG_TUNER
+void iap_handlepkt_mode7(const unsigned int len, const unsigned char *buf);
+#endif
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 @@
#include "iap-lingo.h"
#include "kernel.h"
#include "system.h"
+#include "tuner.h"
+#if CONFIG_TUNER
+#include "ipod_remote_tuner.h"
+#endif
/*
* This macro is meant to be used inside an IAP mode message handler.
@@ -45,10 +49,13 @@
static void cmd_ack(const unsigned char cmd, const unsigned char status)
{
- IAP_TX_INIT(0x00, 0x02);
- IAP_TX_PUT(status);
- IAP_TX_PUT(cmd);
- iap_send_tx();
+ if (cmd != 0){
+ IAP_TX_INIT(0x00, 0x02);
+ IAP_TX_PUT(status);
+ IAP_TX_PUT(cmd);
+
+ iap_send_tx();
+ }
}
#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)
IAP_TX_PUT(0x06);
IAP_TX_PUT(cmd);
IAP_TX_PUT_U32(msdelay);
+
iap_send_tx();
}
@@ -387,7 +395,7 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
{
IAP_TX_INIT(0x00, 0x0E);
IAP_TX_PUT_U32(IAP_IPOD_MODEL);
- IAP_TX_PUT_STRING("ROCKBOX");
+ IAP_TX_PUT_STRING(IAP_IPOD_VARIANT);
iap_send_tx();
break;
@@ -476,6 +484,59 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
/* Issuing this command exits any extended interface states */
iap_interface_state_change(IST_STANDARD);
+ /*
+ * Actions by remote listed Apple Firmware Rockbox Firmware
+ * Apple remote on Radio pause/play - Mutes Mutes
+ * vol up/down - Vol Up/Dn Vol Up/Dn
+ * FF/FR - Station Up/Dn Station Up/Dn
+ * iPod Pause/Play - Mutes Mutes
+ * Vol up/down - Vol Up/Dn Vol Up/Dn
+ * FF/FR - Station Up/Dn Station Up/Dn
+ * Remote pause/play - Pause/Play Pause/Play
+ * vol up/down - Vol Up/Dn Vol Up/Dn
+ * FF/FR - Next/Prev Track Next/Prev Track
+ * iPod Pause/Play - Pause/Play Pause/Play
+ * Vol up/down - Vol Up/Dn Vol Up/Dn
+ * FF/FR - Next/Prev Track Next/Prev Track
+ *
+ * The following bytes are returned by the accessories listed
+ * FF 55 0E 00 13 00 00 00 3D 00 00 00 04 00 00 00 00 9E robi DAB Radio Remote
+ * FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??) FM Transmitter
+ * FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 Apple Radio Remote
+ *
+ * Bytes 9-12 = Options 11111100 0000 00 00
+ * 54321098 7654 32 10
+ * 00000004 = 00000000 00000000 00000000 0000 01 00 Bits 2
+ * 00000004 = 00000000 00000000 00000000 0000 01 00 Bits 2
+ * 0000000E = 00000000 00000000 00000000 0000 01 10 Bits 12
+ *
+ * Bit 0: Authentication 00 = No Authentication
+ * 01 = Defer Auth until required (V1)
+ * Bit 1: 10 = Authenticate Immediately (V2)
+ * 11 = Reserved
+ * Bit 2: Power Requirements 00 = Low Power Only 10 = Reserved
+ * Bit 3: 01 = Int High Power 11 = Reserved
+ *
+ * Bytes 13-16 = Device ID
+ * 00000000
+ * 00000000
+ * 00000003
+ *
+ * Bytes 5-8 = lingoes spoken 11111100 00000000
+ * 54321098 76543210
+ * 0000003D = 00000000 00000000 00000000 00111101 Bits 2345
+ * 00000035 = 00000000 00000000 00000000 00110101 Bits 245
+ * 0000008D = 00000000 00000000 00000000 10001101 Bits 237
+ *
+ *
+ * Bit 0: Must be set by all devices. See above
+ * Bit 1: Microphone Lingo
+ * Bit 2: Simple Remote
+ * Bit 3: Display Remote
+ * Bit 4: Extended Remote
+ * Bit 5: RF Transmitter lingo
+ */
+
/* Loop through the lingoes advertised by the device.
* If it tries to use a lingo we do not support, return
* a Command Failed ACK.
@@ -531,33 +592,49 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
cmd_ok(cmd);
+ /* Bit 0: Must be set by all devices. See above*/
+ /* Bit 1: Microphone Lingo */
+ /* Bit 2: Simple Remote */
+ /* Bit 3: Display Remote */
+ /* Bit 4: Extended Remote */
/* Bit 5: RF Transmitter lingo */
if (lingoes & (1 << 5))
{
/* FM transmitter sends this: */
/* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/
-
+ /* 0x00000035 = 00000000 00000000 00000000 00110101 */
+ /* 1<<5 1 */
/* GetAccessoryInfo */
- unsigned char data2[] = {0x00, 0x27, 0x00};
- iap_send_pkt(data2, sizeof(data2));
- /* RF Transmitter: Begin transmission */
- unsigned char data3[] = {0x05, 0x02};
- iap_send_pkt(data3, sizeof(data3));
- }
+ IAP_TX_INIT(0x00, 0x27);
+ IAP_TX_PUT(0x00);
+ iap_send_tx();
-#if 0
+ /* RF Transmitter: Begin transmission */
+ IAP_TX_INIT(0x05, 0x02);
+
+ iap_send_tx();
+ }
+ /* Bit 6: USB Host Control */
/* Bit 7: RF Tuner lingo */
+#if CONFIG_TUNER
if (lingoes & (1 << 7))
{
- /* ipod fm remote sends this: */
- /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 */
+ /* ipod fm radio remote sends this: */
+ /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 */
+ /* 0x0000008D = 00000000 00000000 00000000 00011101 */
+ /* 1<<7 */
radio_present = 1;
- /* GetDevAuthenticationInfo */
- unsigned char data4[] = {0x00, 0x14};
- iap_send_pkt(data4, sizeof(data4));
}
#endif
+ /* Bit 8: Accessory Equalizer Lingo */
+ /* Bit 9: Reserved */
+ /* Bit 10: Digial Audio Lingo */
+ /* Bit 11: Reserved */
+ /* Bit 12: Storage Lingo */
+ /* Bit 13: Reserved */
+ /* .................*/
+ /* Bit 31: Reserved */
break;
}
@@ -594,7 +671,8 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
{
/* There are two formats of this packet. One with only
* the version information bytes (for Auth version 1.0)
- * and the long form shown above
+ * and the long form shown above but it must be at least 4
+ * bytes long
*/
CHECKLEN(4);
@@ -605,25 +683,8 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
device.auth.version = (buf[2] << 8) | buf[3];
- /* We support authentication versions 1.0 and 2.0 */
- if (device.auth.version == 0x100) {
- /* If we could really do authentication we'd have to
- * check the certificate here. Since we can't, just acknowledge
- * the packet with an "everything OK" AckDevAuthenticationInfo
- *
- * Skip GetAccessoryInfo process, this command together with
- * authentication level 2 were added in iAP release 24, it is
- * not be supported by devices authenticating at level 1.
- */
- IAP_TX_INIT(0x00, 0x16);
- IAP_TX_PUT(0x00);
-
- iap_send_tx();
- device.auth.state = AUST_CERTDONE;
- break;
- }
-
- if (device.auth.version != 0x200) {
+ /* We only support authentication versions 1.0 and 2.0 */
+ if ((device.auth.version != 0x100) && (device.auth.version != 0x200)) {
/* Version mismatches are signalled by AckDevAuthenticationInfo
* with the status set to Authentication Information unsupported
*/
@@ -635,61 +696,77 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
iap_send_tx();
break;
}
-
- /* There must be at least one byte of certificate data
- * in the packet
- */
- CHECKLEN(7);
-
- switch (device.auth.state)
- {
- /* This is the first packet. Note the maximum section number
- * so we can check it later.
+ if (device.auth.version == 0x100) {
+ /* If we could really do authentication we'd have to
+ * check the certificate here. Since we can't, just acknowledge
+ * the packet later with an "everything OK" AckDevAuthenticationInfo
+ * and change device.auth.state to AuthenticateState_CertificateDone
*/
- case AUST_CERTREQ:
+ device.auth.state = AUST_CERTALLRECEIVED;
+ } else {
+ /* Version 2.00 requires at least one byte of certificate data
+ * in the packet
+ */
+ CHECKLEN(7);
+ switch (device.auth.state)
{
- device.auth.max_section = buf[5];
- device.auth.state = AUST_CERTBEG;
+ /* This is the first packet. Note the maximum section number
+ * so we can check it later.
+ */
+ case AUST_CERTREQ:
+ {
+ device.auth.max_section = buf[5];
+ device.auth.state = AUST_CERTBEG;
- /* Intentional fall-through */
- }
- /* All following packets */
- case AUST_CERTBEG:
- {
- /* Check if this is the expected section */
- if (buf[4] != device.auth.next_section) {
- cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ /* Intentional fall-through */
+ }
+ /* All following packets */
+ case AUST_CERTBEG:
+ {
+ /* Check if this is the expected section */
+ if (buf[4] != device.auth.next_section) {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+
+ /* Is this the last section? */
+ if (device.auth.next_section == device.auth.max_section) {
+ /* If we could really do authentication we'd have to
+ * check the certificate here. Since we can't, just acknowledge
+ * the packet later with an "everything OK" AckDevAuthenticationInfo
+ * and change device.auth.state to AuthenticateState_CertificateDone
+ */
+ device.auth.state = AUST_CERTALLRECEIVED;
+ } else {
+ device.auth.next_section++;
+ cmd_ok(cmd);
+ }
break;
}
-
- /* Is this the last section? */
- if (device.auth.next_section == device.auth.max_section) {
- /* If we could really do authentication we'd have to
- * check the certificate here. Since we can't, just acknowledge
- * the packet with an "everything OK" AckDevAuthenticationInfo
- *
- * Also, start GetAccessoryInfo process
- */
- IAP_TX_INIT(0x00, 0x16);
- IAP_TX_PUT(0x00);
-
- iap_send_tx();
- device.auth.state = AUST_CERTDONE;
- device.accinfo = ACCST_INIT;
- } else {
- device.auth.next_section++;
- cmd_ok(cmd);
+ default:
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
}
- break;
- }
-
- default:
- {
- cmd_ack(cmd, IAP_ACK_BAD_PARAM);
- break;
}
}
+ if (device.auth.state == AUST_CERTALLRECEIVED) {
+ /* We've received all the certificate data so just
+ *Acknowledge everything OK
+ */
+ IAP_TX_INIT(0x00, 0x16);
+ IAP_TX_PUT(0x00);
+
+ iap_send_tx();
+
+ /* GetAccessoryInfo*/
+ IAP_TX_INIT(0x00, 0x27);
+ IAP_TX_PUT(0x00);
+
+ iap_send_tx();
+ device.auth.state = AUST_CERTDONE;
+ }
break;
}
@@ -744,6 +821,17 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
iap_send_tx();
device.auth.state = AUST_AUTH;
+#if CONFIG_TUNER
+ if (radio_present == 1)
+ {
+ /* GetTunerCaps */
+ IAP_TX_INIT(0x07, 0x01);
+
+ iap_send_tx();
+ }
+#endif
+ iap_set_remote_volume();
+
break;
}
@@ -926,7 +1014,9 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
CHECKLEN(7);
device.capabilities = get_u32(&buf[0x03]);
- /* Type 0x00 was already queried, that's where this information comes from */
+ /* Type 0x00 was already queried, that's where this
+ * information comes from
+ */
device.capabilities_queried = 0x01;
device.capabilities &= ~0x01;
break;
@@ -1045,9 +1135,8 @@ void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
{
#ifdef LOGF_ENABLE
logf("iap: Unsupported Mode00 Command");
-#else
- cmd_ack(cmd, IAP_ACK_BAD_PARAM);
#endif
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
break;
}
}
diff --git a/apps/iap/iap-lingo1.c b/apps/iap/iap-lingo1.c
index 5702500f23..56c52d81ae 100644
--- a/apps/iap/iap-lingo1.c
+++ b/apps/iap/iap-lingo1.c
@@ -212,6 +212,7 @@ void iap_handlepkt_mode1(const unsigned int len, const unsigned char *buf)
#ifdef LOGF_ENABLE
logf("iap: Unsupported Mode1 Command");
#endif
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
break;
}
}
diff --git a/apps/iap/iap-lingo2.c b/apps/iap/iap-lingo2.c
index d4c2f18c2f..946e51222d 100644
--- a/apps/iap/iap-lingo2.c
+++ b/apps/iap/iap-lingo2.c
@@ -30,6 +30,10 @@
#include "button.h"
#include "audio.h"
#include "settings.h"
+#include "tuner.h"
+#if CONFIG_TUNER
+#include "ipod_remote_tuner.h"
+#endif
/*
* This macro is meant to be used inside an IAP mode message handler.
@@ -57,6 +61,9 @@ static void cmd_ack(const unsigned char cmd, const unsigned char status)
void iap_handlepkt_mode2(const unsigned int len, const unsigned char *buf)
{
static bool poweron_pressed = false;
+#if CONFIG_TUNER
+ static bool remote_mute = false;
+#endif
unsigned int cmd = buf[1];
/* We expect at least three bytes in the buffer, one for the
@@ -95,7 +102,21 @@ void iap_handlepkt_mode2(const unsigned int len, const unsigned char *buf)
if(buf[2] != 0)
{
if(buf[2] & 1)
+ {
REMOTE_BUTTON(BUTTON_RC_PLAY);
+#if CONFIG_TUNER
+ if (radio_present == 1) {
+ if (remote_mute == 0) {
+ /* Not Muted so radio on*/
+ tuner_set(RADIO_MUTE,0);
+ } else {
+ /* Muted so radio off*/
+ tuner_set(RADIO_MUTE,1);
+ }
+ remote_mute = !remote_mute;
+ }
+#endif
+ }
if(buf[2] & 2)
REMOTE_BUTTON(BUTTON_RC_VOL_UP);
if(buf[2] & 4)
@@ -111,11 +132,21 @@ void iap_handlepkt_mode2(const unsigned int len, const unsigned char *buf)
{
if (audio_status() != AUDIO_STATUS_PLAY)
REMOTE_BUTTON(BUTTON_RC_PLAY);
+#if CONFIG_TUNER
+ if (radio_present == 1) {
+ tuner_set(RADIO_MUTE,0);
+ }
+#endif
}
if(buf[3] & 2) /* pause */
{
if (audio_status() == AUDIO_STATUS_PLAY)
REMOTE_BUTTON(BUTTON_RC_PLAY);
+#if CONFIG_TUNER
+ if (radio_present == 1) {
+ tuner_set(RADIO_MUTE,1);
+ }
+#endif
}
if(buf[3] & 128) /* Shuffle */
{
@@ -295,9 +326,8 @@ void iap_handlepkt_mode2(const unsigned int len, const unsigned char *buf)
{
#ifdef LOGF_ENABLE
logf("iap: Unsupported Mode02 Command");
-#else
- cmd_ack(cmd, IAP_ACK_BAD_PARAM);
#endif
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
break;
}
}
diff --git a/apps/iap/iap-lingo3.c b/apps/iap/iap-lingo3.c
index 0ed3df118e..c7801fbce0 100644
--- a/apps/iap/iap-lingo3.c
+++ b/apps/iap/iap-lingo3.c
@@ -38,6 +38,9 @@
#include "settings.h"
#include "metadata.h"
#include "playback.h"
+#if CONFIG_TUNER
+#include "ipod_remote_tuner.h"
+#endif
/*
* This macro is meant to be used inside an IAP mode message handler.
@@ -262,7 +265,7 @@ void iap_handlepkt_mode3(const unsigned int len, const unsigned char *buf)
device.play_status = audio_status();
/* TODO: Fix this */
device.mute = false;
- device.volume = 0x80;
+ device.volume = global_settings.volume;
device.power_state = charger_input_state;
device.battery_level = battery_level();
/* TODO: Fix this */
@@ -299,8 +302,8 @@ void iap_handlepkt_mode3(const unsigned int len, const unsigned char *buf)
/* GetRemoteEventStatus (0x0A)
*
- * Request the events changed since the last call to GetREmoteEventStatus
- * or SetRemoteEventNotification
+ * Request the events changed since the last call to
+ * GetREmoteEventStatus or SetRemoteEventNotification
*
* Packet format (offset in buf[]: Description)
* 0x00: Lingo ID: Display Remote Lingo, always 0x03
@@ -434,15 +437,18 @@ void iap_handlepkt_mode3(const unsigned int len, const unsigned char *buf)
*/
case 0x04:
{
- /* Figuring out what the current volume is
- * seems to be tricky.
- * TODO: Fix.
- */
+ if (device.mute == false) {
+ /* Mute status False*/
+ IAP_TX_PUT(0x00);
+ /* Volume */
+ IAP_TX_PUT(0xFF & (int)((global_settings.volume + 90) * 2.65625));
- /* Mute status */
- IAP_TX_PUT(0x00);
- /* Volume */
- IAP_TX_PUT(0x80);
+ } else {
+ /* Mute status True*/
+ IAP_TX_PUT(0x01);
+ /* Volume should be 0 if muted */
+ IAP_TX_PUT(0x00);
+ }
iap_send_tx();
break;
@@ -620,15 +626,24 @@ void iap_handlepkt_mode3(const unsigned int len, const unsigned char *buf)
*/
case 0x10:
{
- /* TODO: See volume above */
- IAP_TX_PUT(0x00);
- IAP_TX_PUT(0x80);
- IAP_TX_PUT(0x80);
+ if (device.mute == false) {
+ /* Mute status False*/
+ IAP_TX_PUT(0x00);
+ /* Volume */
+ IAP_TX_PUT(0xFF & (int)((global_settings.volume + 90) * 2.65625));
+ IAP_TX_PUT(0xFF & (int)((global_settings.volume + 90) * 2.65625));
+
+ } else {
+ /* Mute status True*/
+ IAP_TX_PUT(0x01);
+ /* Volume should be 0 if muted */
+ IAP_TX_PUT(0x00);
+ IAP_TX_PUT(0x00);
+ }
iap_send_tx();
break;
}
-
default:
{
cmd_ack(cmd, IAP_ACK_BAD_PARAM);
@@ -746,14 +761,18 @@ void iap_handlepkt_mode3(const unsigned int len, const unsigned char *buf)
break;
}
- /* Volume/Mute
- * Data length: 2
- * TODO: Fix this
- */
case 0x04:
{
CHECKLEN(5);
- cmd_ack(cmd, IAP_ACK_CMD_FAILED);
+ if (buf[0x03]==0x00){
+ /* Not Muted */
+ global_settings.volume = (int) (buf[0x04]/2.65625)-90;
+ device.mute = false;
+ }
+ else {
+ device.mute = true;
+ }
+ cmd_ok(cmd);
break;
}
@@ -919,7 +938,16 @@ void iap_handlepkt_mode3(const unsigned int len, const unsigned char *buf)
case 0x10:
{
CHECKLEN(7);
- cmd_ack(cmd, IAP_ACK_CMD_FAILED);
+ if (buf[0x03]==0x00){
+ /* Not Muted */
+ global_settings.volume = (int) (buf[0x04]/2.65625)-90;
+ device.mute = false;
+ }
+ else {
+ device.mute = true;
+ }
+
+ cmd_ok(cmd);
break;
}
@@ -1499,9 +1527,8 @@ void iap_handlepkt_mode3(const unsigned int len, const unsigned char *buf)
{
#ifdef LOGF_ENABLE
logf("iap: Unsupported Mode03 Command");
-#else
- cmd_ack(cmd, IAP_ACK_BAD_PARAM);
#endif
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
break;
}
}
diff --git a/apps/iap/iap-lingo4.c b/apps/iap/iap-lingo4.c
index 903cef9378..b601501b3d 100644
--- a/apps/iap/iap-lingo4.c
+++ b/apps/iap/iap-lingo4.c
@@ -109,9 +109,8 @@ static void seek_to_playlist(unsigned long index)
ft_play_playlist(selected_playlist,
global_settings.playlist_catalog_dir,
strrchr(selected_playlist, '/') + 1);
-
}
-
+
static unsigned long nbr_total_playlists(void)
{
DIR* dp;
@@ -161,7 +160,7 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf)
switch (cmd)
{
case 0x0001: /* CmdAck. See above cmd_ack() */
- /*
+ /*
* The following is the description for the Apple Firmware
* The iPod sends this telegram to acknowledge the receipt of a
* command and return the command status. The command ID field
@@ -1457,7 +1456,7 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf)
case 0x05: /* Tracks */
case 0x02: /* Artists */
case 0x03: /* Albums */
- case 0x04: /* Genre */
+ case 0x04: /* Genre */
case 0x06: /* Composer */
playlist_get_track_info(NULL, start_index + counter,
&track);
@@ -2019,8 +2018,8 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf)
playlist_randomise(NULL, current_tick, true);
}
else
- {
- playlist_sort(NULL, true);
+ {
+ playlist_sort(NULL, true);
}
audio_skip(index - playlist_next(0));
if (!paused)
diff --git a/apps/iap/iap-lingo7.c b/apps/iap/iap-lingo7.c
new file mode 100644
index 0000000000..467a81cc76
--- /dev/null
+++ b/apps/iap/iap-lingo7.c
@@ -0,0 +1,491 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Alan Korr & Nick Robinson
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "iap-core.h"
+#include "iap-lingo.h"
+#include "kernel.h"
+#include "system.h"
+#include "tuner.h"
+#if CONFIG_TUNER
+#include "ipod_remote_tuner.h"
+#endif
+
+/*
+ * This macro is meant to be used inside an IAP mode message handler.
+ * It is passed the expected minimum length of the message inbufferfer.
+ * If the inbufferfer does not have the required lenght an ACK
+ * packet with a Bad Parameter error is generated.
+ */
+#define CHECKLEN(x) do { \
+ if (len < (x)) { \
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM); \
+ return; \
+ }} while(0)
+
+/* Check for authenticated state, and return an ACK Not
+ * Authenticated on failure.
+ */
+#define CHECKAUTH do { \
+ if (!DEVICE_AUTHENTICATED) { \
+ cmd_ack(cmd, IAP_ACK_NO_AUTHEN); \
+ return; \
+ }} while(0)
+
+
+static void cmd_ack(const unsigned char cmd, const unsigned char status)
+{
+ IAP_TX_INIT(0x07, 0x00);
+ IAP_TX_PUT(status);
+ IAP_TX_PUT(cmd);
+
+ iap_send_tx();
+}
+
+#define cmd_ok(cmd) cmd_ack((cmd), IAP_ACK_OK)
+
+void iap_handlepkt_mode7(const unsigned int len, const unsigned char *inbuffer)
+{
+ /* Note that some of the Lingo Mode 7 commands are handled by
+ * ../firmware/drivers/tuner/ipod_remote_tuner.c as some of the
+ * commands are sourced with the remote as the master with the ipod acting
+ * as the slave.
+ */
+ unsigned char cmd = inbuffer[1];
+ unsigned char statusnotifymaskbyte = 0;
+
+ /* We expect at least two bytes in the inbuffer, one for the
+ * lingo and one for the command
+ */
+ CHECKLEN(2);
+
+ /* Lingo 0x07 must have been negotiated */
+ if (!DEVICE_LINGO_SUPPORTED(0x07)) {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ return;
+ }
+
+ switch (cmd)
+ {
+ /* case 00 ToIpod Ack 2/6 bytes*/
+ case 0x00:
+ {
+ /* 0x00 OK
+ * 0x01 Unknown Track Category
+ * 0x02 Command Failed. Command is valid but did not succeed
+ * 0x03 Out Of Resources
+ * 0x04 Bad Parameter
+ * 0x05 Unknown Track ID
+ * 0x06 Command Pending.
+ * 0x07 Not Authenticated
+ *
+ * byte 1 is ID of command being acknowledged
+ * bytes 2-5 only if status byte is pending. timeout in ms.
+ */
+ break;
+ }
+
+ /* case 0x01 ToAccessory GetTunerCaps
+ * This is sent by iap-lingo0.c through case 0x15 after device
+ * has been authenticated FF55020701F6
+ */
+
+ /* case 02 ToIpod RetTunerCaps 8 bytes */
+ case 0x02:
+ {
+ /* Capabilities are stored as bits in first 4 bytes,
+ * inbuffer[2] byte is bits 31:24
+ * inbuffer[3] byte is bits 23:16
+ * inbuffer[4] byte is bits 15:08
+ * inbuffer[5] byte is bits 07:00
+ * inbuffer[6] and inbuffer[7] are all reserved bits
+ * Bit 0 = AM Band 520-1710 Khz
+ * Bit 1 = FM Europe/US 87.5 - 108.0 Mhz
+ * Bit 2 = FM Japan 76.0 - 90.0 Mhz
+ * Bit 3 = FM Wide 76.0 - 108.0 Mhz
+ * Bit 4 = HD Radio Capable
+ * Bit 5:7 Reserved
+ * Bit 8 = Tuner Power On/Off Control Capable
+ * Bit 9 = Status Change Notification Capable
+ * Bit 10:15 Reserved
+ * Bit 17:16 Minimum FM Resolution ID Bits
+ * 00 = 200Khz, 01 = 100Khz, 10 = 50Khz, 11 = reserved
+ * Bit 18 = Tuner Seek Up/Down Capable
+ * Bit 19 = Tuner Seek RSSI Threshold. Only if 18=1
+ * Bit 20 = Force Monophonic mode capable
+ * Bit 21 = Stero Blend Capable
+ * Bit 22 = FM Tuner deemphasis select capable
+ * Bit 23 = AM Tuner Resolution 9Khz (0=10Khz Only) capable
+ * Bit 24 = Radio Data System (RDS/RBDS) data capable
+ * Bit 25 = Tuner Channel RSSI indicator capable
+ * Bit 26 = Stero Source Indicator capable
+ * Bit 27 = RDS/RBDS Raw mode capable
+ * Bit 31:28 Reserved
+ *
+ * ipod Tuner returns 07 5E 07 0E 10 4B
+ * Bytes 6,7 Reserved
+ * ???????? ????????
+ * ???????? ????????
+ * 00010000 01001011
+ *
+ * Byte 5 - 0E
+ * 00000000
+ * 76543210
+ * 00001110
+ * AM
+ * FM Europe/US
+ * FM Japan
+ * FM Wide
+ *
+ * Byte 4 - 07
+ * 11111100
+ * 54321098
+ * 00000111
+ * Tuner Power On/Off
+ * Status Change Notification
+ * ?? Should be reserved
+ *
+ * Byte 3 - 5E
+ * 22221111
+ * 32109876
+ * 01011110
+ * Tuner Seek Up/Down
+ * Tuner Seek RSSI Threshold
+ * Force Mono Mode Capable
+ * Stereo Blend Capable
+ * FM Tuner deemphasis select capable
+ *
+ * Byte 2 - 07
+ * 33222222
+ * 10987654
+ * 00000111
+ * RDS/RBDS Capable
+ * Tuner Channel RSSI Indicator
+ * Stereo Source
+ *
+ * Just need to see what we can use this data for
+ * Make a selection for the tuner mode to select
+ * Preference is
+ * 1st - 76 to 108 FM
+ * 2nd - 87.5 to 108 Fm
+ * 3rd - 76 to 90 Fm
+ * 4th - AM
+ *
+ */
+
+ if ((inbuffer[4] & 0x03) >0) {
+ statusnotifymaskbyte = 0;
+ if ((inbuffer[4] >> 0) & 0x01) {
+ /* Supports Tuner Power On/Off, so set ON */
+ statusnotifymaskbyte = 1;
+ }
+ if ((inbuffer[4] >> 1) & 0x01) {
+ /* Supports Status Change Notification so set ON */
+ /* Apple 5/6/7G firmware does NOT enable this bit */
+ /* statusnotifymaskbyte += 2; */
+ }
+ IAP_TX_INIT(0x07, 0x05);
+ IAP_TX_PUT(statusnotifymaskbyte);
+ iap_send_tx();
+ }
+ if ((inbuffer[5] >> 1) & 0x01) {
+ /* Supports FM Europe/US Tuner 87.5 - 108.0 Mhz */
+ /* Apple firmware sends this before setting region */
+ IAP_TX_INIT(0x07, 0x0E);
+ IAP_TX_PUT(0x00);
+ iap_send_tx();
+ /* Apple firmware then sends region */
+ IAP_TX_INIT(0x07, 0x08);
+ IAP_TX_PUT(0x02);
+ iap_send_tx();
+ } else if ((inbuffer[5] >> 3) & 0x01) {
+ /* Supports FM Wide Tuner 76 - 108.0 Mhz */
+ /* apple firmware send this before setting region */
+ IAP_TX_INIT(0x07, 0x0E);
+ IAP_TX_PUT(0x00);
+ iap_send_tx();
+ /* Apple firmware then send region */
+ IAP_TX_INIT(0x07, 0x08);
+ IAP_TX_PUT(0x08);
+ iap_send_tx();
+ } else if ((inbuffer[5] >> 2) & 0x01) {
+ /* Supports FM Japan Tuner 76 - 90.0 Mhz */
+ /* apple firmware send this before setting region */
+ IAP_TX_INIT(0x07, 0x0E);
+ IAP_TX_PUT(0x41);
+ iap_send_tx();
+ /* Apple firmware then send region */
+ IAP_TX_INIT(0x07, 0x08);
+ IAP_TX_PUT(0x04);
+ iap_send_tx();
+ } else if ((inbuffer[5] >> 0) & 0x01) {
+ /* Supports AM Tuner */
+ IAP_TX_INIT(0x07, 0x08);
+ IAP_TX_PUT(0x01);
+ iap_send_tx();
+ }
+
+ if ((inbuffer[2] & 0x03) > 0) {
+ statusnotifymaskbyte = 0;
+ if ((inbuffer[2] >> 0) & 0x01) {
+ /* Supports RDS/RBDS Capable so set
+ *StatusChangeNotify for RDS/RBDS Data
+ */
+ statusnotifymaskbyte = 1;
+ }
+ if ((inbuffer[2] >> 1) & 0x01) {
+ /* Supports Tuner Channel RSSi Indicator Capable so set */
+ /* StatusChangeNotify for RSSI */
+ /* Apple 5G firmware does NOT enable this bit so we wont */
+ /* statusnotifymaskbyte += 2; */
+ }
+ IAP_TX_INIT(0x07, 0x18);
+ IAP_TX_PUT(statusnotifymaskbyte);
+ iap_send_tx();
+ }
+
+ if ((inbuffer[4] >> 2) & 0x01) {
+ /* Reserved */
+ }
+ if ((inbuffer[4] >> 3) & 0x01) {
+ /* Reserved */
+ }
+ if ((inbuffer[3] >> 1) & 0x01) {
+ /* Tuner Seek Up/Down` */
+ }
+ if ((inbuffer[3] >> 2) & 0x01) {
+ /* Tuner Seek RSSI Threshold */
+ }
+ if ((inbuffer[3] >> 3) & 0x01) {
+ /* Force Mono Mode */
+ }
+ if ((inbuffer[3] >> 4) & 0x01) {
+ /* Stereo Blend */
+ }
+ if ((inbuffer[3] >> 6) & 0x01) {
+ /* FM Tuner deemphasis */
+ }
+ if ((inbuffer[2] >> 2) & 0x01) {
+ /* Stereo Source */
+ }
+ break;
+ }
+ /* case 03 ToAccessory GetTunerCtrl 2 bytes */
+
+ /* case 04 ToIpod RetTunerCtrl 3 bytes
+ * Bit 0 power is on (1) or Off (0)
+ * Bit 1 StatusChangeNotify is enabled (1) or disabled (0)
+ * Bit 3 RDS/RBDS Raw mode enabled
+ *
+ * Should/Can we do something with these?
+ */
+
+ /* case 05 ToAccessory SetTunerCtrl 3 bytes
+ * Bits as per 0x04 above
+ * Bit 0/1 set through Lingo7 Cmd02 */
+
+ /* case 06 ToAccessory GetTunerBand 2 bytes */
+
+ /* case 07 ToIpod RetTunerBand 3 bytes
+ * Returns current band for Tuner. See 0x08 below
+ *
+ * Should/Can we do something with these?
+ */
+
+ /* case 08 ToAccessory SetTuneBand
+ * Set Bit 0 for AM
+ * Set Bit 1 for FM Europe/U S 87.5-108Mhz
+ * Set Bit 2 for FM JApan 76.0-90.0Mhz
+ * Set Bit 3 for FM Wide 76.0-108Mhz
+ * Currently we send this after receiving capabilities
+ * on 0x02 above
+ */
+
+ /* case 09 ToAccessory GetTunerFreq 2 bytes */
+
+ /* case 0A ToIpod RetTunerFreq 7 bytes */
+ case 0x0A:
+ {
+ /* Returns Frequency set and RSSI Power Levels
+ * These are sent as is to rmt_tuner_freq() in
+ * ../firmware/drivers/tuner/ipod_remote_tuner.c */
+ rmt_tuner_freq(len, inbuffer);
+ break;
+ }
+
+ /* case 0B ToAccessory SetTunerFreq 6 bytes */
+
+ /* case 0C ToAccessory GetTunerMode 2 bytes */
+
+ /* case 0D ToIpod RetTunerMode 3 bytes
+ * Returns Tuner Mode Status in 8 bits as follows
+ * Bit 1:0 - FM Tuner Resolution
+ * Bit 2 Tuner is seeking up or down
+ * Bit 3 Tuner is seeking with RSSI min theshold enabled
+ * Bit 4 Force Mono Mode (1) or allow stereo (0)
+ * Bit 5 Stereo Blend enabled. Valid only if Bit 4 is 0
+ * Bit 6 FM Tuner Deemphasis 50uS (1) or 75uS (0)
+ * Bit 7 Reserved 0
+ */
+
+ /* case 0E ToAccessory SetTunerMode 3 bytes
+ * See 0x0D for Bit Descriptions
+ * Bits set by Cmd 02
+ */
+
+ /* case 0F ToAccessory GetTunerSeekRssi 2 bytes */
+
+ /* case 10 ToIpod RetTunerSeekRssi 3 bytes
+ * Returns RSSI Value for seek operations
+ * value is 0 (min) - 255 (max)
+ */
+
+ /* case 11 ToAccessory SetTunerSeekRssi 3 bytes */
+
+ /* case 12 ToAccessory TunerSeekStart 3 bytes */
+
+ /* case 13 ToIpod TunerSeekDone 7 bytes */
+ case 0x13:
+ {
+ rmt_tuner_freq(len, inbuffer);
+ break;
+ }
+
+ /* case 14 ToAccessory GetTunerStatus 2 bytes */
+
+ /* case 15 ToIpod RetTunerStatus 3 bytes */
+
+ /* case 16 ToAccessory GetStatusNotifyMask 2 bytes */
+
+ /* case 17 ToIpod RetStatusNotifyMask 3 bytes */
+
+ /* case 18 ToAccessory SetStatusNotifyMask 3 bytes
+ * This is set by Cmd 02
+ */
+
+ /* case 19 ToIpod StatusChangeNotify 3 bytes */
+ case 0x19:
+ {
+ /* Returns StatusChangeNotify bits to ipod.
+ * Bit 0 set for RDS/RBDS data ready
+ * Bit 1 set for Tuner RSSI level change
+ * Bit 2 for Stereo Indicator changed
+ * If any of these are set we will request the data
+ * need to look at using these
+ */
+ break;
+ }
+
+ /* case 1A ToAccessory GetRdsReadyStatus 2 bytes */
+
+ /* case 1B ToIpod RetRdsReadyStatus 6 bytes */
+ case 0x1B:
+ {
+ break;
+ }
+ /* case 1C ToAccessory GetRdsData 3 bytes */
+
+ /* case 1D ToIpod RetRdsData NN bytes */
+ case 0x1D:
+ {
+ rmt_tuner_rds_data(len, inbuffer);
+ break;
+ }
+
+ /* case 1E ToAccessory GetRdsNotifyMask 2 bytes*/
+
+ /* case 1F ToIpod RetRdsNotifyMask 6 Bytes*/
+ case 0x1F:
+ {
+ break;
+ }
+
+ /* case 20 ToAccessory SetRdsNotifyMask 6 bytes */
+
+ /* case 21 ToIpod RdsReadyNotify NN bytes */
+ case 0x21:
+ {
+ rmt_tuner_rds_data(len, inbuffer);
+ break;
+ }
+ /* case 22 Reserved */
+
+ /* case 23 Reserved */
+
+ /* case 24 Reserved */
+
+ /* case 25 ToAccessory GetHDProgramServiceCount 0 bytes */
+
+ /* case 26 ToIpod RetHDProgramServiceCount 1 bytes */
+ case 0x26:
+ {
+ break;
+ }
+
+ /* case 27 ToAccessory GetHDProgramService 0 bytes */
+
+ /* case 28 ToIpod RetHDProgramService 1 bytes */
+ case 0x28:
+ {
+ break;
+ }
+
+ /* case 29 ToAccessory SetHDProgramService 1 bytes */
+
+ /* case 2A ToAccessory GetHDDataReadyStatus 0 bytes */
+
+ /* case 2B ToIpod RetHDDataReadyStatus 4 bytes */
+ case 0x2B:
+ {
+ break;
+ }
+
+ /* case 2C ToAccessory GetHDData 1 bytes */
+
+ /* case 2D ToIpod RetHDData NN bytes */
+ case 0x2D:
+ {
+ break;
+ }
+
+ /* case 2E ToAccessory GetHDDataNotifyMask 0 bytes */
+
+ /* case 2F ToIpod RetHDDataNotifyMask 4 bytes */
+ case 0x2F:
+ {
+ break;
+ }
+
+ /* case 30 ToAccessory SetHDDataNotifyMask 4 bytes */
+
+ /* case 31 ToIpod HDDataReadyNotify NN bytes */
+ case 0x31:
+ {
+ break;
+ }
+
+ /* The default response is IAP_ACK_BAD_PARAM */
+ default:
+ {
+#ifdef LOGF_ENABLE
+ logf("iap: Unsupported Mode07 Command");
+#endif
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ }
+}