summaryrefslogtreecommitdiffstats
path: root/apps/iap/iap-lingo4.c
diff options
context:
space:
mode:
authorRalf Ertzinger <rockbox@camperquake.de>2013-06-22 10:08:23 +0100
committerFrank Gevaerts <frank@gevaerts.be>2013-11-10 18:41:24 +0100
commitb170c73f922e3457b923b4e7fcbec794a8885c77 (patch)
tree89fbdbd8c25af5101a29a1ede3b896332a4e205c /apps/iap/iap-lingo4.c
parent500b137308a6ee5c2aba873734a8956d70472f56 (diff)
downloadrockbox-b170c73f922e3457b923b4e7fcbec794a8885c77.tar.gz
rockbox-b170c73f922e3457b923b4e7fcbec794a8885c77.tar.bz2
rockbox-b170c73f922e3457b923b4e7fcbec794a8885c77.zip
Updated IAP commands.
Originally written and uploaded by Lalufu (Ralf Ertzinger) in Feb 2012. They have been condensed into a single patch and some further additions by Andy Potter. Currently includes Authentication V2 support from iPod to Accessory, RF/BlueTooth transmitter support, selecting a playlist and selecting a track from the current playlist. Does not support uploading Album Art or podcasts. Has been tested on the following iPods, 4th Gen Grayscale, 4th Gen Color/Photo, Mini 2nd Gen, Nano 1st Gen and Video 5.5Gen. Change-Id: Ie8fc098361844132f0228ecbe3c48da948726f5e Co-Authored by: Andy Potter <liveboxandy@gmail.com> Reviewed-on: http://gerrit.rockbox.org/533 Reviewed-by: Frank Gevaerts <frank@gevaerts.be>
Diffstat (limited to 'apps/iap/iap-lingo4.c')
-rw-r--r--apps/iap/iap-lingo4.c3153
1 files changed, 3153 insertions, 0 deletions
diff --git a/apps/iap/iap-lingo4.c b/apps/iap/iap-lingo4.c
new file mode 100644
index 0000000000..fa0196645b
--- /dev/null
+++ b/apps/iap/iap-lingo4.c
@@ -0,0 +1,3153 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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 "dir.h"
+#include "settings.h"
+#include "filetree.h"
+#include "wps.h"
+#include "playback.h"
+
+/*
+ * This macro is meant to be used inside an IAP mode message handler.
+ * It is passed the expected minimum length of the message buffer.
+ * If the buffer 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)
+
+/* Used to remember the last Type and Record requested */
+static char cur_dbrecord[5] = {0};
+
+/* Used to remember the total number of filtered database records */
+static unsigned long dbrecordcount = 0;
+
+/* Used to remember the LAST playlist selected */
+static unsigned long last_selected_playlist = 0;
+
+static void cmd_ack(const unsigned int cmd, const unsigned char status)
+{
+ IAP_TX_INIT4(0x04, 0x0001);
+ IAP_TX_PUT(status);
+ IAP_TX_PUT_U16(cmd);
+ iap_send_tx();
+}
+
+#define cmd_ok(cmd) cmd_ack((cmd), IAP_ACK_OK)
+
+static void get_playlist_name(unsigned char *dest,
+ unsigned long item_offset,
+ size_t max_length)
+{
+ if (item_offset == 0) return;
+ DIR* dp;
+ struct dirent* playlist_file = NULL;
+
+ dp = opendir(global_settings.playlist_catalog_dir);
+
+ char *extension;
+ unsigned long nbr = 0;
+ while ((nbr < item_offset) && ((playlist_file = readdir(dp)) != NULL))
+ {
+ /*Increment only if there is a playlist extension*/
+ if ((extension=strrchr(playlist_file->d_name, '.')) != NULL){
+ if ((strcmp(extension, ".m3u") == 0 ||
+ strcmp(extension, ".m3u8") == 0))
+ nbr++;
+ }
+ }
+ if (playlist_file != NULL) {
+ strlcpy(dest, playlist_file->d_name, max_length);
+ }
+ closedir(dp);
+}
+
+static void seek_to_playlist(unsigned long index)
+{
+ unsigned char selected_playlist
+ [sizeof(global_settings.playlist_catalog_dir)
+ + 1
+ + MAX_PATH] = {0};
+
+ strcpy(selected_playlist,
+ global_settings.playlist_catalog_dir);
+ int len = strlen(selected_playlist);
+ selected_playlist[len] = '/';
+ get_playlist_name (selected_playlist + len + 1,
+ index,
+ MAX_PATH);
+ ft_play_playlist(selected_playlist,
+ global_settings.playlist_catalog_dir,
+ strrchr(selected_playlist, '/') + 1);
+
+}
+
+static unsigned long nbr_total_playlists(void)
+{
+ DIR* dp;
+ unsigned long nbr_total_playlists = 0;
+ struct dirent* playlist_file = NULL;
+ char *extension;
+ dp = opendir(global_settings.playlist_catalog_dir);
+ while ((playlist_file = readdir(dp)) != NULL)
+ {
+ /*Increment only if there is a playlist extension*/
+ if ((extension=strrchr(playlist_file->d_name, '.')) != NULL)
+ {
+ if ((strcmp(extension, ".m3u") == 0 ||
+ strcmp(extension, ".m3u8") == 0))
+ {
+ nbr_total_playlists++;
+ }
+ }
+ }
+ closedir(dp);
+ return nbr_total_playlists;
+}
+
+void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf)
+{
+ unsigned int cmd = (buf[1] << 8) | buf[2];
+ /* Lingo 0x04 commands are at least 3 bytes in length */
+ CHECKLEN(3);
+
+ /* Lingo 0x04 must have been negotiated */
+ if (!DEVICE_LINGO_SUPPORTED(0x04)) {
+#ifdef LOGF_ENABLE
+ logf("iap: Mode04 Not Negotiated");
+#endif
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ return;
+ }
+
+ /* All these commands require extended interface mode */
+ if (interface_state != IST_EXTENDED) {
+#ifdef LOGF_ENABLE
+ logf("iap: Not in Mode04 Extended Mode");
+#endif
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ return;
+ }
+ 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
+ * indicates the device command for which the response is being
+ * sent. The command status indicates the results of the command
+ * (success or failure).
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x06 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x01 Command ID (bits 7:0)
+ * 6 0xNN Command result status. Possible values are:
+ *  0x00 = Success (OK)
+ * 0x01 = ERROR: Unknown database category
+ *  0x02 = ERROR: Command failed
+ * 0x03 = ERROR: Out of resources
+ * 0x04 = ERROR: Bad parameter
+ * 0x05 = ERROR: Unknown ID
+ * 0x06 = Reserved
+ * 0x07 = Accessory not authenticated
+ *  0x08 - 0xFF = Reserved
+ * 7 0xNN The ID of the command being acknowledged (bits 15:8).
+ * 8 0xNN The ID of the command being acknowledged (bits 7:0).
+ * 9 0xNN Telegram payload checksum byte
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0002: /* GetCurrentPlayingTrackChapterInfo */
+ /* The following is the description for the Apple Firmware
+ * Requests the chapter information of the currently playing track.
+ * In response, the iPod sends a
+ * Command 0x0003: ReturnCurrentPlayingTrackChapterInfo
+ * telegram to the device.
+ * Note: The returned track index is valid only when there is a
+ * currently playing or paused track.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x02 Command ID (bits 7:0)
+ * 6 0xF7 Telegram payload checksum byte
+ *
+ * We Return that the track does not have chapter information by
+ * returning chapter index -1 (0xFFFFFFFF) and chapter count 0
+ * (0x00000000)
+ */
+ {
+ unsigned char data[] = {0x04, 0x00, 0x03,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00};
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x0003: /* ReturnCurrentPlayingTrackChapterInfo. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the chapter information of the currently playing track.
+ * The iPod sends this telegramin response to the
+ * Command 0x0002: GetCurrentPlayingTrackChapterInfo
+ * telegram from the device. The track chapter information includes
+ * the currently playingtrack's chapter index,as well as the
+ * total number of chapters in the track. The track chapter and the
+ * total number of chapters are 32-bit signed integers. The chapter
+ * index of the firstchapter is always 0x00000000. If the track does
+ * not have chapter information, a chapter index of -1(0xFFFFFFFF)
+ * and a chapter count of 0 (0x00000000) are returned.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x0B Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x03 Command ID (bits 7:0)
+ * 6 0xNN Current chapter index (bits 31:24)
+ * 7 0xNN Current chapter index (bits 23:16)
+ * 8 0xNN Current chapter index (bits 15:8)
+ * 9 0xNN Current chapter index (bits 7:0)
+ * 10 0xNN Chapter count (bits 31:24)
+ * 11 0xNN Chapter count (bits 23:16)
+ * 12 0xNN Chapter count (bits 15:8)
+ * 13 0xNN Chapter count (bits 7:0)
+ * 14 0xNN Telegram payload checksum byte
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0004: /* SetCurrentPlayingTrackChapter */
+ /* The following is the description for the Apple Firmware
+ *
+ * Sets the currently playing track chapter.You can send the Command
+ * 0x0002: GetCurrentPlayingTrackChapterInfo telegram to get the
+ * chapter count and the index of the currently playing chapter in
+ * the current track. In response to the command
+ * SetCurrentPlayingTrackChapter, the iPod sends an ACK telegram
+ * with the command status.
+ *
+ * Note: This command should be used only when the iPod is in a
+ * playing or paused state. The command fails if the iPod is stopped
+ * or if the track does not contain chapter information.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x04 Command ID (bits 7:0)
+ * 6 0xNN Chapter index (bits 31:24)
+ * 7 0xNN Chapter index (bits 23:16)
+ * 8 0xNN Chapter index (bits 15:8)
+ * 9 0xNN Chapter index (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ * We don't do anything with this as we don't support chapters,
+ * so just return BAD_PARAM
+ */
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0005: /* GetCurrentPlayingTrackChapterPlayStatus */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the chapter playtime status of the currently playing
+ * track. The status includes the chapter length and the time
+ * elapsed within that chapter. In response to a valid telegram, the
+ * iPod sends a Command 0x0006:
+ * ReturnCurrentPlayingTrackChapterPlayStatus telegram to the
+ * device.
+ *
+ * Note: If the telegram length or chapter index is invalid for
+ * instance, if the track does not contain chapter information the
+ * iPod responds with an ACK telegram including the specific error
+ * status.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x05 Command ID (bits 7:0)
+ * 6 0xNN Currently playingchapter index (bits31:24)
+ * 7 0xNN Currently playingchapter index (bits23:16)
+ * 8 0xNN Currently playing chapter index (bits 15:8)
+ * 9 0xNN Currently playing chapter index (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ * The returned data includes 4 bytes for Chapter Length followed
+ * by 4 bytes of elapsed time If there is no currently playing
+ * chapter, length and elapsed are 0
+ * We don't do anything with this as we don't support chapters,
+ * so just return BAD_PARAM
+ */
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0006: /* ReturnCurrentPlayingTrackChapterPlayStatus. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the play status of the currently playing track chapter.
+ * The iPod sends this telegram in response to the Command 0x0005:
+ * GetCurrentPlayingTrackChapterPlayStatus telegram from the device.
+ * The returned information includes the chapter length and elapsed
+ * time, in milliseconds. If there is no currently playing chapter,
+ * the chapter length and elapsed time are zero.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x0B Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x06 Command ID (bits 7:0)
+ * 6 0xNN Chapter length in milliseconds (bits 31:24)
+ * 7 0xNN Chapter length in milliseconds (bits 23:16)
+ * 8 0xNN Chapter length in milliseconds (bits 15:8)
+ * 9 0xNN Chapter length in milliseconds (bits 7:0)
+ * 10 0xNN Elapsed time in chapter, in milliseconds (bits 31:24)
+ * 11 0xNN Elapsed time in chapter, in milliseconds (bits 23:16)
+ * 12 0xNN Elapsed time in chapter, in milliseconds (bits 15:8)
+ * 13 0xNN Elapsed time in chapter, in milliseconds (bits 7:0)
+ * 14 0xNN Telegram payload checksum byte
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0007: /* GetCurrentPlayingTrackChapterName */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests a chapter name in the currently playing track. In
+ * response to a valid telegram, the iPod sends a Command 0x0008:
+ * ReturnCurrentPlayingTrackChapterName telegram to the device.
+ *
+ * Note: If the received telegram length or track index is invalid
+ * for instance, if the track does not have chapter information or
+ * is not a part of the Audiobook category, the iPod responds with
+ * an ACK telegram including the specific error status.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x07 Command ID (bits 7:0)
+ * 6 0xNN Chapter index (bits 31:24)
+ * 7 0xNN Chapter index (bits 23:16)
+ * 8 0xNN Chapter index (bits 15:8)
+ * 9 0xNN Chapter index (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ * We don't do anything with this as we don't support chapters,
+ * so just return BAD_PARAM
+ */
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0008: /* ReturnCurrentPlayingTrackChapterName. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns a chapter name in the currently playing track. The iPod
+ * sends this telegram in response to a valid Command 0x0007:
+ * GetCurrentPlayingTrackChapterName telegram from the
+ * device. The chapter name is encoded as a null-terminated UTF-8
+ * character array.
+ *
+ * Note: The chapter name string is not limited to 252 characters;
+ * it may be sent in small or large telegram format depending on
+ * the string length. The small telegram format is shown.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x08 Command ID (bits 7:0)
+ * 6-N 0xNN Chapter name as UTF-8 character array
+ *(last byte) 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0009: /* GetAudioBookSpeed */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the current iPod audiobook speed state. The iPod
+ * responds with the “Command 0x000A: ReturnAudiobookSpeed”
+ * telegram indicating the current audiobook speed.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x09 Command ID (bits 7:0)
+ * 6 0xF0 Telegram payload checksum byte
+ *
+ * ReturnAudioBookSpeed
+ * 0x00 = Normal, 0xFF = Slow, 0x01 = Fast
+ * We always respond with Normal speed
+ */
+ {
+ unsigned char data[] = {0x04, 0x00, 0x0A, 0x00};
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x000A: /* ReturnAudioBookSpeed. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the current audiobook speed setting. The iPod sends
+ * this telegram in response to the Command 0x0009:
+ * GetAudiobookSpeed command from the device.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x0A Command ID (bits 7:0)
+ * 6 0xNN Audiobook speed status code.
+ * 0xFF Slow (-1)
+ * 0x00 Normal
+ * 0x01 Fast (+1)
+ * 7 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x000B: /* SetAudioBookSpeed */
+ /* The following is the description for the Apple Firmware
+ * Sets the speed of audiobook playback. The iPod audiobook speed
+ * states are listed above. This telegram has two modes: one to
+ * set the speed of the currently playing audiobook and a second
+ * to set the audiobook speed for all audiobooks. Byte number 7
+ * is an optional byte; devices should not send this byte if they
+ * want to set the speed only of the currently playing audiobook.
+ * If devices want to set the global audiobook speed setting then
+ * they must use byte number 7. This is the Restore on Exit byte;
+ * a nonzero value restores the original audiobook speed setting
+ * when the accessory is detached. If this byte is zero, the
+ * audiobook speed setting set by the accessory is saved and
+ * persists after the accessory is detached from the iPod. See below
+ * for the telegram format used when including the Restore on Exit
+ * byte.
+ * In response to this command, the iPod sends an ACK telegram with
+ * the command status.
+ *
+ * Note: Accessory developers are encouraged to always use the
+ * Restore on Exit byte with a nonzero value, to restore any of the
+ * user's iPod settings that were modified by the accessory.
+ *
+ * Byte Value Meaning (Cuurent audiobook only
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x0B Command ID (bits 7:0)
+ * 6 0xNN New audiobook speed code.
+ * 7 0xNN Telegram payload checksum byte
+ *
+ *
+ * SetAudiobookSpeed telegram to set the global audiobook speed
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x05 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x0B Command ID (bits 7:0)
+ * 6 0xNN Global audiobook speed code.
+ * 7 0xNN Restore on Exit byte.
+ * If 1, the original setting is restored on detach;
+ * if 0, the newsetting persists after accessory detach.
+ * 8 0xNN Telegram payload checksum byte
+ *
+ *
+ * We don't do anything with this as we don't support chapters,
+ * so just return BAD_PARAM
+ */
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x000C: /* GetIndexedPlayingTrackInfo */
+ /* The following is the description for the Apple Firmware
+ *
+ * Gets track information for the track at the specified index.
+ * The track info type field specifies the type of information to be
+ * returned, such as song lyrics, podcast name, episode date, and
+ * episode description. In response, the iPod sends the Command
+ * 0x000D: ReturnIndexedPlayingTrackInfo command with the requested
+ * track information. If the information type is invalid or does not
+ * apply to the selected track, the iPod returns an ACK with an
+ * error status.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x0A Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x0C Command ID (bits 7:0)
+ * 6 0xNN Track info type. See Below
+ * 7 0xNN Track index (bits 31:24)
+ * 8 0xNN Track index (bits 23:16)
+ * 9 0xNN Track index (bits 15:8)
+ * 10 0xNN Track index (bits 7:0)
+ * 11 0xNN Chapter index (bits 15:8)
+ * 12 0xNN Chapter index (bits 7:0)
+ * (last byte)0xNN Telegram payload checksum byte
+ *
+ * Track Info Types: Return Data
+ * 0x00 Track Capabilities. 10byte data
+ * 0x01 Podcast Name UTF-8 String
+ * 0x02 Track Release Date 7Byte Data All 0 if invalid
+ * 0x03 Track Description UTF-8 String
+ * 0x04 Track Song Lyrics UTF-8 String
+ * 0x05 Track Genre UTF-8 String
+ * 0x06 Track Composer UTF-8 String
+ * 0x07 Track Artwork Count 2byte formatID and 2byte count of images
+ * 0x08-0xff Reserved
+ *
+ * Track capabilities
+ * 0x00-0x03
+ * Bit0 is Audiobook
+ * Bit1 has chapters
+ * Bit2 has album art
+ * Bit3 has lyrics
+ * Bit4 is podcast episode
+ * Bit5 has Release Date
+ * Bit6 has Decription
+ * Bit7 Contains Video
+ * Bit8 Play as Video
+ * Bit9+ Reserved
+ * 0x04-0x07 Total Track Length in ms
+ * 0x08-0x09 Chapter Count
+ *
+ * Track Release Date Encoding
+ * 0x00 Seconds 0-59
+ * 0x01 Minutes 0-59
+ * 0x02 Hours 0-23
+ * 0x03 Day Of Month 1-31
+ * 0x04 Month 1-12
+ * 0x05 Year Bits 15:8 2006 = 2006AD
+ * 0x06 Year Bits 7:0
+ * 0x07 Weekday 0-6 where 0=Sunday 6=Saturday
+ *
+ *
+ */
+ {
+ if (len < (10))
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ struct mp3entry *id3 = audio_current_track();
+
+ switch(buf[3])
+ {
+ case 0x01: /* Podcast Not Supported */
+ case 0x04: /* Lyrics Not Supported */
+ case 0x03: /* Description */
+ case 0x05: /* Genre */
+ case 0x06: /* Composer */
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ default:
+ {
+ IAP_TX_INIT4(0x04, 0x000D);
+ IAP_TX_PUT(buf[3]);
+ switch(buf[3])
+ {
+ case 0x00:
+ {
+ /* Track Capabilities 10Bytes Data */
+ IAP_TX_PUT_U32(0); /* Track Capabilities. */
+ /* Currently None Supported*/
+ IAP_TX_PUT_U32(id3->length); /* Track Length */
+ IAP_TX_PUT_U16(0x00); /* Chapter Count */
+ break;
+ }
+ case 0x02:
+ {
+ /* Track Release Date 7 Bytes Data
+ * Currently only returns a fixed value,
+ * Sunday 1st Feb 2011 3Hr 4Min 5Secs
+ */
+ IAP_TX_PUT(5); /* Seconds 0-59 */
+ IAP_TX_PUT(4); /* Minutes 0-59 */
+ IAP_TX_PUT(3); /* Hours 0-23 */
+ IAP_TX_PUT(1); /* Day Of Month 1-31 */
+ IAP_TX_PUT(2); /* Month 1-12 */
+ IAP_TX_PUT_U16(2011); /* Year */
+ IAP_TX_PUT(0); /* Day 0=Sunday */
+ break;
+ }
+ case 0x07:
+ {
+ /* Track Artwork Count */
+ /* Currently not supported */
+ IAP_TX_PUT_U16(0x00); /* Format ID */
+ IAP_TX_PUT_U16(0x00); /* Image Count */
+ break;
+ }
+ }
+ iap_send_tx();
+ break;
+ }
+ }
+ break;
+ }
+ case 0x000D: /* ReturnIndexedPlayingTrackInfo. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the requested track information type and data. The iPod
+ * sends this command in response to the Command 0x000C:
+ * GetIndexedPlayingTrackInfo command.
+ * Data returned as strings are encoded as null-terminated UTF-8
+ * character arrays.
+ * If the track information string does not exist, a null UTF-8
+ * string is returned. If the track has no release date, then the
+ * returned release date has all bytes zeros. Track song lyrics and
+ * the track description are sent in a large or small telegram
+ * format with an incrementing packet index field, spanning
+ * multiple packets if needed.
+ *
+ * Below is the packet format for the
+ * ReturnIndexedPlayingTrackInfo telegram sent in response to a
+ * request for information types 0x00 to 0x02.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte
+ * 1 0x55 Start of telegram
+ * 2 0xNN Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x0D Command ID (bits 7:0)
+ * 6 0xNN Track info type. See
+ * 7-N 0xNN Track information. The data format is specific
+ * to the track info type.
+ * NN 0xNN Telegram payload checksum byte
+ *
+ * Below is the large packet format for the
+ * ReturnIndexedPlayingTrackInfo telegram sent in response to a
+ * request for information types 0x03 to 0x04. The small telegram
+ * format is not shown.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte
+ * 1 0x55 Start of telegram
+ * 2 0x00 Telegram payload marker (large format)
+ * 3 0xNN Large telegram payload length (bits 15:8)
+ * 4 0xNN Large telegram payload length (bits 7:0)
+ * 5 0x04 Lingo ID (Extended Interface lingo)
+ * 6 0x00 Command ID (bits 15:8)
+ * 7 0x0D Command ID (bits 7:0)
+ * 8 0xNN Track info type.
+ * 9 0xNN Packet information bits. If set,
+ * these bits have the following meanings:
+ * Bit 0: Indicates that there are multiple packets.
+ * Bit 1: This is the last packet. Applicable only if
+ * bit 0 is set.
+ * Bit 31:2 Reserved
+ * 10 0xNN Packet Index (bits 15:8)
+ * 11 0xNN Packet Index (bits 7:0)
+ * 12-N 0xNN Track information as a UTF-8 string.
+ * NN 0xNN Telegram payload checksum byte
+ *
+ * Track info types and return data
+ * Info Type Code Data Format
+ * 0x00 Track Capabilities and Information 10-byte data.
+ * 0x01 PodcastName UTF-8 string
+ * 0x02 Track Release Date 7-byte data.
+ * 0x03 Track Description UTF-8 string
+ * 0x04 Track Song Lyrics UTF-8 string
+ * 0x05 TrackGenre UTF-8 string
+ * 0x06 Track Composer UTF-8 string
+ * 0x07 Track Artwork Count Artwork count data. The
+ * artwork count is a sequence of 4-byte records; each record
+ * consists of a 2-byte format ID value followed by a 2-byte
+ * count of images in that format for this track. For more
+ * information about formatID and chapter index values, see
+ * commands 0x000E-0x0011 and 0x002A-0x002B.
+ * 0x08-0xFF Reserved
+ *
+ * Track Capabilities and Information encoding
+ * Byte Code
+ * 0x00-0x03 Track Capability bits. If set, these bits have the
+ * following meanings:
+ * Bit 0: Track is audiobook
+ * Bit 1: Track has chapters
+ * Bit 2: Track has album artwork
+ * Bit 3: Track has song lyrics
+ * Bit 4: Track is a podcast episode
+ * Bit 5: Track has release date
+ * Bit 6: Track has description
+ * Bit 7: Track contains video (a video podcast, music
+ * video, movie, or TV show)
+ * Bit 8: Track is currently queued to play as a video
+ * Bit 31:9: Reserved
+ * 0x04 Total track length, in milliseconds (bits 31:24)
+ * 0x05 Total track length, in milliseconds (bits 23:16)
+ * 0x06 Total track length, in milliseconds (bits 15:8)
+ * 0x07 Total track length, in milliseconds (bits 7:0)
+ * 0x08 Chapter count (bits 15:8)
+ * 0x09 Chapter count (bits 7:0)
+ *
+ * Track Release Date encoding
+ * Byte Code
+ * 0x00 Seconds (0-59)
+ * 0x01 Minutes (0-59)
+ * 0x02 Hours (0-23)
+ * 0x03 Day of themonth(1-31)
+ * 0x04 Month (1-12)
+ * 0x05 Year (bits 15:8). For example, 2006 signifies the year 2006
+ * 0x06 Year (bits 7:0)
+ * 0x07 Weekday (0-6, where 0 = Sunday and 6 = Saturday)
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x000E: /* GetArtworkFormats */
+ /* The following is the description for the Apple Firmware
+ *
+ * The device sends this command to obtain the list of supported
+ * artwork formats on the iPod. No parameters are sent.
+ *
+ * Byte Value Comment
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Length of packet
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x0E Command ID (bits 7:0)
+ * 6 0xEB Checksum/
+ *
+ * Returned Artwork Formats are a 7byte record.
+ * formatID:2
+ * pixelFormat:1
+ * width:2
+ * height:2
+ */
+ {
+ unsigned char data[] = {0x04, 0x00, 0x0F,
+ 0x04, 0x04, /* FormatID */
+ 0x02, /* PixelFormat*/
+ 0x00, 0x64, /* 100 pixels */
+ 0x00, 0x64, /* 100 pixels */
+ 0x04, 0x05, /* FormatID */
+ 0x02, /* PixelFormat*/
+ 0x00, 0xC8, /* 200 pixels */
+ 0x00, 0xC8 /* 200 pixels */
+ };
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x000F: /* RetArtworkFormats. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * The iPod sends this command to the device, giving it the list
+ * of supported artwork formats. Each format is described in a
+ * 7-byte record (formatID:2, pixelFormat:1, width:2, height:2).
+ * The formatID is used when sending GetTrackArtworkTimes.
+ * The device may return zero records.
+ *
+ * Byte Value Comment
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Length of packet
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x0F Command ID (bits 7:0)
+ * NN 0xNN formatID (15:8) iPod-assigned value for this format
+ * NN 0xNN formatID (7:0)
+ * NN 0xNN pixelFormat. Same as from SetDisplayImage
+ * NN 0xNN imageWidth(15:8).Number of pixels widefor eachimage.
+ * NN 0xNN imageWidth (7:0)
+ * NN 0xNN imageHeight (15:8). Number of pixels high for each
+ * NN 0xNN imageHeight (7:0). image
+ * Previous 7 bytes may be repeated NN times
+ * NN 0xNN Checksum
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0010: /* GetTrackArtworkData */
+ /* The following is the description for the Apple Firmware
+ * The device sends this command to the iPod to request data for a
+ * given trackIndex, formatID, and artworkIndex. The time offset
+ * from track start is the value returned by GetTrackArtworkTimes
+ *
+ * Byte Value Comment
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x0D Length of packet
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x10 Command ID (bits 7:0)
+ * 6 0xNN trackIndex (31:24).
+ * 7 0xNN trackIndex(23:16)
+ * 8 0xNN trackIndex (15:8)
+ * 9 0xNN trackIndex (7:0)
+ * 10 0xNN formatID (15:8)
+ * 11 0xNN formatID (7:0)
+ * 12 0xNN time offset from track start, in ms (31:24)
+ * 13 0xNN time offset from track start, in ms (23:16)
+ * 14 0xNN time offset from track start, in ms (15:8)
+ * 15 0xNN time offset from track start, in ms (7:0)
+ * 16 0xNN Checksum
+ *
+ * Returned data is
+ * DescriptorTelegramIndex: 2
+ * pixelformatcode: 1
+ * ImageWidthPixels: 2
+ * ImageHeightPixels: 2
+ * InsetRectangleTopLeftX: 2
+ * InsetRectangleTopLeftY: 2
+ * InsetRectangleBotRightX: 2
+ * InsetRectangleBotRightY: 2
+ * RowSizeInBytes: 4
+ * ImagePixelData:VariableLength
+ * Subsequent packets omit bytes 8 - 24
+ */
+ {
+ unsigned char data[] = {0x04, 0x00, 0x11,
+ 0x00, 0x00, /* DescriptorIndex */
+ 0x00, /* PixelFormat */
+ 0x00, 0x00, /* ImageWidthPixels*/
+ 0x00, 0x00, /* ImageHeightPixels*/
+ 0x00, 0x00, /* InsetRectangleTopLeftX*/
+ 0x00, 0x00, /* InsetRectangleTopLeftY*/
+ 0x00, 0x00, /* InsetRectangleBotRightX*/
+ 0x00, 0x00, /* InsetRectangleBotRoghtY*/
+ 0x00, 0x00, 0x00, 0x00,/* RowSize*/
+ 0x00 /* ImagePixelData Var Length*/
+ };
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x0011: /* RetTrackArtworkData. See Abobe */
+ /* The following is the description for the Apple Firmware
+ *
+ * The iPod sends the requested artwork to the accessory. Multiple
+ * RetTrackArtworkData commands may be necessary to transfer all
+ * the data because it will be too much to fit into a single packet.
+ * This command uses nearly the same format as the SetDisplayImage
+ * command (command 0x0032). The only difference is the addition
+ * of 2 coordinates; they define an inset rectangle that describes
+ * any padding that may have been added to the image. The
+ * coordinates consist of two x,y pairs. Each x or y value is 2
+ * bytes, so the total size of the coordinate set is 8 bytes.
+ *
+ * Byte Value Comment
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Length of packet
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x11 Command ID (bits 7:0)
+ * 6 0x00 Descriptor telegram index (15:8).
+ * These fields uniquely identify each packet in the
+ * RetTrackArtworkData transaction. The first telegram
+ * is the descriptor telegram, which always starts with
+ * an index of 0x0000.
+ * 7 0x00 Descriptor telegram index (7:0)
+ * 8 0xNN Display pixel format code.
+ * 9 0xNN Imagewidth in pixels (15:8)
+ * 10 0xNN Image width in pixels (7:0)
+ * 11 0xNN Image height in pixels (15:8)
+ * 12 0xNN Image height in pixels (7:0)
+ * 13 0xNN Inset rectangle, top-left point, x value (15:8)
+ * 14 0xNN Inset rectangle, top-left point, x value (7:0)
+ * 15 0xNN Inset rectangle, top-left point, y value (15:8)
+ * 16 0xNN Inset rectangle, top-left point, y value (7:0)
+ * 17 0xNN Inset rectangle,bottom-rightpoint,xvalue(15:8)
+ * 18 0xNN Inset rectangle,bottom-rightpoint, x value(7:0)
+ * 19 0xNN Inset rectangle,bottom-rightpoint,y value(15:8)
+ * 20 0xNN Inset rectangle, bottom-right point, y value(7:0)
+ * 21 0xNN Rowsize in bytes (31:24)
+ * 22 0xNN Rowsize in bytes (23:16)
+ * 23 0xNN Row size in bytes (15:8)
+ * 24 0xNN Row size in bytes (7:0)
+ * 25-NN 0xNN Image pixel data (variable length)
+ * NN 0xNN Checksum
+ *
+ * In subsequent packets in the sequence, bytes 8 through 24 are
+ * omitted.
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0012: /* RequestProtocolVersion */
+ /* The following is the description for the Apple Firmware
+ *
+ * This command is deprecated.
+ *
+ * Requests the version of the running protocol from the iPod.
+ * The iPod responds with a Command 0x0013:ReturnProtocolVersion
+ * command.
+ *
+ * Note: This command requests the Extended Interface protocol
+ * version, not the iPod software version.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x12 Command ID (bits 7:0)
+ * 6 0xE7 Telegram payload checksum byte
+ *
+ */
+ {
+ IAP_TX_INIT4(0x04, 0x0013);
+ IAP_TX_PUT(LINGO_MAJOR(0x04));
+ IAP_TX_PUT(LINGO_MINOR(0x04));
+ iap_send_tx();
+ break;
+ }
+ case 0x0013: /* ReturnProtocolVersion. See Above */
+ /* The following is the description for the Apple Firmware
+ * This command is deprecated.
+ * Sent from the iPod to the device
+ * Returns the iPod Extended Interface protocol version number.
+ * The iPod sends this command in response to the Command 0x0012:
+ * RequestProtocolVersion command from the device. The major
+ * version number specifies the protocol version digits to the left
+ * of the decimal point; the minor version number specifies the
+ * digits to the right of the decimal point. For example, a major
+ * version number of 0x01 and a minor version number of 0x08
+ * represents an Extended Interface protocol version of 1.08. This
+ * protocol information is also available through the General lingo
+ * (lingo 0x00) command RequestLingoProtocolVersion when passing
+ * lingo 0x04 as the lingo parameter.
+ *
+ * Note: This command returns the Extended Interface protocol
+ * version, not the iPod software version.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x05 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x13 Command ID (bits 7:0)
+ * 6 0xNN Protocol major version number
+ * 7 0xNN Protocol minor version number
+ * 8 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0014: /* RequestiPodName */
+ /* The following is the description for the Apple Firmware
+ * This command is deprecated.
+ * Retrieves the name of the iPod
+ *
+ * Returns the name of the user's iPod or 'iPod' if the iPod name
+ * is undefined. This allows the iPod name to be shown in the
+ * human-machineinterface(HMI) of the interfacingbody. The iPod
+ * responds with the Command 0x0015: ReturniPodName command
+ * containing the iPod name text string.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x14 Command ID (bits 7:0)
+ * 6 0xE5 Telegram payload checksum byte
+ *
+ * We return ROCKBOX, should this be definable?
+ * Should it be Volume Name?
+ */
+ {
+ IAP_TX_INIT4(0x04, 0x0015);
+ IAP_TX_PUT_STRING("ROCKBOX");
+ iap_send_tx();
+ break;
+ }
+ case 0x0015: /* ReturniPodName. See Above */
+ /* The following is the description for the Apple Firmware
+ * This command is deprecated.
+ * Sent from the iPod to the device
+ *
+ * The iPod sends this command in response to the Command 0x0014:
+ * RequestiPodName telegram from the device. The iPod name is
+ * encoded as a null-terminated UTF-8 character array. The iPod
+ * name string is not limited to 252 characters; it may be sent
+ * in small or large telegram format. The small telegram format
+ * is shown.
+ *
+ * Note: Starting with version 1.07 of the Extended Interface lingo,
+ * the ReturniPodName command on Windows-formatted iPods returns the
+ * iTunes name of the iPod instead of the Windows volume name.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x15 Command ID (bits 7:0)
+ * 6-N 0xNN iPod name as UTF-8 character array
+ * NN 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0016: /* ResetDBSelection */
+ /* The following is the description for the Apple Firmware
+ *
+ * Resets the current database selection to an empty state and
+ * invalidates the category entry count that is, sets the count
+ * to 0, for all categories except the playlist category. This is
+ * analogous to pressing the Menu button repeatedly to get to the
+ * topmost iPod HMI menu. Any previously selected database items
+ * are deselected. The command has no effect on the playback engine
+ * In response, the iPod sends an ACK telegram with the command
+ * status. Once the accessory has reset the database selection,
+ * it must initialize the category count before it can select
+ * database records. Please refer to Command 0x0018:
+ * GetNumberCategorizedDBRecords and Command 0x0017:
+ * SelectDBRecord for details.
+ *
+ * Note: Starting with protocol version 1.07, the ResetDBSelection
+ * command clears the sort order.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x16 Command ID (bits 7:0)
+ * 6 0xE3 Telegram payload checksum byte
+ *
+ *
+ * Reset the DB Record Type
+ * Hierarchy is as follows
+ * All = 0
+ * Playlist = 1
+ * Artist = 2
+ * Album = 3
+ * Genre = 4
+ * Tracks = 5
+ * Composers = 6
+ * Audiobooks = 7
+ * Podcasts = 8
+ *
+ */
+ {
+ cur_dbrecord[0] = 0;
+ put_u32(&cur_dbrecord[1],0);
+ /* respond with cmd ok packet */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x0017: /* SelectDBRecord */
+ /* The following is the description for the Apple Firmware
+ * Selects one or more records in the Database Engine, based on a
+ * category relative index. For example, selecting category two
+ * (artist) and record index one results in a list of selected
+ * tracks (or database records) from the second artist in the
+ * artist list.
+ * Selections are additive and limited by the category hierarchy;
+ * Subsequent selections are made based on the subset of records
+ * resulting from the previous selections and not from the entire
+ * database.
+ * Note that the selection of a single record automatically passes
+ * it to the Playback Engine and starts its playback. Record indices
+ * consist of a 32-bit signed integer. To select database records
+ * with a specific sort order, use
+ * Command 0x0038: SelectSortDBRecord
+ * SelectDBRecord should be called only once a category count has
+ * been initialized through a call to Command 0x0018:
+ * GetNumberCategorizedDBRecords. Without a valid category count,
+ * the SelectDBRecord call cannot select a database record and will
+ * fail with a command failed ACK. Accessories that make use of
+ * Command 0x0016: ResetDBSelection must always initialize the
+ * category count before selecting a new database record using
+ * SelectDBRecord.
+ * Accessories should pay close attention to the ACK returned by the
+ * SelectDBRecord command. Ignoring errors may cause unexpected
+ * behavior.
+ * To undo a database selection, send the SelectDBRecord telegram
+ * with the current category selected in theDatabase Engine and a
+ * record index of -1 (0xFFFFFFFF). This has the same effect as
+ * pressing the iPod Menu button once and moves the database
+ * selection up to the next highest menu level. For example, if a
+ * device selected artist number three and then album number one,
+ * it could use the SelectDBRecord(Album, -1) telegram to return
+ * to the database selection of artist number three. If multiple
+ * database selections have been made, devices can use any of the
+ * previously used categories to return to the next highest database
+ * selection. If the category used in one of these SelectDBRecord
+ * telegrams has not been used in a previous database selection
+ * then the command is treated as a no-op.
+ * Sending a SelectDBRecord telegram with the Track category and a
+ * record index of -1 is invalid, because the previous database
+ * selection made with the Track category and a valid index passes
+ * the database selection to the Playback Engine.
+ * Sending a SelectDBRecord(Track, -1) telegram returns a parameter
+ * error. The iPod also returns a bad parameter error ACK when
+ * devices send the SelectDBRecord telegram with an invalid category
+ * type, or with the Track category and an index greater than the
+ * total number of tracks available on the iPod.
+ *
+ * Note: Selecting a podcast always selects from the main podcast
+ * library regardless of the current category context of the iPod.
+ *
+ * To immediately go to the topmost iPod menu level and reset all
+ * database selections, send the ResetDBSelection telegram to the
+ * iPod.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x08 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x17 Command ID (bits 7:0)
+ * 6 0xNN Database category type. See
+ * 7 0xNN Database record index (bits 31:24)
+ * 8 0xNN Database record index (bits 23:16)
+ * 9 0xNN Database record index (bits 15:8)
+ * 10 0xNN Database record index (bits 7:0)
+ * 11 0xNN Telegram payload checksum byte
+ *
+ * The valid database categories are listed below
+ *
+ * Category Code Protocol version
+ * Reserved 0x00 N/A
+ * Playlist 0x01 1.00
+ * Artist 0x02 1.00
+ * Album 0x03 1.00
+ * Genre 0x04 1.00
+ * Track 0x05 1.00
+ * Composer 0x06 1.00
+ * Audiobook0x07 1.06
+ * Podcast 0x08 1.08
+ * Reserved 0x09+ N/A
+ *
+ * cur_dbrecord[0] is the record type
+ * cur_dbrecord[1-4] is the u32 of the record number requested
+ * which might be a playlist or a track number depending on
+ * the value of cur_dbrecord[0]
+ */
+ {
+ memcpy(cur_dbrecord, buf + 3, 5);
+
+ int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE));
+ uint32_t index;
+ uint32_t trackcount;
+ index = get_u32(&cur_dbrecord[1]);
+ trackcount = playlist_amount();
+ if ((cur_dbrecord[0] == 5) && (index > trackcount))
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ if ((cur_dbrecord[0] == 1) && (index > (nbr_total_playlists() + 1)))
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ audio_pause();
+ switch (cur_dbrecord[0])
+ {
+ case 0x01: /* Playlist*/
+ {
+ if (index != 0x00) /* 0x00 is the On-The-Go Playlist and
+ we do nothing with it */
+ {
+ last_selected_playlist = index;
+ audio_skip(-iap_get_trackindex());
+ seek_to_playlist(last_selected_playlist);
+ }
+ break;
+ }
+ case 0x02: /* Artist */
+ case 0x03: /* Album */
+ case 0x04: /* Genre */
+ case 0x05: /* Track */
+ case 0x06: /* Composer */
+ {
+ audio_skip(index - playlist_next(0));
+ break;
+ }
+ default:
+ {
+ /* We don't do anything with the other selections.
+ * YET.
+ */
+ break;
+ }
+ }
+ if (!paused)
+ audio_resume();
+ /* respond with cmd ok packet */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x0018: /* GetNumberCategorizedDBRecords */
+ /* The following is the description for the Apple Firmware
+ *
+ * Retrieves the number of records in a particular database
+ * category.
+ * For example, a device can get the number of artists or albums
+ * present in the database. The category types are described above.
+ * The iPod responds with a Command 0x0019:
+ * ReturnNumberCategorizedDBRecords telegram indicating the number
+ * of records present for this category.
+ * GetNumberCategorizedDBRecords must be called to initialize the
+ * category count before selecting a database record using Command
+ * 0x0017: SelectDBRecord or Command 0x0038: SelectSortDBRecord
+ * commands. A category’s record count can change based on the prior
+ * categories selected and the database hierarchy. The accessory
+ * is expected to call GetNumberCategorizedDBRecords in order to
+ * get the valid range of category entries before selecting a
+ * record in that category.
+ *
+ * Note: The record count returned by this command depends on the
+ * database state before this command is sent. If the database has
+ * been reset using Command 0x0016: ResetDBSelection this command
+ * returns the total number of records for a given category.
+ * However, if this command is sent after one or more categories
+ * are selected, the record count is the subset of records that are
+ * members of all the categories selected prior to this command.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x18 Command ID (bits 7:0)
+ * 6 0xNN Database category type. See above
+ * 7 0xNN Telegram payload checksum byte
+ *
+ * This is the actual number of available records for that category
+ * some head units (Alpine CDE-103BT) use this command before
+ * requesting records and then hang if not enough records are
+ * returned.
+ */
+ {
+ unsigned char data[] = {0x04, 0x00, 0x19,
+ 0x00, 0x00, 0x00, 0x00};
+ switch(buf[3]) /* type number */
+ {
+ case 0x01: /* total number of playlists */
+ dbrecordcount = nbr_total_playlists() + 1;
+ break;
+ case 0x05: /* total number of Tracks */
+ case 0x02: /* total number of Artists */
+ case 0x03: /* total number of Albums */
+ /* We don't sort on the above but some Head Units
+ * require at least one to exist so we just return
+ * the number of tracks in the playlist. */
+ dbrecordcount = playlist_amount();
+ break;
+ case 0x04: /* total number of Genres */
+ case 0x06: /* total number of Composers */
+ case 0x07: /* total number of AudioBooks */
+ case 0x08: /* total number of Podcasts */
+ /* We don't support the above so just return that
+ there are none available. */
+ dbrecordcount = 0;
+ break;
+ }
+ put_u32(&data[3], dbrecordcount);
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x0019: /* ReturnNumberCategorizedDBRecords. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the number of database records matching the specified
+ * database category. The iPod sends this telegram in response to
+ * the Command 0x0018: GetNumberCategorizedDBRecords telegram from
+ * the device. Individual records can then be extracted by sending
+ * Command 0x001A: RetrieveCategorizedDatabaseRecords to the iPod.
+ * If no matching database records are found, a record count of
+ * zero is returned. Category types are described above.
+ * After selecting the podcast category, the number of artist,
+ * album, composer, genre, and audiobook records is always zero.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x19 Command ID (bits 7:0)
+ * 6 0xNN Database record count (bits 31:24)
+ * 7 0xNN Database record count (bits 23:16)
+ * 8 0xNN Database record count (bits 15:8)
+ * 9 0xNN Database record count (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x001A: /* RetrieveCategorizedDatabaseRecords */
+ /* The following is the description for the Apple Firmware
+ *
+ * Retrieves one or more database records from the iPod,
+ * typically based on the results from the Command 0x0018:
+ * GetNumberCategorizedDBRecords query. The database
+ * category types are described above. This telegram
+ * specifies the starting record index and the number of
+ * records to retrieve (the record count). This allows a device
+ * to retrieve an individual record or the entire set of records
+ * for a category. The record start index and record count consist
+ * of 32-bit signed integers. To retrieve all records from a given
+ * starting record index, set the record count to -1 (0xFFFFFFFF).
+ * The iPod responds to this telegram with a separate Command
+ * 0x001B: ReturnCategorizedDatabaseRecord telegram FOR EACH record
+ * matching the specified criteria (category and record index
+ * range).
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x0C Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x1A Command ID (bits 7:0)
+ * 6 0xNN Database category type. See above
+ * 7 0xNN Database record start index (bits 31:24)
+ * 8 0xNN Database record start index (bits 23:16)
+ * 9 0xNN Database record start index (bits 15:8)
+ * 10 0xNN Database record start index (bits 7:0)
+ * 11 0xNN Database record read count (bits 31:24)
+ * 12 0xNN Database record read count (bits 23:16)
+ * 13 0xNN Database record read count (bits 15:8)
+ * 14 0xNN Database record read count (bits 7:0)
+ * 15 0xNN Telegram payload checksum byte
+
+ * The returned data
+ * contains information for a single database record. The iPod sends
+ * one or more of these telegrams in response to the Command 0x001A:
+ * RetrieveCategorizedDatabaseRecords telegram from the device. The
+ * category record index is included to allow the device to
+ * determine which record has been sent. The record data is sent as
+ * a null-terminated UTF-8 encoded data array.
+ */
+ {
+ unsigned char data[7 + MAX_PATH] =
+ {0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00,
+ 'O','n','-','T','h','e','-','G','o','\0'};
+ struct playlist_track_info track;
+ struct mp3entry id3;
+
+ unsigned long start_index = get_u32(&buf[4]);
+ unsigned long read_count = get_u32(&buf[8]);
+ unsigned long counter = 0;
+ unsigned int number_of_playlists = nbr_total_playlists();
+ uint32_t trackcount;
+ trackcount = playlist_amount();
+ size_t len;
+
+ if ((buf[3] == 0x05) && ((start_index + read_count ) > trackcount))
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ if ((buf[3] == 0x01) && ((start_index + read_count) > (number_of_playlists + 1)))
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ for (counter=0;counter<read_count;counter++)
+ {
+ switch(buf[3]) /* type number */
+ {
+ case 0x01: /* Playlists */
+ get_playlist_name(data +7,start_index+counter, MAX_PATH);
+ /*Remove file extension*/
+ char *dot=NULL;
+ dot = (strrchr(data+7, '.'));
+ if (dot != NULL)
+ *dot = '\0';
+ break;
+ case 0x05: /* Tracks */
+ case 0x02: /* Artists */
+ case 0x03: /* Albums */
+ case 0x04: /* Genre */
+ case 0x06: /* Composer */
+ playlist_get_track_info(NULL, start_index + counter,
+ &track);
+ iap_get_trackinfo(start_index + counter, &id3);
+ switch(buf[3])
+ {
+ case 0x05:
+ len = strlcpy((char *)&data[7], id3.title,64);
+ break;
+ case 0x02:
+ len = strlcpy((char *)&data[7], id3.artist,64);
+ break;
+ case 0x03:
+ len = strlcpy((char *)&data[7], id3.album,64);
+ break;
+ case 0x04:
+ case 0x06:
+ len = strlcpy((char *)&data[7], "Not Supported",14);
+ break;
+ }
+ break;
+ }
+ put_u32(&data[3], start_index+counter);
+ iap_send_pkt(data, 7 + strlen(data+7) + 1);
+ yield();
+ }
+ break;
+ }
+ case 0x001B: /* ReturnCategorizedDatabaseRecord. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Contains information for a single database record. The iPod sends
+ * ONE OR MORE of these telegrams in response to the Command 0x001A:
+ * RetrieveCategorizedDatabaseRecords telegram from the device. The
+ * category record index is included to allow the device to
+ * determine which record has been sent. The record data is sent
+ * as a null-terminated UTF-8 encoded data array.
+ *
+ * Note: The database record string is not limited to 252 characters
+ * it may be sent in small or large telegram format, depending on
+ * the record size. The small telegram format is shown.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x1B Command ID (bits 7:0)
+ * 6 0xNN Database record category index (bits 31:24)
+ * 7 0xNN Database record category index (bits 23:16)
+ * 8 0xNN Database record category index (bits 15:8)
+ * 9 0xNN Database record category index (bits 7:0)
+ * 10-N 0xNN Database record as a UTF-8 character array.
+ * NN 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x001C: /* GetPlayStatus */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the current iPod playback status, allowing the
+ * device to display feedback to the user. In response, the
+ * iPod sends a Command 0x001D: ReturnPlayStatus telegram
+ * with the current playback status.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x1C Command ID (bits 7:0)
+ * 6 0xDD Telegram payload checksum byte
+ *
+ */
+ {
+ unsigned char data[] = {0x04, 0x00, 0x1D,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00};
+ struct mp3entry *id3 = audio_current_track();
+ unsigned long time_total = id3->length;
+ unsigned long time_elapsed = id3->elapsed;
+ int status = audio_status();
+ put_u32(&data[3], time_total);
+ put_u32(&data[7], time_elapsed);
+ if (status == AUDIO_STATUS_PLAY)
+ data[11] = 0x01; /* play */
+ else if (status & AUDIO_STATUS_PAUSE)
+ data[11] = 0x02; /* pause */
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x001D: /* ReturnPlayStatus. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the current iPod playback status. The iPod sends this
+ * telegram in response to the Command 0x001C: GetPlayStatus
+ * telegram from the device. The information returned includes the
+ * current track length, track position, and player state.
+ *
+ * Note: The track length and track position fields are valid only
+ * if the player state is Playing or Paused. For other player
+ * states, these fields should be ignored.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x0C Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x1D Command ID (bits 7:0)
+ * 6 0xNN Track length in milliseconds (bits 31:24)
+ * 7 0xNN Track length in milliseconds (bits 23:16)
+ * 8 0xNN Track length in milliseconds (bits 15:8)
+ * 9 0xNN Track length in milliseconds (bits 7:0)
+ * 10 0xNN Track position in milliseconds (bits 31:24)
+ * 11 0xNN Track position in milliseconds (bits 23:16)
+ * 12 0xNN Track position in milliseconds (bits 15:8)
+ * 13 0xNN Track position in milliseconds (bits 7:0)
+ * 14 0xNN Player state. Possible values are:
+ * 0x00 = Stopped
+ * 0x01 = Playing
+ * 0x02 = Paused
+ * 0x03 - 0xFE = Reserved
+ * 0xFF = Error
+ * 15 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x001E: /* GetCurrentPlayingTrackIndex */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the playback engine index of the currently playing
+ * track. In response, the iPod sends a Command 0x001F:
+ * ReturnCurrentPlayingTrackIndex telegram to the device.
+ *
+ * Note: The track index returned is valid only if there is
+ * currently a track playing or paused.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x1E Command ID (bits 7:0)
+ * 6 0xDB Telegram payload checksum byte
+ *
+ */
+ {
+ unsigned char data[] = {0x04, 0x00, 0x1F,
+ 0xFF, 0xFF, 0xFF, 0xFF};
+ long playlist_pos = playlist_next(0);
+ int status = audio_status();
+ playlist_pos -= playlist_get_first_index(NULL);
+ if(playlist_pos < 0)
+ playlist_pos += playlist_amount();
+ if ((status == AUDIO_STATUS_PLAY) || (status & AUDIO_STATUS_PAUSE))
+ put_u32(&data[3], playlist_pos);
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x001F: /* ReturnCurrentPlayingTrackIndex. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the playback engine index of the current playing track in
+ * response to the Command 0x001E: GetCurrentPlayingTrackIndex
+ * telegram from the device. The track index is a 32-bit signed
+ * integer.
+ * If there is no track currently playing or paused, an index of -1
+ * (0xFFFFFFFF) is returned.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x1F Command ID (bits 7:0)
+ * 6 0xNN Playback track index (bits 31:24)
+ * 7 0xNN Playback track index (bits 23:16)
+ * 8 0xNN Playback track index (bits 15:8)
+ * 9 0xNN Playback track index (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0020: /* GetIndexedPlayingTrackTitle. See 0x0024 below */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the title name of the indexed playing track from the
+ * iPod. In response to a valid telegram, the iPod sends a
+ * Command 0x0021: ReturnIndexedPlayingTrackTitle telegram to the
+ * device.
+ *
+ * Note: If the telegram length or playing track index is invalid,
+ * the iPod responds with an ACK telegram including the specific
+ * error status.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x20 Command ID (bits 7:0)
+ * 6 0xNN Playback track index (bits 31:24)
+ * 7 0xNN Playback track index (bits 23:16)
+ * 8 0xNN Playback track index (bits 15:8)
+ * 9 0xNN Playback track index (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ */
+ case 0x0021: /* ReturnIndexedPlayingTrackTitle. See 0x0024 Below */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the title of the indexed playing track in response to
+ * a valid Command 0x0020 GetIndexedPlayingTrackTitle telegram from
+ * the device. The track title is encoded as a null-terminated UTF-8
+ * character array.
+ *
+ * Note: The track title string is not limited to 252 characters;
+ * it may be sent in small or large telegram format, depending on
+ * the string length. The small telegram format is shown.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x21 Command ID (bits 7:0)
+ * 6-N 0xNN Track title as a UTF-8 character array
+ * NN 0xNN Telegram payload checksum byte
+ *
+ */
+ case 0x0022: /* GetIndexedPlayingTrackArtistName. See 0x0024 Below */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the name of the artist of the indexed playing track
+ * In response to a valid telegram, the iPod sends a
+ * Command 0x0023: ReturnIndexedPlayingTrackArtistName telegram to
+ * the device.
+ *
+ * Note: If the telegram length or playing track index is invalid,
+ * the iPod responds with an ACK telegram including the specific
+ * error status.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x22 Command ID (bits 7:0)
+ * 6 0xNN Playback track index (bits 31:24)
+ * 7 0xNN Playback track index (bits 23:16)
+ * 8 0xNN Playback track index (bits 15:8)
+ * 9 0xNN Playback track index (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ */
+ case 0x0023: /* ReturnIndexedPlayingTrackArtistName. See 0x0024 Below */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the artist name of the indexed playing track in response
+ * to a valid Command 0x0022 GetIndexedPlayingTrackArtistName
+ * telegram from the device. The track artist name is encoded as a
+ * null-terminated UTF-8 character array.
+ *
+ * Note: The artist name string is not limited to 252 characters;
+ * it may be sent in small or large telegram format, depending on
+ * the string length. The small telegram format is shown.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x23 Command ID (bits 7:0)
+ * 6-N 0xNN Track Artist as a UTF-8 character array
+ * NN 0xNN Telegram payload checksum byte
+ *
+ */
+ case 0x0024: /* GetIndexedPlayingTrackAlbumName AND
+ * GetIndexedPlayingTrackTitle AND
+ * AND GetIndexedPlayingTrackArtistName. */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the album name of the indexed playing track
+ * In response to a valid telegram, the iPod sends a
+ * Command 0x0025: ReturnIndexedPlayingTrackAlbumName telegram to
+ * the device.
+ *
+ * Note: If the telegram length or playing track index is invalid,
+ * the iPod responds with an ACK telegram including the specific
+ * error status.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x24 Command ID (bits 7:0)
+ * 6 0xNN Playback track index (bits 31:24)
+ * 7 0xNN Playback track index (bits 23:16)
+ * 8 0xNN Playback track index (bits 15:8)
+ * 9 0xNN Playback track index (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ unsigned char data[70] = {0x04, 0x00, 0xFF};
+ struct mp3entry id3;
+ int fd;
+ size_t len;
+ long tracknum = get_u32(&buf[3]);
+
+ data[2] = cmd + 1;
+ memcpy(&id3, audio_current_track(), sizeof(id3));
+ tracknum += playlist_get_first_index(NULL);
+ if(tracknum >= playlist_amount())
+ tracknum -= playlist_amount();
+ /* If the tracknumber is not the current one,
+ read id3 from disk */
+ if(playlist_next(0) != tracknum)
+ {
+ struct playlist_track_info info;
+ playlist_get_track_info(NULL, tracknum, &info);
+ fd = open(info.filename, O_RDONLY);
+ memset(&id3, 0, sizeof(struct mp3entry));
+ get_metadata(&id3, fd, info.filename);
+ close(fd);
+ }
+ /* Return the requested track data */
+ switch(cmd)
+ {
+ case 0x20:
+ len = strlcpy((char *)&data[3], id3.title, 64);
+ iap_send_pkt(data, 4+len);
+ break;
+ case 0x22:
+ len = strlcpy((char *)&data[3], id3.artist, 64);
+ iap_send_pkt(data, 4+len);
+ break;
+ case 0x24:
+ len = strlcpy((char *)&data[3], id3.album, 64);
+ iap_send_pkt(data, 4+len);
+ break;
+ }
+ break;
+ }
+ case 0x0025: /* ReturnIndexedPlayingTrackAlbumName. See 0x0024 Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the album name of the indexed playing track in response
+ * to a valid Command 0x0024 GetIndexedPlayingTrackAlbumName
+ * telegram from the device. The track artist name is encoded as a
+ * null-terminated UTF-8 character array.
+ *
+ * Note: The album name string is not limited to 252 characters;
+ * it may be sent in small or large telegram format, depending on
+ * the string length. The small telegram format is shown.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x25 Command ID (bits 7:0)
+ * 6-N 0xNN Track Album as a UTF-8 character array
+ * NN 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0026: /* SetPlayStatusChangeNotification */
+ /* The following is the description for the Apple Firmware
+ * Sets the state of play status change notifications from the iPod
+ * to the device. Notification of play status changes can be
+ * globally enabled or disabled. If notifications are enabled, the
+ * iPod sends a Command 0x0027: PlayStatusChangeNotification
+ * telegram to the device each time the play status changes, until
+ * the device sends this telegram again with the disable
+ * notification option. In response, the iPod sends an ACK telegram
+ * indicating the status of the SetPlayStatusChangeNotification
+ * command.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x26 Command ID (bits 7:0)
+ * 6 0xNN The state of play status change notifications.
+ * Possible values are:
+ * 0x00 = Disable all change notification
+ * 0x01 = Enable all change notification
+ * 0x02 - 0xFF = Reserved
+ * 7 0xNN Telegram payload checksum byte
+ */
+ {
+ device.do_notify = buf[3] ? true : false;
+ /* respond with cmd ok packet */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x0027: /* PlayStatusChangeNotification */
+ /* This response is handled by iap_track_changed() and iap_periodic()
+ * within iap-core.c
+ * The following is the description for the Apple Firmware
+ *
+ * The iPod sends this telegram to the device when the iPod play status
+ * changes, if the device has previously enabled notifications using
+ * Command 0x0026: SetPlayStatusChangeNotification . This telegram
+ * contains details about the new play status. Notification telegrams
+ * for changes in track position occur approximately every 500
+ * milliseconds while the iPod is playing. Notification telegrams are
+ * sent from the iPod until the device sends the
+ * SetPlayStatusChangeNotification telegram with the option to disable
+ * all notifications.
+ * Some notifications include additional data about the new play status.
+ *
+ * PlayStatusChangeNotification telegram: notifications 0x00, 0x02, 0x03
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x27 Command ID (bits 7:0)
+ * 6 0xNN New play status. See Below.
+ * 7 0xNN Telegram payload checksum byte
+ *
+ * Play Status Change Code Extended Status Data (if
+ * any)
+ * Playback stopped 0x00 None
+ * Playback track changed 0x01 New track record index
+ * (32 bits)
+ * Playback forward seek stop 0x02 None
+ * Playback backward seek stop 0x03 None
+ * Playback track position 0x04 New track position in
+ * milliseconds (32 bits)
+ * Playback chapter changed 0x05 New chapter index (32
+ * bits)
+ * Reserved 0x06 - 0xFF N/A
+ *
+ * Playback track changed (code 0x01)
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x08 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x27 Command ID (bits 7:0)
+ * 6 0x01 New status: Playback track changed
+ * 7 0xNN New playback track index (bits 31:24)
+ * 8 0xNN New playback track index (bits 23:16)
+ * 9 0xNN New playback track index (bits 15:8)
+ * 10 0xNN New playback track index (bits 7:0)
+ * 11 0xNN Telegram payload checksum byte
+ *
+ * Playback track position changed (code 0x04)
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x08 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x27 Command ID (bits 7:0)
+ * 6 0x04 New status: Playback track position changed
+ * 7 0xNN New track position in milliseconds (bits 31:24)
+ * 8 0xNN New track position in milliseconds (bits 23:16)
+ * 9 0xNN New track position in milliseconds (bits 15:8)
+ * 10 0xNN New track position in milliseconds (bits 7:0)
+ * 11 0xNN Telegram payload checksum byte
+ *
+ * Playback chapter changed (code 0x05)
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x08 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x27 Command ID (bits 7:0)
+ * 6 0x05 New status: Playback chapter changed
+ * 7 0xNN New track chapter index (bits 31:24)
+ * 8 0xNN New track chapter index (bits 23:16)
+ * 9 0xNN New track chapter index (bits 15:8)
+ * 10 0xNN New track chapter index (bits 7:0)
+ * 11 0xNN Telegram payload checksum byte
+ *
+ */
+ case 0x0028: /* PlayCurrentSelection */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests playback of the currently selected track or list of
+ * tracks. The currently selected tracks are placed in the Now
+ * Playing playlist, where they are optionally shuffled (if the
+ * shuffle feature is enabled). Finally, the specified track record
+ * index is passed to the player to play. Note that if the track
+ * index is -1(0xFFFFFFFF), the first track after the shuffle is
+ * complete is played first. If a track index of n is sent, the nth
+ * track of the selected tracks is played first, regardless of
+ * where it is located in the Now Playing playlist after the shuffle
+ * is performed (assuming that shuffle is on). In response, the iPod
+ * sends an ACK telegram indicating the status of the command.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x28 Command ID (bits 7:0)
+ * 6 0xNN Selection track record index (bits 31:24)
+ * 7 0xNN Selection track record index (bits 23:16)
+ * 8 0xNN Selection track record index (bits 15:8)
+ * 9 0xNN Selection track record index (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE));
+ uint32_t index;
+ uint32_t trackcount;
+ index = get_u32(&buf[3]);
+ trackcount = playlist_amount();
+ if (index >= trackcount)
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ audio_pause();
+ if(global_settings.playlist_shuffle)
+ {
+ playlist_randomise(NULL, current_tick, true);
+ }
+ else
+ {
+ playlist_sort(NULL, true);
+ }
+ audio_skip(index - playlist_next(0));
+ if (!paused)
+ audio_resume();
+ /* respond with cmd ok packet */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x0029: /* PlayControl */
+ {
+ /* The following is the description for the Apple Firmware
+ *
+ * Sets the new play state of the iPod. The play control command
+ * codes are shown below. In response, the iPod sends an ACK
+ * telegram indicating the status of the command.
+ *
+ * Note: If a remote device requests the Next or Previous Chapter
+ * for a track that does not contain chapters, the iPod returns a
+ * command failed ACK.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x29 Command ID (bits 7:0)
+ * 6 0xNN Play control command code.
+ * 7 0xNN Telegram payload checksum byte
+ *
+ * Play Control Command Code Protocol version
+ * Reserved 0x00 N/A
+ * Toggle Play/Pause 0x01 1.00
+ * Stop 0x02 1.00
+ * Next Track 0x03 1.00
+ * Previous Track 0x04 1.00
+ * StartFF 0x05 1.00
+ * StartRew 0x06 1.00
+ * EndFFRew 0x07 1.00
+ * NextChapter 0x08 1.06
+ * Previous Chapter 0x09 1.06
+ * Reserved 0x0A - 0xFF
+ *
+ */
+ switch(buf[3])
+ {
+ case 0x01: /* play/pause */
+ iap_remotebtn = BUTTON_RC_PLAY;
+ iap_repeatbtn = 2;
+ break;
+ case 0x02: /* stop */
+ iap_remotebtn = BUTTON_RC_PLAY|BUTTON_REPEAT;
+ iap_repeatbtn = 2;
+ break;
+ case 0x03: /* skip++ */
+ iap_remotebtn = BUTTON_RC_RIGHT;
+ iap_repeatbtn = 2;
+ break;
+ case 0x04: /* skip-- */
+ iap_remotebtn = BUTTON_RC_LEFT;
+ iap_repeatbtn = 2;
+ break;
+ case 0x05: /* ffwd */
+ iap_remotebtn = BUTTON_RC_RIGHT;
+ break;
+ case 0x06: /* frwd */
+ iap_remotebtn = BUTTON_RC_LEFT;
+ break;
+ case 0x07: /* end ffwd/frwd */
+ iap_remotebtn = BUTTON_NONE;
+ break;
+ }
+ /* respond with cmd ok packet */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x002A: /* GetTrackArtworkTimes */
+ /* The following is the description for the Apple Firmware
+ *
+ * The device sends this command to the iPod to request the list of
+ * artwork time locations for a track. A 4-byte track Index
+ * specifies which track from the Playback Engine is to be selected.
+ * A 2-byte formatID indicates which type of artwork is desired.
+ * The 2-byte artworkIndex specifies at which index to begin
+ * searching for artwork. A value of 0 indicates that the iPod
+ * should start with the first available artwork.
+ * The 2-byte artworkCount specifies the maximum number of times
+ * (artwork locations) to be returned. A value of -1 (0xFFFF)
+ * indicates that there is no preferred limit. Note that podcasts
+ * may have a large number of associated images.
+ *
+ * Byte Value Comment
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x0D Length of packet
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x2A Command ID (bits 7:0)
+ * 6 0xNN trackIndex(31:24)
+ * 7 0xNN trackIndex(23:16)
+ * 8 0xNN trackIndex (15:8)
+ * 9 0xNN trackIndex (7:0)
+ * 10 0xNN formatID (15:8)
+ * 11 0xNN formatID (7:0)
+ * 12 0xNN artworkIndex (15:8)
+ * 13 0xNN artworkIndex (7:0)
+ * 14 0xNN artworkCount (15:8)
+ * 15 0xNN artworkCount (7:0)
+ * 16 0xNN Checksum
+ *
+ */
+ {
+ unsigned char data[] = {0x04, 0x00, 0x2B,
+ 0x00, 0x00, 0x00, 0x00};
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x002B: /* ReturnTrackArtworkTimes. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * The iPod sends this command to the device to return the list of
+ * artwork times for a given track. The iPod returns zero or more
+ * 4-byte times, one for each piece of artwork associated with the
+ * track and format specified by GetTrackArtworkTimes.
+ * The number of records returned will be no greater than the number
+ * specified in the GetTrackArtworkTimes command. It may however, be
+ * less than requested. This can happen if there are fewer pieces of
+ * artwork available than were requested, or if the iPod is unable
+ * to place the full number in a single packet. Check the number of
+ * records returned against the results of
+ * RetIndexedPlayingTrackInfo with infoType 7 to ensure that all
+ * artwork has been received.
+ *
+ * Byte Value Comment
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Length of packet
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x2B Command ID (bits 7:0)
+ * 6 0xNN time offset from track start in ms (31:24)
+ * 7 0xNN time offset from track start in ms (23:16)
+ * 8 0xNN time offset from track start in ms (15:8)
+ * 9 0xNN time offset from track start in ms (7:0)
+ * Preceding 4 bytes may be repeated NN times
+ * NN 0xNN Checksum
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x002C: /* GetShuffle */
+ {
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the current state of the iPod shuffle setting. The iPod
+ * responds with the Command0x002D: ReturnShuffle telegram.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x2C Command ID (bits 7:0)
+ * 6 0xCD Telegram payload checksum byte
+ *
+ */
+ unsigned char data[] = {0x04, 0x00, 0x2D,
+ 0x00};
+ data[3] = global_settings.playlist_shuffle ? 1 : 0;
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x002D: /* ReturnShuffle. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the current state of the shuffle setting. The iPod sends
+ * this telegram in response to the Command 0x002C: GetShuffle
+ * telegram from the device.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x2D Command ID (bits 7:0)
+ * 6 0xNN Shuffle mode. See Below.
+ * 7 0xNN Telegram payload checksum byte
+ *
+ * Possible values of the shufflemode.
+ * Value Meaning
+ * 0x00 Shuffle off
+ * 0x01 Shuffle tracks
+ * 0x02 Shuffle albums
+ * 0x03 – 0xFF Reserved
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x002E: /* SetShuffle */
+ {
+ /* The following is the description for the Apple Firmware
+ *
+ * Sets the iPod shuffle mode. The iPod shuffle modes are listed
+ * below. In response, the iPod sends an ACK telegram with the
+ * command status.
+ * This telegram has an optional byte, byte 0x07, called the
+ * RestoreonExit byte. This byte can be used to restore the
+ * original shuffle setting in use when the accessory was attached
+ * to the iPod. A non zero value restores the original shuffle
+ * setting of the iPod when the accessory is detached. If this byte
+ * is zero, the shuffle setting set by the accessory overwrites the
+ * original setting and persists after the accessory is detached
+ * from the iPod.
+ * Accessory engineers should note that the shuffle mode affects
+ * items only in the playback engine. The shuffle setting does not
+ * affect the order of tracks in the database engine, so calling
+ * Command 0x001A: RetrieveCategorizedDatabaseRecords on a database
+ * selection with the shuffle mode set returns a list of unshuffled
+ * tracks. To get the shuffled playlist, an accessory must query the
+ * playback engine by calling Command 0x0020
+ * GetIndexedPlayingTrackTitle.
+ * Shuffling tracks does not affect the track index, just the track
+ * at that index. If an unshuffled track at playback index 1 is
+ * shuffled, a new track is placed into index 1. The playback
+ * indexes themselves are not shuffled.
+ * When shuffle mode is enabled, tracks that are marked 'skip when
+ * shuffling' are filtered from the database selection. This affects
+ * all audiobooks and all tracks that the user has marked in iTunes.
+ * It also affects all podcasts unless their default 'skip when
+ * shuffling' markings have been deliberately removed. To apply the
+ * filter to the playback engine, the accessory should send
+ * Command 0x0017: SelectDBRecord or
+ * Command 0x0028: PlayCurrentSelection after enabling shuffle mode.
+ *
+ * Note: Accessory developers are encouraged to always use the
+ * Restore on Exit byte with a nonzero value to restore any settings
+ * modified by the accessory upon detach.
+ *
+ * SetShuffle telegram with Restore on Exit byte
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x05 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x2E Command ID (bits 7:0)
+ * 6 0xNN New shuffle mode. See above .
+ * 7 0xNN Restore on Exit byte. If 1, the orig setting is
+ * restored on detach; if 0, the newsetting persists
+ * after accessory detach.
+ * 8 0xNN Telegram payload checksum byte
+ *
+ * SetShuffle setting persistent after the accessory detach.
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x2E Command ID (bits 7:0)
+ * 6 0xNN New shuffle mode. See above.
+ * 7 0xNN Telegram payload checksum byte
+ *
+ */
+ if(buf[3] && !global_settings.playlist_shuffle)
+ {
+ global_settings.playlist_shuffle = 1;
+ settings_save();
+ if (audio_status() & AUDIO_STATUS_PLAY)
+ playlist_randomise(NULL, current_tick, true);
+ }
+ else if(!buf[3] && global_settings.playlist_shuffle)
+ {
+ global_settings.playlist_shuffle = 0;
+ settings_save();
+ if (audio_status() & AUDIO_STATUS_PLAY)
+ playlist_sort(NULL, true);
+ }
+
+ /* respond with cmd ok packet */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x002F: /* GetRepeat */
+ {
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the track repeat state of the iPod. In response, the
+ * iPod sends a Command 0x0030: ReturnRepeat telegram
+ * to the device.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x2F Command ID (bits 7:0)
+ * 6 0xCA Telegram payload checksum byte
+ *
+ */
+ unsigned char data[] = {0x04, 0x00, 0x30, 0x00};
+ if(global_settings.repeat_mode == REPEAT_OFF)
+ data[3] = 0;
+ else if(global_settings.repeat_mode == REPEAT_ONE)
+ data[3] = 1;
+ else
+ data[3] = 2;
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x0030: /* ReturnRepeat. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the current iPod track repeat state to the device.
+ * The iPod sends this telegram in response to the Command
+ * 0x002F:GetRepeat command.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x30 Command ID (bits 7:0)
+ * 6 0xNN Repeat state. See Below.
+ * 7 0xNN Telegram payload checksum byte
+ *
+ * Repeat state values
+ * Value Meaning
+ * 0x00 Repeat off
+ * 0x01 Repeat one track
+ * 0x02 Repeat all tracks
+ * 0x03 - 0xFF Reserved
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0031: /* SetRepeat */
+ {
+ /* The following is the description for the Apple Firmware
+ *
+ * Sets the repeat state of the iPod. The iPod track repeat modes
+ * are listed above. In response, the iPod sends an ACK telegram
+ * with the command status.
+ *
+ * This telegram has an optional byte, byte 0x07, called the
+ * RestoreonExitbyte. This byte can be used to restore the original
+ * repeat setting in use when the accessory was attached to the
+ * iPod. A nonzero value restores the original repeat setting of
+ * the iPod when the accessory is detached. If this byte is zero,
+ * the repeat setting set by the accessory overwrites the original
+ * setting and persists after the accessory is detached from the
+ * iPod.
+ *
+ * Note: Accessory developers are encouraged to always use the
+ * Restore on Exit byte with a nonzero value to restore any
+ * settings modified by the accessory upon detach.
+ *
+ * SetRepeat telegram with Restore on Exit byte
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x05 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x31 Command ID (bits 7:0)
+ * 6 0xNN New repeat state. See above.
+ * 7 0xNN Restore on Exit byte. If 1, the original setting is
+ * restored on detach; if 0, the newsetting persists
+ * after accessory detach.
+ * 8 0xNN Telegram payload checksum byte
+ *
+ * SetRepeat setting persistent after the accessory detach.
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x31 Command ID (bits 7:0)
+ * 6 0xNN New repeat state. See above.
+ * 7 0xNN Telegram payload checksum byte
+ *
+ */
+ int oldmode = global_settings.repeat_mode;
+ if (buf[3] == 0)
+ global_settings.repeat_mode = REPEAT_OFF;
+ else if (buf[3] == 1)
+ global_settings.repeat_mode = REPEAT_ONE;
+ else if (buf[3] == 2)
+ global_settings.repeat_mode = REPEAT_ALL;
+
+ if (oldmode != global_settings.repeat_mode)
+ {
+ settings_save();
+ if (audio_status() & AUDIO_STATUS_PLAY)
+ audio_flush_and_reload_tracks();
+ }
+ /* respond with cmd ok packet */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x0032: /* SetDisplayImage */
+ {
+ /* The following is the description for the Apple Firmware
+ * This sets a bitmap image
+ * that is displayed on the iPod display when connected to the
+ * device. It replaces the default checkmark bitmap image that is
+ * displayed when iPod is connected to an external device
+ *
+ * Sets a bitmap image that is shown on the iPod display when it is
+ * connected to the device. The intent is to allow third party
+ * branding when the iPod is communicating with an external device.
+ * An image downloaded using this mechanism replaces the default
+ * checkmark bitmap image that is displayed when iPod is connected
+ * to an external device. The new bitmap is retained in RAM for as
+ * long as the iPod remains powered. After a system reset or deep
+ * sleep state, the new bitmap is lost and the checkmark image
+ * restored as the default when the iPod next enters Extended
+ * Interface mode after power-up.
+ * Before setting a monochrome display image, the device can send
+ * the Command 0x0033: GetMonoDisplayImageLimits telegram to obtain
+ * the current iPod display width, height and pixel format.The
+ * monochrome display information returned in the Command 0x0034:
+ * ReturnMonoDisplayImageLimits telegram can be useful to the
+ * device in deciding which type of display image format is suitable
+ * for downloading to the iPod.
+ * On iPods withcolor displays, devices can send the Command 0x0039:
+ * GetColorDisplayImageLimits telegram to obtain the iPod color
+ * display width,height,and pixel formats. The color display
+ * information is returned in the Command 0x003A:
+ * ReturnColorDisplayImageLimits” telegram.
+ * To set a display image, the device must successfully send
+ * SetDisplayImage descriptor and data telegrams to the iPod. The
+ * SetDisplayImage descriptor telegram (telegram index 0x0000) must
+ * be sent first, as it gives the iPod a description of the image
+ * to be downloaded. This telegram is shown in below. The image
+ * descriptor telegram includes image pixel format, image width and
+ * height, and display row size (stride) in bytes. Optionally, the
+ * descriptor telegram may also contain the beginning data of the
+ * display image, as long as it remains within the maximum length
+ * limits of the telegram.
+ * Following the descriptor telegram, the SetDisplayImage data
+ * telegrams (telegram index 0x0001 - 0xNNNN) should be sent using
+ * sequential telegram indices until the entire image has been sent
+ * to the iPod.
+ *
+ * Note: The SetDisplayImage telegram payload length is limited to
+ * 500 bytes. This telegram length limit and the size and format of
+ * the display image generally determine the minimum number of
+ * telegrams that are required to set a display image.
+ *
+ * Note: Starting with the second generation iPod nano with version
+ * 1.1.2 firmware, the use of the SetDisplayImage command is
+ * limited to once every 15 seconds over USB transport. The iPod
+ * classic and iPod 3G nano apply this restriction to both USB and
+ * UART transports. Calls made to SetDisplayImage more frequently
+ * than every 15 seconds will return a successful ACK command, but
+ * the bitmap will not be displayed on the iPod’s screen. Hence use
+ * of the SetDisplayImage command should be limited to drawing one
+ * bitmap image per accessory connect. The iPod touch will accept
+ * the SetDisplayImage command but will not draw it on the iPod’s
+ * screen.
+ *
+ * Below shows the format of a descriptor telegram. This example
+ * assumes the display image descriptor data exceeds the small
+ * telegram payload capacity; a large telegram format is shown.
+ *
+ * SetDisplayImage descriptor telegram (telegram index = 0x0000)
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x00 Telegram payload marker (large format)
+ * 3 0xNN Large telegram payload length (bits 15:8)
+ * 4 0xNN Large telegram payload length (bits 7:0)
+ * 5 0x04 Lingo ID: Extended Interface lingo
+ * 6 0x00 Command ID (bits 15:8)
+ * 7 0x32 Command ID (bits 7:0)
+ * 8 0x00 Descriptor telegram index (bits 15:8). These fields
+ * uniquely identify each packet in the SetDisplayImage
+ * transaction. The first telegram is the Descriptor
+ * telegram and always starts with an index of 0x0000.
+ * 9 0x00 Descriptor telegram index (bits 7:0)
+ * 10 0xNN Display pixel format code. See Below.
+ * 11 0xNN Imagewidth in pixels (bits 15:8). The number of
+ * pixels, from left to right, per row.
+ * 12 0xNN Image width in pixels (bits 7:0)
+ * 13 0xNN Image height in pixels (bits 15:8). The number of
+ * rows, from top to bottom, in the image.
+ * 14 0xNN Image height in pixels (bits 7:0)
+ * 15 0xNN Row size (stride) in bytes (bits 31:24). The number of
+ * bytes representing one row of pixels. Each row is
+ * zero-padded to end on a 32-bit boundary. The
+ * cumulative size, in bytes, of the image data,
+ * transferred across all telegrams in this transaction
+ * is effectively (Row Size * Image Height).
+ * 16 0xNN Row size (stride) in bytes (bits 23:16)
+ * 17 0xNN Row size (stride) in bytes (bits 15:8)
+ * 18 0xNN Row size (stride) in bytes (bits 7:0)
+ * 19–N 0xNN Display image pixel data
+ * NN 0xNN Telegram payload checksum byte
+ *
+ * SetDisplayImage data telegram (telegram index = 0x0001 - 0xNNNN)
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x00 Telegram payload marker (large format)
+ * 3 0xNN Large telegram payload length (bits 15:8)
+ * 4 0xNN Large telegram payload length (bits 7:0)
+ * 5 0x04 Lingo ID: Extended Interface lingo
+ * 6 0x00 Command ID (bits 15:8)
+ * 7 0x32 Command ID (bits 7:0)
+ * 8 0xNN Descriptor telegram index (bits 15:8). These fields
+ * uniquely identify each packet in the SetDisplayImage
+ * transaction. The first telegram is the descriptor
+ * telegram, shown in Table 6-68 (page 97). The
+ * remaining n-1 telegrams are simply data telegrams,
+ * where n is determined by the size of the image.
+ * 9 0xNN Descriptor telegram index (bits 7:0)
+ * 10–N 0xNN Display image pixel data
+ * NN 0xNN Telegram payload checksum byte
+ *
+ * Note: A known issue causes SetDisplayImage data telegram
+ * lengths less than 11 bytes to return a bad parameter error (0x04)
+ * ACK on 3G iPods.
+ *
+ * The iPod display is oriented as a rectangular grid of pixels. In
+ * the horizontal direction (x-coordinate), the pixel columns are
+ * numbered, left to right, from 0 to Cmax. In the vertical
+ * direction (y-coordinate), the pixel rows are numbered, top to
+ * bottom, from 0 to Rmax. Therefore, an (x,y) coordinate of (0,0)
+ * represents the upper-leftmost pixel on the display and
+ * (Cmax,Rmax) represents the lower-rightmost pixel on the display.
+ * A portion of the iPod display pixel layout is shown below, where
+ * x is the column number, y is the row number, and (Cmax,Rmax)
+ * represents the maximum row and column numbers.
+ *
+ * Pixel layout
+ * x
+ * y 0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 - Cmax,0
+ * 0,1 1,1 2,1 3,1 4,1 5,1 6,1 7,1 - Cmax,1
+ * 0,2 1,2 2,2 3,2 4,2 5,2 6,2 7,2 - Cmax,2
+ * 0,3 1,3 2,3 3,3 4,3 5,3 6,3 7,3 - Cmax,3
+ * 0,4 1,4 2,4 3,4 4,4 5,4 6,4 7,4 - Cmax,4
+ * 0,5 1,5 2,5 3,5 4,5 5,5 6,5 7,5 - Cmax,5
+ * 0,6 1,6 2,6 3,6 4,6 5,6 6,6 7,6 - Cmax,6
+ * 0,7 1,7 2,7 3,7 4,7 5,7 6,7 7,7 - Cmax,7
+ * " " " " " " " " " "
+ * 0, 1, 2, 3, 4, 5, 6, 7, - Cmax,
+ * RmaxRmaxRmaxRmaxRmaxRmaxRmaxRmax Rmax
+ *
+ * Display pixel format codes
+ * Display pixel format Code Protocol version
+ * Reserved 0x00 N/A
+ * Monochrome, 2 bits per pixel 0x01 1.01
+ * RGB 565 color, little-endian, 16 bpp 0x02 1.09
+ * RGB 565 color, big-endian, 16 bpp 0x03 1.09
+ * Reserved 0x04-0xFF N/A
+ *
+ * iPods with color screens support all three image formats. All
+ * other iPods support only display pixel format 0x01 (monochrome,
+ * 2 bpp).
+ *
+ * Display Pixel Format 0x01
+ * Display pixel format 0x01 (monochrome, 2 bits per pixel) is the
+ * pixel format supported by all iPods. Each pixel consists of 2
+ * bits that control the pixel intensity. The pixel intensities and
+ * associated binary codes are listed below.
+ *
+ * 2 bpp monochrome pixel intensities
+ * Pixel Intensity Binary Code
+ * Pixel off (not visible) 00b
+ * Pixel on 25% (light grey) 01b
+ * Pixel on 50% (dark grey) 10b
+ * Pixel on 100% (black) 11b
+ *
+ * Each byte of image data contains four packed pixels. The pixel
+ * ordering within bytes and the byte ordering within 32 bits is
+ * shown below.
+ *
+ * Image Data Byte 0x0000
+ * Pixel0 Pixel1 Pixel2 Pixel3
+ * 7 6 5 4 3 2 1 0
+ *
+ * Image Data Byte 0x0001
+ * Pixel4 Pixel5 Pixel6 Pixel7
+ * 7 6 5 4 3 2 1 0
+ *
+ * Image Data Byte 0x0002
+ * Pixel8 Pixel9 Pixel10 Pixel11
+ * 7 6 5 4 3 2 1 0
+ *
+ * Image Data Byte 0x0003
+ * Pixel12 Pixel13 Pixel14 Pixel15
+ * 7 6 5 4 3 2 1 0
+ *
+ * Image Data Byte 0xNNNN
+ * PixelN PixelN+1 PixelN+2 PixelN+3
+ * 7 6 5 4 3 2 1 0
+ *
+ * Display Pixel Formats 0x02 and 0x03
+ * Display pixel format 0x02 (RGB 565, little-endian) and display
+ * pixel format 0x03 (RGB 565, big-endian) are available for use
+ * in all iPods with color screens. Each pixel consists of 16 bits
+ * that control the pixel intensity for the colors red, green, and
+ * blue.
+ * It takes two bytes to represent a single pixel. Red is
+ * represented by 5 bits, green is represented by 6 bits, and blue
+ * by the final 5 bits. A 32-bit sequence represents 2 pixels. The
+ * pixel ordering within bytes and the byte ordering within 32 bits
+ * for display format 0x02 (RGB 565, little-endian) is shown below.
+ *
+ * Image Data Byte 0x0000
+ * Pixel 0, lower 3 bits of green Pixel 0, all 5 bits of blue
+ * 7 6 5 4 3 2 1 0
+ * Image Data Byte 0x0001
+ * Pixel 0, all 5 bits of red Pixel 0,upper 3 bits of green
+ * 7 6 5 4 3 2 1 0
+ *
+ * Image Data Byte 0x0002
+ * Pixel 1, lower 3 bits of green Pixel 1, all 5 bits of blue
+ * 7 6 5 4 3 2 1 0
+ *
+ * Image Data Byte 0x0003
+ * Pixel 1, all 5 bits of red Pixel 1, upper 3 bits of green
+ * 7 6 5 4 3 2 1 0
+ *
+ * The format for display pixel format 0x03 (RGB 565, big-endian, 16
+ * bpp) is almost identical, with the exception that bytes 0 and 1
+ * are swapped and bytes 2 and 3 are swapped.
+ *
+ */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x0033: /* GetMonoDisplayImageLimits */
+
+ {
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the limiting characteristics of the monochrome image
+ * that can be sent to the iPod for display while it is connected
+ * to the device. It can be used to determine the display pixel
+ * format and maximum width and height of a monochrome image to be
+ * set using the Command 0x0032: SetDisplayImage telegram. In
+ * response, the iPod sends a Command 0x0034:
+ * ReturnMonoDisplayImageLimits telegram to the device with the
+ * requested display information. The GetMonoDisplayImageLimits
+ * command is supported by iPods with either monochrome or color
+ * displays. To obtain color display image limits, use Command
+ * 0x0039: GetColorDisplayImageLimits.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x33 Command ID (bits 7:0)
+ * 6 0xC6 Telegram payload checksum byte
+ *
+ */
+ unsigned char data[] = {0x04, 0x00, 0x34,
+ LCD_WIDTH >> 8, LCD_WIDTH & 0xff,
+ LCD_HEIGHT >> 8, LCD_HEIGHT & 0xff,
+ 0x01};
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x0034: /* ReturnMonoDisplayImageLimits. See Above*/
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the limiting characteristics of the monochrome image that
+ * can be sent to the iPod for display while it is connected to the
+ * device. The iPod sends this telegram in response to the Command
+ * 0x0033: GetMonoDisplayImageLimits telegram. Monochrome display
+ * characteristics include maximum image width and height and the
+ * display pixel format.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x34 Command ID (bits 7:0)
+ * 6 0xNN Maximum image width in pixels (bits 15:8)
+ * 7 0xNN Maximum image width in pixels (bits 7:0)
+ * 8 0xNN Maximum image height in pixels (bits 15:8)
+ * 9 0xNN Maximumimage height in pixels (bits 7:0)
+ * 10 0xNN Display pixel format (see Table 6-70 (page 99)).
+ * 11 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0035: /* GetNumPlayingTracks */
+ {
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the number of tracks in the list of tracks queued to
+ * play on the iPod. In response, the iPod sends a Command 0x0036:
+ * ReturnNumPlayingTracks telegram with the count of tracks queued
+ * to play.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x35 Command ID (bits 7:0)
+ * 6 0xC4 Telegram payload checksum byte
+ *
+ */
+ unsigned char data[] = {0x04, 0x00, 0x36,
+ 0x00, 0x00, 0x00, 0x00};
+ unsigned long playlist_amt = playlist_amount();
+ put_u32(&data[3], playlist_amt);
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x0036: /* ReturnNumPlayingTracks. See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the number of tracks in the actual list of tracks queued
+ * to play, including the currently playing track (if any). The
+ * iPod sends this telegram in response to the Command 0x0035:
+ * GetNumPlayingTracks telegram.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x36 Command ID (bits 7:0)
+ * 6 0xNN Number of tracks playing(bits 31:24)
+ * 7 0xNN Number of tracks playing(bits 23:16)
+ * 8 0xNN Number of tracks playing (bits 15:8)
+ * 9 0xNN Number of tracks playing (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x0037: /* SetCurrentPlayingTrack */
+ /* The following is the description for the Apple Firmware
+ *
+ * Sets the index of the track to play in the Now Playing playlist
+ * on the iPod. The index that is specified here is obtained by
+ * sending the Command 0x0035: GetNumPlayingTracks and Command
+ * 0x001E: GetCurrentPlayingTrackIndex telegrams to obtain the
+ * number of playing tracks and the current playing track index,
+ * respectively. In response, the iPod sends an ACK telegram
+ * indicating the status of the command.
+ *
+ * Note: The behavior of this command has changed. Before the
+ * 2G nano, if this command was sent with the current playing track
+ * index the iPod would pause playback momentarily and then resume.
+ * Starting with the 2G nano, the iPod restarts playback of the
+ * current track from the beginning. Older iPods will not be
+ * updated to the new behavior.
+ *
+ * Note: This command is usable only when the iPod is in a playing
+ * or paused state. If the iPod is stopped, this command fails.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x07 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x37 Command ID (bits 7:0)
+ * 6 0xNN New current playing track index (bits 31:24)
+ * 7 0xNN New current playing track index (bits 23:16)
+ * 8 0xNN New current playing track index (bits 15:8)
+ * 9 0xNN New current playing track index (bits 7:0)
+ * 10 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE));
+ long tracknum = get_u32(&buf[3]);
+
+ audio_pause();
+ audio_skip(tracknum - playlist_next(0));
+ if (!paused)
+ audio_resume();
+
+ /* respond with cmd ok packet */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x0038: /* SelectSortDBRecord */
+ /* The following is the description for the Apple Firmware
+ *
+ * Selects one or more records in the iPod database, based on a
+ * category-relative index. For example, selecting category 2
+ * (Artist), record index 1, and sort order 3 (Album) results in a
+ * list of selected tracks (records) from the second artist in the
+ * artist list, sorted by album name. Selections are additive and
+ * limited by the category hierarchy. Subsequent selections are
+ * made based on the subset of records resulting from previous
+ * selections and not from the entire database. The database
+ * category types are shown above. The sort order options and codes
+ * are shown below.
+ *
+ * SelectSortDBRecord telegram
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x09 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x38 Command ID (bits 7:0)
+ * 6 0xNN Database category type.
+ * 7 0xNN Category record index (bits 31:24)
+ * 8 0xNN Category record index (bits 23:16)
+ * 9 0xNN Category record index (bits 15:8)
+ * 10 0xNN Category record index (bits 7:0)
+ * 11 0xNN Database sort type.
+ * 12 0xNN Telegram payload checksum byte
+ *
+ * Database sort order options
+ * Sort Order Code Protocol version
+ * Sort by genre 0x00 1.00
+ * Sort by artist 0x01 1.00
+ * Sort by composer 0x02 1.00
+ * Sort by album 0x03 1.00
+ * Sort by name 0x04 1.00
+ * Sort by playlist 0x05 1.00
+ * Sort by release date 0x06 1.08
+ * Reserved 0x07 - 0xFE N/A
+ * Use default sort type 0xFF 1.00
+ *
+ * The default order of song and audiobook tracks on the iPod is
+ * alphabetical by artist, then alphabetical by that artist's
+ * albums, then ordered according to the order of the tracks on the
+ * album.
+ * For podcasts, the default order of episode tracks is reverse
+ * chronological. That is, the newest ones are first,then
+ * alphabetical by podcast name.
+ * The SelectSortDBRecord command can be used to sort all the song
+ * and audiobook tracks on the iPod alphabetically as follows:
+ * 1. Command 0x0016: ResetDBSelection
+ * 2. Command 0x0018: GetNumberCategorizedDBRecords for the Playlist
+ * category.
+ * 3. SelectSortDBRecord based on the Playlist category, using a
+ * record index of 0 to select the All Tracks
+ * playlist and the sort by name (0x04) sort
+ * order.
+ * 4. GetNumberCategorizedDBRecords for the Track category.
+ * 5. Command 0x001A :RetrieveCategorizedDatabaseRecords based on
+ * the Track category, using a start index of 0
+ * and an end index of the number of records
+ * returned by the call to
+ * GetNumberCategorizedDBRecords in step 4.
+ *
+ * The sort order of artist names ignores certain articles such
+ * that the artist “The Doors” is sorted under the letter ‘D’ and
+ * not ‘T’; this matches the behavior of iTunes. The sort order is
+ * different depending on the language setting used in the iPod.
+ * The list of ignored articles may change in the future without
+ * notice.
+ * The SelectDBRecord command may also be used to select a database
+ * record with the default sort order.
+ *
+ * Note: The sort order field is ignored for the Audiobook category.
+ * Audiobooks are automatically sorted by track title. The sort
+ * order for podcast tracks defaults to release date, with the
+ * newest track coming first.
+ *
+ * Selects one or more records in the iPod database, based on a
+ * category-relative index. This appears to be hardcoded hierarchy
+ * decided by Apple that the external devices follow.
+ * This is as follows for all except podcasts,
+ *
+ * All (highest level),
+ * Playlist,
+ * Genre or Media Kind,
+ * Artist or Composer,
+ * Album,
+ * Track or Audiobook (lowest)
+ *
+ * for Podcasts, the order is
+ *
+ * All (highest),
+ * Podcast,
+ * Episode
+ * Track (lowest)
+ *
+ * Categories are
+ *
+ * 0x00 Reserved
+ * 0x01 Playlist
+ * 0x02 Artist
+ * 0x03 Album
+ * 0x04 Genre
+ * 0x05 Track
+ * 0x06 Composer
+ * 0x07 Audiobook
+ * 0x08 Podcast
+ * 0x09 - 0xff Reserved
+ *
+ * Sort Order optiona and codes are
+ *
+ * 0x00 Sort by Genre
+ * 0x01 Sort by Artist
+ * 0x02 Sort by Composer
+ * 0x03 Sort by Album
+ * 0x04 Sort by Name (Song Title)
+ * 0x05 Sort by Playlist
+ * 0x06 Sort by Release Date
+ * 0x07 - 0xfe Reserved
+ * 0xff Use default Sort Type
+ *
+ * Packet format (offset in data[]: Description)
+ * 0x00: Lingo ID: Extended Interface Protocol Lingo, always 0x04
+ * 0x01-0x02: Command, always 0x0038
+ * 0x03: Database Category Type
+ * 0x04-0x07: Category Record Index
+ * 0x08 Database Sort Type
+ *
+ * On Rockbox, if the recordtype is playlist, we load the selected
+ * playlist and start playing from the first track.
+ * If the recordtype is track, we play that track from the current
+ * playlist.
+ * On anything else we just play the current track from the current
+ * playlist.
+ * cur_dbrecord[0] is the recordtype
+ * cur_dbrecord[1-4] is the u32 of the record number requested
+ * which might be a playlist or a track number depending on
+ * the value of cur_dbrecord[0]
+ */
+ {
+ memcpy(cur_dbrecord, buf + 3, 5);
+
+ int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE));
+ unsigned int number_of_playlists = nbr_total_playlists();
+ uint32_t index;
+ uint32_t trackcount;
+ index = get_u32(&cur_dbrecord[1]);
+ trackcount = playlist_amount();
+ if ((cur_dbrecord[0] == 0x05) && (index > trackcount))
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ if ((cur_dbrecord[0] == 0x01) && (index > (number_of_playlists + 1)))
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ switch (cur_dbrecord[0])
+ {
+ case 0x01: /* Playlist*/
+ {
+ if (index != 0x00) /* 0x00 is the On-The-Go Playlist and
+ we do nothing with it */
+ {
+ audio_pause();
+ audio_skip(-iap_get_trackindex());
+ playlist_sort(NULL, true);
+ last_selected_playlist = index;
+ seek_to_playlist(last_selected_playlist);
+ }
+ break;
+ }
+ case 0x02: /* Artist Do Nothing */
+ case 0x03: /* Album Do Nothing */
+ case 0x04: /* Genre Do Nothing */
+ case 0x06: /* Composer Do Nothing */
+ break;
+ case 0x05: /* Track*/
+ {
+ audio_pause();
+ audio_skip(-iap_get_trackindex());
+ playlist_sort(NULL, true);
+ audio_skip(index - playlist_next(0));
+ break;
+ }
+ }
+ if (!paused)
+ audio_resume();
+ /* respond with cmd ok packet */
+ cmd_ok(cmd);
+ break;
+ }
+ case 0x0039: /* GetColorDisplayImageLimits */
+ /* The following is the description for the Apple Firmware
+ *
+ * Requests the limiting characteristics of the color image that
+ * can be sent to the iPod for display while it is connected to
+ * the device. It can be used to determine the display pixel format
+ * and maximum width and height of a color image to be set using
+ * the Command 0x0032: SetDisplayImage telegram. In response, the
+ * iPod sends a Command 0x003A: ReturnColorDisplayImageLimits
+ * telegram to the device with the requested display information.
+ * This command is supported only by iPods with color displays.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x03 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x39 Command ID (bits 7:0)
+ * 6 0xC0 Telegram payload checksum byte
+ *
+ */
+ {
+ /* Set the same as the ReturnMonoDisplayImageLimits */
+ unsigned char data[] = {0x04, 0x00, 0x3A,
+ LCD_WIDTH >> 8, LCD_WIDTH & 0xff,
+ LCD_HEIGHT >> 8, LCD_HEIGHT & 0xff,
+ 0x01};
+ iap_send_pkt(data, sizeof(data));
+ break;
+ }
+ case 0x003A: /* ReturnColorDisplayImageLimits See Above */
+ /* The following is the description for the Apple Firmware
+ *
+ * Returns the limiting characteristics of the color image that can
+ * be sent to the iPod for display while it is connected to the
+ * device. The iPod sends this telegram in response to the Command
+ * 0x0039: GetColorDisplayImageLimits telegram. Display
+ * characteristics include maximum image width and height and the
+ * display pixel format.
+ *
+ * Note: If the iPod supports multiple display image formats, a five
+ * byte block of additional image width, height, and pixel format
+ * information is appended to the payload for each supported display
+ * format. The list of supported color display image formats
+ * returned by the iPod may change in future software versions.
+ * Devices must be able to parse a variable length list of supported
+ * color display formats to search for compatible formats.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0xNN Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x3A Command ID (bits 7:0)
+ * 6 0xNN Maximum image width in pixels (bits 15:8)
+ * 7 0xNN Maximum image width in pixels (bits 7:0)
+ * 8 0xNN Maximum image height in pixels (bits 15:8)
+ * 9 0xNN Maximum image height in pixels (bits 7:0)
+ * 10 0xNN Display pixel format (see Table 6-70 (page 99)).
+ * 11-N 0xNN Optional display image width, height, and pixel format
+ * for the second to nth supported display formats,
+ * if present.
+ * NN 0xNN Telegram payload checksum byte
+ *
+ */
+ {
+ /* We should NEVER receive this command so ERROR if we do */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ case 0x003B: /* ResetDBSelectionHierarchy */
+ {
+ /* The following is the description for the Apple Firmware
+ *
+ * This command carries a single byte in its payload (byte 6). A
+ * hierarchy selection value of 0x01 means that the accessory wants
+ * to navigate the music hierarchy; a hierarchy selection value of
+ * 0x02 means that the accessory wants to navigate the video
+ * hierarchy.
+ *
+ * Byte Value Meaning
+ * 0 0xFF Sync byte (required only for UART serial)
+ * 1 0x55 Start of telegram
+ * 2 0x04 Telegram payload length
+ * 3 0x04 Lingo ID: Extended Interface lingo
+ * 4 0x00 Command ID (bits 15:8)
+ * 5 0x3B Command ID (bits 7:0)
+ * 6 0x01 or 0x02 Hierarchy selection
+ * 7 0xNN Telegram payload checksum byte
+ *
+ * Note: The iPod will return an error if a device attempts to
+ * enable an unsupported hierarchy, such as a video hierarchy on an
+ * iPod model that does not support video.
+ */
+ dbrecordcount = 0;
+ cur_dbrecord[0] = 0;
+ put_u32(&cur_dbrecord[1],0);
+ switch (buf[3])
+ {
+ case 0x01: /* Music */
+ {
+ cmd_ok(cmd);
+ break;
+ }
+ default: /* Anything else */
+ {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ }
+ }
+ default:
+ {
+#ifdef LOGF_ENABLE
+ logf("iap: Unsupported Mode04 Command");
+#endif
+ /* The default response is IAP_ACK_BAD_PARAM */
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ break;
+ }
+ }
+}