diff options
Diffstat (limited to 'apps/iap/iap-lingo2.c')
-rw-r--r-- | apps/iap/iap-lingo2.c | 278 |
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr & Nick Robinson | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | /* Lingo 0x02, Simple Remote Lingo | ||
21 | * | ||
22 | * TODO: | ||
23 | * - Fix cmd 0x00 handling, there has to be a more elegant way of doing | ||
24 | * this | ||
25 | */ | ||
26 | |||
27 | #include "iap-core.h" | ||
28 | #include "iap-lingo.h" | ||
29 | #include "system.h" | ||
30 | #include "button.h" | ||
31 | #include "audio.h" | ||
32 | #include "settings.h" | ||
33 | |||
34 | /* | ||
35 | * This macro is meant to be used inside an IAP mode message handler. | ||
36 | * It is passed the expected minimum length of the message buffer. | ||
37 | * If the buffer does not have the required lenght an ACK | ||
38 | * packet with a Bad Parameter error is generated. | ||
39 | */ | ||
40 | #define CHECKLEN(x) do { \ | ||
41 | if (len < (x)) { \ | ||
42 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); \ | ||
43 | return; \ | ||
44 | }} while(0) | ||
45 | |||
46 | static void cmd_ack(const unsigned char cmd, const unsigned char status) | ||
47 | { | ||
48 | IAP_TX_INIT(0x02, 0x01); | ||
49 | IAP_TX_PUT(status); | ||
50 | IAP_TX_PUT(cmd); | ||
51 | |||
52 | iap_send_tx(); | ||
53 | } | ||
54 | |||
55 | #define cmd_ok(cmd) cmd_ack((cmd), IAP_ACK_OK) | ||
56 | |||
57 | void iap_handlepkt_mode2(const unsigned int len, const unsigned char *buf) | ||
58 | { | ||
59 | unsigned int cmd = buf[1]; | ||
60 | |||
61 | /* We expect at least three bytes in the buffer, one for the | ||
62 | * lingo, one for the command, and one for the first button | ||
63 | * state bits. | ||
64 | */ | ||
65 | CHECKLEN(3); | ||
66 | |||
67 | /* Lingo 0x02 must have been negotiated */ | ||
68 | if (!DEVICE_LINGO_SUPPORTED(0x02)) { | ||
69 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | switch (cmd) | ||
74 | { | ||
75 | /* ContextButtonStatus (0x00) | ||
76 | * | ||
77 | * Transmit button events from the device to the iPod | ||
78 | * | ||
79 | * Packet format (offset in buf[]: Description) | ||
80 | * 0x00: Lingo ID: Simple Remote Lingo, always 0x02 | ||
81 | * 0x01: Command, always 0x00 | ||
82 | * 0x02: Button states 0:7 | ||
83 | * 0x03: Button states 8:15 (optional) | ||
84 | * 0x04: Button states 16:23 (optional) | ||
85 | * 0x05: Button states 24:31 (optional) | ||
86 | * | ||
87 | * Returns: (none) | ||
88 | */ | ||
89 | case 0x00: | ||
90 | { | ||
91 | iap_remotebtn = BUTTON_NONE; | ||
92 | iap_timeoutbtn = 0; | ||
93 | |||
94 | if(buf[2] != 0) | ||
95 | { | ||
96 | if(buf[2] & 1) | ||
97 | REMOTE_BUTTON(BUTTON_RC_PLAY); | ||
98 | if(buf[2] & 2) | ||
99 | REMOTE_BUTTON(BUTTON_RC_VOL_UP); | ||
100 | if(buf[2] & 4) | ||
101 | REMOTE_BUTTON(BUTTON_RC_VOL_DOWN); | ||
102 | if(buf[2] & 8) | ||
103 | REMOTE_BUTTON(BUTTON_RC_RIGHT); | ||
104 | if(buf[2] & 16) | ||
105 | REMOTE_BUTTON(BUTTON_RC_LEFT); | ||
106 | } | ||
107 | else if(len >= 4 && buf[3] != 0) | ||
108 | { | ||
109 | if(buf[3] & 1) /* play */ | ||
110 | { | ||
111 | if (audio_status() != AUDIO_STATUS_PLAY) | ||
112 | REMOTE_BUTTON(BUTTON_RC_PLAY); | ||
113 | } | ||
114 | if(buf[3] & 2) /* pause */ | ||
115 | { | ||
116 | if (audio_status() == AUDIO_STATUS_PLAY) | ||
117 | REMOTE_BUTTON(BUTTON_RC_PLAY); | ||
118 | } | ||
119 | if(buf[3] & 128) /* Shuffle */ | ||
120 | { | ||
121 | if (!iap_btnshuffle) | ||
122 | { | ||
123 | iap_shuffle_state(!global_settings.playlist_shuffle); | ||
124 | iap_btnshuffle = true; | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | else if(len >= 5 && buf[4] != 0) | ||
129 | { | ||
130 | if(buf[4] & 1) /* repeat */ | ||
131 | { | ||
132 | if (!iap_btnrepeat) | ||
133 | { | ||
134 | iap_repeat_next(); | ||
135 | iap_btnrepeat = true; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | /* Power off | ||
140 | * Not quite sure how to react to this, but stopping playback | ||
141 | * is a good start. | ||
142 | */ | ||
143 | if (buf[4] & 0x04) | ||
144 | { | ||
145 | if (audio_status() == AUDIO_STATUS_PLAY) | ||
146 | REMOTE_BUTTON(BUTTON_RC_PLAY); | ||
147 | } | ||
148 | |||
149 | if(buf[4] & 16) /* ffwd */ | ||
150 | REMOTE_BUTTON(BUTTON_RC_RIGHT); | ||
151 | if(buf[4] & 32) /* frwd */ | ||
152 | REMOTE_BUTTON(BUTTON_RC_LEFT); | ||
153 | } | ||
154 | |||
155 | break; | ||
156 | } | ||
157 | /* ACK (0x01) | ||
158 | * | ||
159 | * Sent from the iPod to the device | ||
160 | */ | ||
161 | |||
162 | /* ImageButtonStatus (0x02) | ||
163 | * | ||
164 | * Transmit image button events from the device to the iPod | ||
165 | * | ||
166 | * Packet format (offset in buf[]: Description) | ||
167 | * 0x00: Lingo ID: Simple Remote Lingo, always 0x02 | ||
168 | * 0x01: Command, always 0x02 | ||
169 | * 0x02: Button states 0:7 | ||
170 | * 0x03: Button states 8:15 (optional) | ||
171 | * 0x04: Button states 16:23 (optional) | ||
172 | * 0x05: Button states 24:31 (optional) | ||
173 | * | ||
174 | * This command requires authentication | ||
175 | * | ||
176 | * Returns on success: | ||
177 | * IAP_ACK_OK | ||
178 | * | ||
179 | * Returns on failure: | ||
180 | * IAP_ACK_* | ||
181 | */ | ||
182 | case 0x02: | ||
183 | { | ||
184 | if (!DEVICE_AUTHENTICATED) { | ||
185 | cmd_ack(cmd, IAP_ACK_NO_AUTHEN); | ||
186 | break; | ||
187 | } | ||
188 | |||
189 | cmd_ack(cmd, IAP_ACK_CMD_FAILED); | ||
190 | break; | ||
191 | } | ||
192 | |||
193 | /* VideoButtonStatus (0x03) | ||
194 | * | ||
195 | * Transmit video button events from the device to the iPod | ||
196 | * | ||
197 | * Packet format (offset in buf[]: Description) | ||
198 | * 0x00: Lingo ID: Simple Remote Lingo, always 0x02 | ||
199 | * 0x01: Command, always 0x03 | ||
200 | * 0x02: Button states 0:7 | ||
201 | * 0x03: Button states 8:15 (optional) | ||
202 | * 0x04: Button states 16:23 (optional) | ||
203 | * 0x05: Button states 24:31 (optional) | ||
204 | * | ||
205 | * This command requires authentication | ||
206 | * | ||
207 | * Returns on success: | ||
208 | * IAP_ACK_OK | ||
209 | * | ||
210 | * Returns on failure: | ||
211 | * IAP_ACK_* | ||
212 | */ | ||
213 | case 0x03: | ||
214 | { | ||
215 | if (!DEVICE_AUTHENTICATED) { | ||
216 | cmd_ack(cmd, IAP_ACK_NO_AUTHEN); | ||
217 | break; | ||
218 | } | ||
219 | |||
220 | cmd_ack(cmd, IAP_ACK_CMD_FAILED); | ||
221 | break; | ||
222 | } | ||
223 | |||
224 | /* AudioButtonStatus (0x04) | ||
225 | * | ||
226 | * Transmit audio button events from the device to the iPod | ||
227 | * | ||
228 | * Packet format (offset in buf[]: Description) | ||
229 | * 0x00: Lingo ID: Simple Remote Lingo, always 0x02 | ||
230 | * 0x01: Command, always 0x04 | ||
231 | * 0x02: Button states 0:7 | ||
232 | * 0x03: Button states 8:15 (optional) | ||
233 | * 0x04: Button states 16:23 (optional) | ||
234 | * 0x05: Button states 24:31 (optional) | ||
235 | * | ||
236 | * This command requires authentication | ||
237 | * | ||
238 | * Returns on success: | ||
239 | * IAP_ACK_OK | ||
240 | * | ||
241 | * Returns on failure: | ||
242 | * IAP_ACK_* | ||
243 | */ | ||
244 | case 0x04: | ||
245 | { | ||
246 | unsigned char repeatbuf[6]; | ||
247 | |||
248 | if (!DEVICE_AUTHENTICATED) { | ||
249 | cmd_ack(cmd, IAP_ACK_NO_AUTHEN); | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | /* This is basically the same command as ContextButtonStatus (0x00), | ||
254 | * with the difference that it requires authentication and that | ||
255 | * it returns an ACK packet to the device. | ||
256 | * So just route it through the handler again, with 0x00 as the | ||
257 | * command | ||
258 | */ | ||
259 | memcpy(repeatbuf, buf, 6); | ||
260 | repeatbuf[1] = 0x00; | ||
261 | iap_handlepkt_mode2((len<6)?len:6, repeatbuf); | ||
262 | |||
263 | cmd_ok(cmd); | ||
264 | break; | ||
265 | } | ||
266 | |||
267 | /* The default response is IAP_ACK_BAD_PARAM */ | ||
268 | default: | ||
269 | { | ||
270 | #ifdef LOGF_ENABLE | ||
271 | logf("iap: Unsupported Mode02 Command"); | ||
272 | #else | ||
273 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); | ||
274 | #endif | ||
275 | break; | ||
276 | } | ||
277 | } | ||
278 | } | ||