summaryrefslogtreecommitdiffstats
path: root/apps/iap/iap-lingo2.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-lingo2.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-lingo2.c')
-rw-r--r--apps/iap/iap-lingo2.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/apps/iap/iap-lingo2.c b/apps/iap/iap-lingo2.c
new file mode 100644
index 0000000000..4fbf730192
--- /dev/null
+++ b/apps/iap/iap-lingo2.c
@@ -0,0 +1,278 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+/* Lingo 0x02, Simple Remote Lingo
+ *
+ * TODO:
+ * - Fix cmd 0x00 handling, there has to be a more elegant way of doing
+ * this
+ */
+
+#include "iap-core.h"
+#include "iap-lingo.h"
+#include "system.h"
+#include "button.h"
+#include "audio.h"
+#include "settings.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)
+
+static void cmd_ack(const unsigned char cmd, const unsigned char status)
+{
+ IAP_TX_INIT(0x02, 0x01);
+ IAP_TX_PUT(status);
+ IAP_TX_PUT(cmd);
+
+ iap_send_tx();
+}
+
+#define cmd_ok(cmd) cmd_ack((cmd), IAP_ACK_OK)
+
+void iap_handlepkt_mode2(const unsigned int len, const unsigned char *buf)
+{
+ unsigned int cmd = buf[1];
+
+ /* We expect at least three bytes in the buffer, one for the
+ * lingo, one for the command, and one for the first button
+ * state bits.
+ */
+ CHECKLEN(3);
+
+ /* Lingo 0x02 must have been negotiated */
+ if (!DEVICE_LINGO_SUPPORTED(0x02)) {
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+ return;
+ }
+
+ switch (cmd)
+ {
+ /* ContextButtonStatus (0x00)
+ *
+ * Transmit button events from the device to the iPod
+ *
+ * Packet format (offset in buf[]: Description)
+ * 0x00: Lingo ID: Simple Remote Lingo, always 0x02
+ * 0x01: Command, always 0x00
+ * 0x02: Button states 0:7
+ * 0x03: Button states 8:15 (optional)
+ * 0x04: Button states 16:23 (optional)
+ * 0x05: Button states 24:31 (optional)
+ *
+ * Returns: (none)
+ */
+ case 0x00:
+ {
+ iap_remotebtn = BUTTON_NONE;
+ iap_timeoutbtn = 0;
+
+ if(buf[2] != 0)
+ {
+ if(buf[2] & 1)
+ REMOTE_BUTTON(BUTTON_RC_PLAY);
+ if(buf[2] & 2)
+ REMOTE_BUTTON(BUTTON_RC_VOL_UP);
+ if(buf[2] & 4)
+ REMOTE_BUTTON(BUTTON_RC_VOL_DOWN);
+ if(buf[2] & 8)
+ REMOTE_BUTTON(BUTTON_RC_RIGHT);
+ if(buf[2] & 16)
+ REMOTE_BUTTON(BUTTON_RC_LEFT);
+ }
+ else if(len >= 4 && buf[3] != 0)
+ {
+ if(buf[3] & 1) /* play */
+ {
+ if (audio_status() != AUDIO_STATUS_PLAY)
+ REMOTE_BUTTON(BUTTON_RC_PLAY);
+ }
+ if(buf[3] & 2) /* pause */
+ {
+ if (audio_status() == AUDIO_STATUS_PLAY)
+ REMOTE_BUTTON(BUTTON_RC_PLAY);
+ }
+ if(buf[3] & 128) /* Shuffle */
+ {
+ if (!iap_btnshuffle)
+ {
+ iap_shuffle_state(!global_settings.playlist_shuffle);
+ iap_btnshuffle = true;
+ }
+ }
+ }
+ else if(len >= 5 && buf[4] != 0)
+ {
+ if(buf[4] & 1) /* repeat */
+ {
+ if (!iap_btnrepeat)
+ {
+ iap_repeat_next();
+ iap_btnrepeat = true;
+ }
+ }
+
+ /* Power off
+ * Not quite sure how to react to this, but stopping playback
+ * is a good start.
+ */
+ if (buf[4] & 0x04)
+ {
+ if (audio_status() == AUDIO_STATUS_PLAY)
+ REMOTE_BUTTON(BUTTON_RC_PLAY);
+ }
+
+ if(buf[4] & 16) /* ffwd */
+ REMOTE_BUTTON(BUTTON_RC_RIGHT);
+ if(buf[4] & 32) /* frwd */
+ REMOTE_BUTTON(BUTTON_RC_LEFT);
+ }
+
+ break;
+ }
+ /* ACK (0x01)
+ *
+ * Sent from the iPod to the device
+ */
+
+ /* ImageButtonStatus (0x02)
+ *
+ * Transmit image button events from the device to the iPod
+ *
+ * Packet format (offset in buf[]: Description)
+ * 0x00: Lingo ID: Simple Remote Lingo, always 0x02
+ * 0x01: Command, always 0x02
+ * 0x02: Button states 0:7
+ * 0x03: Button states 8:15 (optional)
+ * 0x04: Button states 16:23 (optional)
+ * 0x05: Button states 24:31 (optional)
+ *
+ * This command requires authentication
+ *
+ * Returns on success:
+ * IAP_ACK_OK
+ *
+ * Returns on failure:
+ * IAP_ACK_*
+ */
+ case 0x02:
+ {
+ if (!DEVICE_AUTHENTICATED) {
+ cmd_ack(cmd, IAP_ACK_NO_AUTHEN);
+ break;
+ }
+
+ cmd_ack(cmd, IAP_ACK_CMD_FAILED);
+ break;
+ }
+
+ /* VideoButtonStatus (0x03)
+ *
+ * Transmit video button events from the device to the iPod
+ *
+ * Packet format (offset in buf[]: Description)
+ * 0x00: Lingo ID: Simple Remote Lingo, always 0x02
+ * 0x01: Command, always 0x03
+ * 0x02: Button states 0:7
+ * 0x03: Button states 8:15 (optional)
+ * 0x04: Button states 16:23 (optional)
+ * 0x05: Button states 24:31 (optional)
+ *
+ * This command requires authentication
+ *
+ * Returns on success:
+ * IAP_ACK_OK
+ *
+ * Returns on failure:
+ * IAP_ACK_*
+ */
+ case 0x03:
+ {
+ if (!DEVICE_AUTHENTICATED) {
+ cmd_ack(cmd, IAP_ACK_NO_AUTHEN);
+ break;
+ }
+
+ cmd_ack(cmd, IAP_ACK_CMD_FAILED);
+ break;
+ }
+
+ /* AudioButtonStatus (0x04)
+ *
+ * Transmit audio button events from the device to the iPod
+ *
+ * Packet format (offset in buf[]: Description)
+ * 0x00: Lingo ID: Simple Remote Lingo, always 0x02
+ * 0x01: Command, always 0x04
+ * 0x02: Button states 0:7
+ * 0x03: Button states 8:15 (optional)
+ * 0x04: Button states 16:23 (optional)
+ * 0x05: Button states 24:31 (optional)
+ *
+ * This command requires authentication
+ *
+ * Returns on success:
+ * IAP_ACK_OK
+ *
+ * Returns on failure:
+ * IAP_ACK_*
+ */
+ case 0x04:
+ {
+ unsigned char repeatbuf[6];
+
+ if (!DEVICE_AUTHENTICATED) {
+ cmd_ack(cmd, IAP_ACK_NO_AUTHEN);
+ break;
+ }
+
+ /* This is basically the same command as ContextButtonStatus (0x00),
+ * with the difference that it requires authentication and that
+ * it returns an ACK packet to the device.
+ * So just route it through the handler again, with 0x00 as the
+ * command
+ */
+ memcpy(repeatbuf, buf, 6);
+ repeatbuf[1] = 0x00;
+ iap_handlepkt_mode2((len<6)?len:6, repeatbuf);
+
+ cmd_ok(cmd);
+ break;
+ }
+
+ /* The default response is IAP_ACK_BAD_PARAM */
+ default:
+ {
+#ifdef LOGF_ENABLE
+ logf("iap: Unsupported Mode02 Command");
+#else
+ cmd_ack(cmd, IAP_ACK_BAD_PARAM);
+#endif
+ break;
+ }
+ }
+}