diff options
Diffstat (limited to 'apps/iap/iap-lingo7.c')
-rw-r--r-- | apps/iap/iap-lingo7.c | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/apps/iap/iap-lingo7.c b/apps/iap/iap-lingo7.c new file mode 100644 index 0000000000..467a81cc76 --- /dev/null +++ b/apps/iap/iap-lingo7.c | |||
@@ -0,0 +1,491 @@ | |||
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 | #include "iap-core.h" | ||
20 | #include "iap-lingo.h" | ||
21 | #include "kernel.h" | ||
22 | #include "system.h" | ||
23 | #include "tuner.h" | ||
24 | #if CONFIG_TUNER | ||
25 | #include "ipod_remote_tuner.h" | ||
26 | #endif | ||
27 | |||
28 | /* | ||
29 | * This macro is meant to be used inside an IAP mode message handler. | ||
30 | * It is passed the expected minimum length of the message inbufferfer. | ||
31 | * If the inbufferfer does not have the required lenght an ACK | ||
32 | * packet with a Bad Parameter error is generated. | ||
33 | */ | ||
34 | #define CHECKLEN(x) do { \ | ||
35 | if (len < (x)) { \ | ||
36 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); \ | ||
37 | return; \ | ||
38 | }} while(0) | ||
39 | |||
40 | /* Check for authenticated state, and return an ACK Not | ||
41 | * Authenticated on failure. | ||
42 | */ | ||
43 | #define CHECKAUTH do { \ | ||
44 | if (!DEVICE_AUTHENTICATED) { \ | ||
45 | cmd_ack(cmd, IAP_ACK_NO_AUTHEN); \ | ||
46 | return; \ | ||
47 | }} while(0) | ||
48 | |||
49 | |||
50 | static void cmd_ack(const unsigned char cmd, const unsigned char status) | ||
51 | { | ||
52 | IAP_TX_INIT(0x07, 0x00); | ||
53 | IAP_TX_PUT(status); | ||
54 | IAP_TX_PUT(cmd); | ||
55 | |||
56 | iap_send_tx(); | ||
57 | } | ||
58 | |||
59 | #define cmd_ok(cmd) cmd_ack((cmd), IAP_ACK_OK) | ||
60 | |||
61 | void iap_handlepkt_mode7(const unsigned int len, const unsigned char *inbuffer) | ||
62 | { | ||
63 | /* Note that some of the Lingo Mode 7 commands are handled by | ||
64 | * ../firmware/drivers/tuner/ipod_remote_tuner.c as some of the | ||
65 | * commands are sourced with the remote as the master with the ipod acting | ||
66 | * as the slave. | ||
67 | */ | ||
68 | unsigned char cmd = inbuffer[1]; | ||
69 | unsigned char statusnotifymaskbyte = 0; | ||
70 | |||
71 | /* We expect at least two bytes in the inbuffer, one for the | ||
72 | * lingo and one for the command | ||
73 | */ | ||
74 | CHECKLEN(2); | ||
75 | |||
76 | /* Lingo 0x07 must have been negotiated */ | ||
77 | if (!DEVICE_LINGO_SUPPORTED(0x07)) { | ||
78 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | switch (cmd) | ||
83 | { | ||
84 | /* case 00 ToIpod Ack 2/6 bytes*/ | ||
85 | case 0x00: | ||
86 | { | ||
87 | /* 0x00 OK | ||
88 | * 0x01 Unknown Track Category | ||
89 | * 0x02 Command Failed. Command is valid but did not succeed | ||
90 | * 0x03 Out Of Resources | ||
91 | * 0x04 Bad Parameter | ||
92 | * 0x05 Unknown Track ID | ||
93 | * 0x06 Command Pending. | ||
94 | * 0x07 Not Authenticated | ||
95 | * | ||
96 | * byte 1 is ID of command being acknowledged | ||
97 | * bytes 2-5 only if status byte is pending. timeout in ms. | ||
98 | */ | ||
99 | break; | ||
100 | } | ||
101 | |||
102 | /* case 0x01 ToAccessory GetTunerCaps | ||
103 | * This is sent by iap-lingo0.c through case 0x15 after device | ||
104 | * has been authenticated FF55020701F6 | ||
105 | */ | ||
106 | |||
107 | /* case 02 ToIpod RetTunerCaps 8 bytes */ | ||
108 | case 0x02: | ||
109 | { | ||
110 | /* Capabilities are stored as bits in first 4 bytes, | ||
111 | * inbuffer[2] byte is bits 31:24 | ||
112 | * inbuffer[3] byte is bits 23:16 | ||
113 | * inbuffer[4] byte is bits 15:08 | ||
114 | * inbuffer[5] byte is bits 07:00 | ||
115 | * inbuffer[6] and inbuffer[7] are all reserved bits | ||
116 | * Bit 0 = AM Band 520-1710 Khz | ||
117 | * Bit 1 = FM Europe/US 87.5 - 108.0 Mhz | ||
118 | * Bit 2 = FM Japan 76.0 - 90.0 Mhz | ||
119 | * Bit 3 = FM Wide 76.0 - 108.0 Mhz | ||
120 | * Bit 4 = HD Radio Capable | ||
121 | * Bit 5:7 Reserved | ||
122 | * Bit 8 = Tuner Power On/Off Control Capable | ||
123 | * Bit 9 = Status Change Notification Capable | ||
124 | * Bit 10:15 Reserved | ||
125 | * Bit 17:16 Minimum FM Resolution ID Bits | ||
126 | * 00 = 200Khz, 01 = 100Khz, 10 = 50Khz, 11 = reserved | ||
127 | * Bit 18 = Tuner Seek Up/Down Capable | ||
128 | * Bit 19 = Tuner Seek RSSI Threshold. Only if 18=1 | ||
129 | * Bit 20 = Force Monophonic mode capable | ||
130 | * Bit 21 = Stero Blend Capable | ||
131 | * Bit 22 = FM Tuner deemphasis select capable | ||
132 | * Bit 23 = AM Tuner Resolution 9Khz (0=10Khz Only) capable | ||
133 | * Bit 24 = Radio Data System (RDS/RBDS) data capable | ||
134 | * Bit 25 = Tuner Channel RSSI indicator capable | ||
135 | * Bit 26 = Stero Source Indicator capable | ||
136 | * Bit 27 = RDS/RBDS Raw mode capable | ||
137 | * Bit 31:28 Reserved | ||
138 | * | ||
139 | * ipod Tuner returns 07 5E 07 0E 10 4B | ||
140 | * Bytes 6,7 Reserved | ||
141 | * ???????? ???????? | ||
142 | * ???????? ???????? | ||
143 | * 00010000 01001011 | ||
144 | * | ||
145 | * Byte 5 - 0E | ||
146 | * 00000000 | ||
147 | * 76543210 | ||
148 | * 00001110 | ||
149 | * AM | ||
150 | * FM Europe/US | ||
151 | * FM Japan | ||
152 | * FM Wide | ||
153 | * | ||
154 | * Byte 4 - 07 | ||
155 | * 11111100 | ||
156 | * 54321098 | ||
157 | * 00000111 | ||
158 | * Tuner Power On/Off | ||
159 | * Status Change Notification | ||
160 | * ?? Should be reserved | ||
161 | * | ||
162 | * Byte 3 - 5E | ||
163 | * 22221111 | ||
164 | * 32109876 | ||
165 | * 01011110 | ||
166 | * Tuner Seek Up/Down | ||
167 | * Tuner Seek RSSI Threshold | ||
168 | * Force Mono Mode Capable | ||
169 | * Stereo Blend Capable | ||
170 | * FM Tuner deemphasis select capable | ||
171 | * | ||
172 | * Byte 2 - 07 | ||
173 | * 33222222 | ||
174 | * 10987654 | ||
175 | * 00000111 | ||
176 | * RDS/RBDS Capable | ||
177 | * Tuner Channel RSSI Indicator | ||
178 | * Stereo Source | ||
179 | * | ||
180 | * Just need to see what we can use this data for | ||
181 | * Make a selection for the tuner mode to select | ||
182 | * Preference is | ||
183 | * 1st - 76 to 108 FM | ||
184 | * 2nd - 87.5 to 108 Fm | ||
185 | * 3rd - 76 to 90 Fm | ||
186 | * 4th - AM | ||
187 | * | ||
188 | */ | ||
189 | |||
190 | if ((inbuffer[4] & 0x03) >0) { | ||
191 | statusnotifymaskbyte = 0; | ||
192 | if ((inbuffer[4] >> 0) & 0x01) { | ||
193 | /* Supports Tuner Power On/Off, so set ON */ | ||
194 | statusnotifymaskbyte = 1; | ||
195 | } | ||
196 | if ((inbuffer[4] >> 1) & 0x01) { | ||
197 | /* Supports Status Change Notification so set ON */ | ||
198 | /* Apple 5/6/7G firmware does NOT enable this bit */ | ||
199 | /* statusnotifymaskbyte += 2; */ | ||
200 | } | ||
201 | IAP_TX_INIT(0x07, 0x05); | ||
202 | IAP_TX_PUT(statusnotifymaskbyte); | ||
203 | iap_send_tx(); | ||
204 | } | ||
205 | if ((inbuffer[5] >> 1) & 0x01) { | ||
206 | /* Supports FM Europe/US Tuner 87.5 - 108.0 Mhz */ | ||
207 | /* Apple firmware sends this before setting region */ | ||
208 | IAP_TX_INIT(0x07, 0x0E); | ||
209 | IAP_TX_PUT(0x00); | ||
210 | iap_send_tx(); | ||
211 | /* Apple firmware then sends region */ | ||
212 | IAP_TX_INIT(0x07, 0x08); | ||
213 | IAP_TX_PUT(0x02); | ||
214 | iap_send_tx(); | ||
215 | } else if ((inbuffer[5] >> 3) & 0x01) { | ||
216 | /* Supports FM Wide Tuner 76 - 108.0 Mhz */ | ||
217 | /* apple firmware send this before setting region */ | ||
218 | IAP_TX_INIT(0x07, 0x0E); | ||
219 | IAP_TX_PUT(0x00); | ||
220 | iap_send_tx(); | ||
221 | /* Apple firmware then send region */ | ||
222 | IAP_TX_INIT(0x07, 0x08); | ||
223 | IAP_TX_PUT(0x08); | ||
224 | iap_send_tx(); | ||
225 | } else if ((inbuffer[5] >> 2) & 0x01) { | ||
226 | /* Supports FM Japan Tuner 76 - 90.0 Mhz */ | ||
227 | /* apple firmware send this before setting region */ | ||
228 | IAP_TX_INIT(0x07, 0x0E); | ||
229 | IAP_TX_PUT(0x41); | ||
230 | iap_send_tx(); | ||
231 | /* Apple firmware then send region */ | ||
232 | IAP_TX_INIT(0x07, 0x08); | ||
233 | IAP_TX_PUT(0x04); | ||
234 | iap_send_tx(); | ||
235 | } else if ((inbuffer[5] >> 0) & 0x01) { | ||
236 | /* Supports AM Tuner */ | ||
237 | IAP_TX_INIT(0x07, 0x08); | ||
238 | IAP_TX_PUT(0x01); | ||
239 | iap_send_tx(); | ||
240 | } | ||
241 | |||
242 | if ((inbuffer[2] & 0x03) > 0) { | ||
243 | statusnotifymaskbyte = 0; | ||
244 | if ((inbuffer[2] >> 0) & 0x01) { | ||
245 | /* Supports RDS/RBDS Capable so set | ||
246 | *StatusChangeNotify for RDS/RBDS Data | ||
247 | */ | ||
248 | statusnotifymaskbyte = 1; | ||
249 | } | ||
250 | if ((inbuffer[2] >> 1) & 0x01) { | ||
251 | /* Supports Tuner Channel RSSi Indicator Capable so set */ | ||
252 | /* StatusChangeNotify for RSSI */ | ||
253 | /* Apple 5G firmware does NOT enable this bit so we wont */ | ||
254 | /* statusnotifymaskbyte += 2; */ | ||
255 | } | ||
256 | IAP_TX_INIT(0x07, 0x18); | ||
257 | IAP_TX_PUT(statusnotifymaskbyte); | ||
258 | iap_send_tx(); | ||
259 | } | ||
260 | |||
261 | if ((inbuffer[4] >> 2) & 0x01) { | ||
262 | /* Reserved */ | ||
263 | } | ||
264 | if ((inbuffer[4] >> 3) & 0x01) { | ||
265 | /* Reserved */ | ||
266 | } | ||
267 | if ((inbuffer[3] >> 1) & 0x01) { | ||
268 | /* Tuner Seek Up/Down` */ | ||
269 | } | ||
270 | if ((inbuffer[3] >> 2) & 0x01) { | ||
271 | /* Tuner Seek RSSI Threshold */ | ||
272 | } | ||
273 | if ((inbuffer[3] >> 3) & 0x01) { | ||
274 | /* Force Mono Mode */ | ||
275 | } | ||
276 | if ((inbuffer[3] >> 4) & 0x01) { | ||
277 | /* Stereo Blend */ | ||
278 | } | ||
279 | if ((inbuffer[3] >> 6) & 0x01) { | ||
280 | /* FM Tuner deemphasis */ | ||
281 | } | ||
282 | if ((inbuffer[2] >> 2) & 0x01) { | ||
283 | /* Stereo Source */ | ||
284 | } | ||
285 | break; | ||
286 | } | ||
287 | /* case 03 ToAccessory GetTunerCtrl 2 bytes */ | ||
288 | |||
289 | /* case 04 ToIpod RetTunerCtrl 3 bytes | ||
290 | * Bit 0 power is on (1) or Off (0) | ||
291 | * Bit 1 StatusChangeNotify is enabled (1) or disabled (0) | ||
292 | * Bit 3 RDS/RBDS Raw mode enabled | ||
293 | * | ||
294 | * Should/Can we do something with these? | ||
295 | */ | ||
296 | |||
297 | /* case 05 ToAccessory SetTunerCtrl 3 bytes | ||
298 | * Bits as per 0x04 above | ||
299 | * Bit 0/1 set through Lingo7 Cmd02 */ | ||
300 | |||
301 | /* case 06 ToAccessory GetTunerBand 2 bytes */ | ||
302 | |||
303 | /* case 07 ToIpod RetTunerBand 3 bytes | ||
304 | * Returns current band for Tuner. See 0x08 below | ||
305 | * | ||
306 | * Should/Can we do something with these? | ||
307 | */ | ||
308 | |||
309 | /* case 08 ToAccessory SetTuneBand | ||
310 | * Set Bit 0 for AM | ||
311 | * Set Bit 1 for FM Europe/U S 87.5-108Mhz | ||
312 | * Set Bit 2 for FM JApan 76.0-90.0Mhz | ||
313 | * Set Bit 3 for FM Wide 76.0-108Mhz | ||
314 | * Currently we send this after receiving capabilities | ||
315 | * on 0x02 above | ||
316 | */ | ||
317 | |||
318 | /* case 09 ToAccessory GetTunerFreq 2 bytes */ | ||
319 | |||
320 | /* case 0A ToIpod RetTunerFreq 7 bytes */ | ||
321 | case 0x0A: | ||
322 | { | ||
323 | /* Returns Frequency set and RSSI Power Levels | ||
324 | * These are sent as is to rmt_tuner_freq() in | ||
325 | * ../firmware/drivers/tuner/ipod_remote_tuner.c */ | ||
326 | rmt_tuner_freq(len, inbuffer); | ||
327 | break; | ||
328 | } | ||
329 | |||
330 | /* case 0B ToAccessory SetTunerFreq 6 bytes */ | ||
331 | |||
332 | /* case 0C ToAccessory GetTunerMode 2 bytes */ | ||
333 | |||
334 | /* case 0D ToIpod RetTunerMode 3 bytes | ||
335 | * Returns Tuner Mode Status in 8 bits as follows | ||
336 | * Bit 1:0 - FM Tuner Resolution | ||
337 | * Bit 2 Tuner is seeking up or down | ||
338 | * Bit 3 Tuner is seeking with RSSI min theshold enabled | ||
339 | * Bit 4 Force Mono Mode (1) or allow stereo (0) | ||
340 | * Bit 5 Stereo Blend enabled. Valid only if Bit 4 is 0 | ||
341 | * Bit 6 FM Tuner Deemphasis 50uS (1) or 75uS (0) | ||
342 | * Bit 7 Reserved 0 | ||
343 | */ | ||
344 | |||
345 | /* case 0E ToAccessory SetTunerMode 3 bytes | ||
346 | * See 0x0D for Bit Descriptions | ||
347 | * Bits set by Cmd 02 | ||
348 | */ | ||
349 | |||
350 | /* case 0F ToAccessory GetTunerSeekRssi 2 bytes */ | ||
351 | |||
352 | /* case 10 ToIpod RetTunerSeekRssi 3 bytes | ||
353 | * Returns RSSI Value for seek operations | ||
354 | * value is 0 (min) - 255 (max) | ||
355 | */ | ||
356 | |||
357 | /* case 11 ToAccessory SetTunerSeekRssi 3 bytes */ | ||
358 | |||
359 | /* case 12 ToAccessory TunerSeekStart 3 bytes */ | ||
360 | |||
361 | /* case 13 ToIpod TunerSeekDone 7 bytes */ | ||
362 | case 0x13: | ||
363 | { | ||
364 | rmt_tuner_freq(len, inbuffer); | ||
365 | break; | ||
366 | } | ||
367 | |||
368 | /* case 14 ToAccessory GetTunerStatus 2 bytes */ | ||
369 | |||
370 | /* case 15 ToIpod RetTunerStatus 3 bytes */ | ||
371 | |||
372 | /* case 16 ToAccessory GetStatusNotifyMask 2 bytes */ | ||
373 | |||
374 | /* case 17 ToIpod RetStatusNotifyMask 3 bytes */ | ||
375 | |||
376 | /* case 18 ToAccessory SetStatusNotifyMask 3 bytes | ||
377 | * This is set by Cmd 02 | ||
378 | */ | ||
379 | |||
380 | /* case 19 ToIpod StatusChangeNotify 3 bytes */ | ||
381 | case 0x19: | ||
382 | { | ||
383 | /* Returns StatusChangeNotify bits to ipod. | ||
384 | * Bit 0 set for RDS/RBDS data ready | ||
385 | * Bit 1 set for Tuner RSSI level change | ||
386 | * Bit 2 for Stereo Indicator changed | ||
387 | * If any of these are set we will request the data | ||
388 | * need to look at using these | ||
389 | */ | ||
390 | break; | ||
391 | } | ||
392 | |||
393 | /* case 1A ToAccessory GetRdsReadyStatus 2 bytes */ | ||
394 | |||
395 | /* case 1B ToIpod RetRdsReadyStatus 6 bytes */ | ||
396 | case 0x1B: | ||
397 | { | ||
398 | break; | ||
399 | } | ||
400 | /* case 1C ToAccessory GetRdsData 3 bytes */ | ||
401 | |||
402 | /* case 1D ToIpod RetRdsData NN bytes */ | ||
403 | case 0x1D: | ||
404 | { | ||
405 | rmt_tuner_rds_data(len, inbuffer); | ||
406 | break; | ||
407 | } | ||
408 | |||
409 | /* case 1E ToAccessory GetRdsNotifyMask 2 bytes*/ | ||
410 | |||
411 | /* case 1F ToIpod RetRdsNotifyMask 6 Bytes*/ | ||
412 | case 0x1F: | ||
413 | { | ||
414 | break; | ||
415 | } | ||
416 | |||
417 | /* case 20 ToAccessory SetRdsNotifyMask 6 bytes */ | ||
418 | |||
419 | /* case 21 ToIpod RdsReadyNotify NN bytes */ | ||
420 | case 0x21: | ||
421 | { | ||
422 | rmt_tuner_rds_data(len, inbuffer); | ||
423 | break; | ||
424 | } | ||
425 | /* case 22 Reserved */ | ||
426 | |||
427 | /* case 23 Reserved */ | ||
428 | |||
429 | /* case 24 Reserved */ | ||
430 | |||
431 | /* case 25 ToAccessory GetHDProgramServiceCount 0 bytes */ | ||
432 | |||
433 | /* case 26 ToIpod RetHDProgramServiceCount 1 bytes */ | ||
434 | case 0x26: | ||
435 | { | ||
436 | break; | ||
437 | } | ||
438 | |||
439 | /* case 27 ToAccessory GetHDProgramService 0 bytes */ | ||
440 | |||
441 | /* case 28 ToIpod RetHDProgramService 1 bytes */ | ||
442 | case 0x28: | ||
443 | { | ||
444 | break; | ||
445 | } | ||
446 | |||
447 | /* case 29 ToAccessory SetHDProgramService 1 bytes */ | ||
448 | |||
449 | /* case 2A ToAccessory GetHDDataReadyStatus 0 bytes */ | ||
450 | |||
451 | /* case 2B ToIpod RetHDDataReadyStatus 4 bytes */ | ||
452 | case 0x2B: | ||
453 | { | ||
454 | break; | ||
455 | } | ||
456 | |||
457 | /* case 2C ToAccessory GetHDData 1 bytes */ | ||
458 | |||
459 | /* case 2D ToIpod RetHDData NN bytes */ | ||
460 | case 0x2D: | ||
461 | { | ||
462 | break; | ||
463 | } | ||
464 | |||
465 | /* case 2E ToAccessory GetHDDataNotifyMask 0 bytes */ | ||
466 | |||
467 | /* case 2F ToIpod RetHDDataNotifyMask 4 bytes */ | ||
468 | case 0x2F: | ||
469 | { | ||
470 | break; | ||
471 | } | ||
472 | |||
473 | /* case 30 ToAccessory SetHDDataNotifyMask 4 bytes */ | ||
474 | |||
475 | /* case 31 ToIpod HDDataReadyNotify NN bytes */ | ||
476 | case 0x31: | ||
477 | { | ||
478 | break; | ||
479 | } | ||
480 | |||
481 | /* The default response is IAP_ACK_BAD_PARAM */ | ||
482 | default: | ||
483 | { | ||
484 | #ifdef LOGF_ENABLE | ||
485 | logf("iap: Unsupported Mode07 Command"); | ||
486 | #endif | ||
487 | cmd_ack(cmd, IAP_ACK_BAD_PARAM); | ||
488 | break; | ||
489 | } | ||
490 | } | ||
491 | } | ||