summaryrefslogtreecommitdiffstats
path: root/apps/iap/iap-lingo7.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/iap/iap-lingo7.c')
-rw-r--r--apps/iap/iap-lingo7.c491
1 files changed, 491 insertions, 0 deletions
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;
+ }
+ }
+}