492 lines
16 KiB
C
492 lines
16 KiB
C
|
/***************************************************************************
|
||
|
* __________ __ ___.
|
||
|
* 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;
|
||
|
}
|
||
|
}
|
||
|
}
|