summaryrefslogtreecommitdiff
path: root/apps/iap/iap-lingo0.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-lingo0.c
parent500b137308a6ee5c2aba873734a8956d70472f56 (diff)
downloadrockbox-b170c73f922e3457b923b4e7fcbec794a8885c77.tar.gz
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-lingo0.c')
-rw-r--r--apps/iap/iap-lingo0.c1035
1 files changed, 1035 insertions, 0 deletions
diff --git a/apps/iap/iap-lingo0.c b/apps/iap/iap-lingo0.c
new file mode 100644
index 0000000000..9e0355cb3f
--- /dev/null
+++ b/apps/iap/iap-lingo0.c
@@ -0,0 +1,1035 @@
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#include "iap-core.h"
21#include "iap-lingo.h"
22#include "kernel.h"
23#include "system.h"
24
25/*
26 * This macro is meant to be used inside an IAP mode message handler.
27 * It is passed the expected minimum length of the message buffer.
28 * If the buffer does not have the required lenght an ACK
29 * packet with a Bad Parameter error is generated.
30 */
31#define CHECKLEN(x) do { \
32 if (len < (x)) { \
33 cmd_ack(cmd, IAP_ACK_BAD_PARAM); \
34 return; \
35 }} while(0)
36
37/* Check for authenticated state, and return an ACK Not
38 * Authenticated on failure.
39 */
40#define CHECKAUTH do { \
41 if (!DEVICE_AUTHENTICATED) { \
42 cmd_ack(cmd, IAP_ACK_NO_AUTHEN); \
43 return; \
44 }} while(0)
45
46static void cmd_ack(const unsigned char cmd, const unsigned char status)
47{
48 IAP_TX_INIT(0x00, 0x02);
49 IAP_TX_PUT(status);
50 IAP_TX_PUT(cmd);
51 iap_send_tx();
52}
53
54#define cmd_ok(cmd) cmd_ack((cmd), IAP_ACK_OK)
55
56static void cmd_pending(const unsigned char cmd, const uint32_t msdelay)
57{
58 IAP_TX_INIT(0x00, 0x02);
59 IAP_TX_PUT(0x06);
60 IAP_TX_PUT(cmd);
61 IAP_TX_PUT_U32(msdelay);
62 iap_send_tx();
63}
64
65void iap_handlepkt_mode0(const unsigned int len, const unsigned char *buf)
66{
67 unsigned int cmd = buf[1];
68
69 /* We expect at least two bytes in the buffer, one for the
70 * lingo, one for the command
71 */
72 CHECKLEN(2);
73
74 switch (cmd) {
75 /* RequestIdentify (0x00)
76 *
77 * Sent from the iPod to the device
78 */
79
80 /* Identify (0x01)
81 * This command is deprecated.
82 *
83 * It is used by a device to inform the iPod of the devices
84 * presence and of the lingo the device supports.
85 *
86 * Also, it is used to negotiate power for RF transmitters
87 *
88 * Packet format (offset in buf[]: Description)
89 * 0x00: Lingo ID: General Lingo, always 0x00
90 * 0x01: Command, always 0x01
91 * 0x02: Lingo supported by the device
92 *
93 * Some RF transmitters use an extended version of this
94 * command:
95 *
96 * 0x00: Lingo ID: General Lingo, always 0x00
97 * 0x01: Command, always 0x01
98 * 0x02: Lingo supported by the device, always 0x05 (RF Transmitter)
99 * 0x03: Reserved, always 0x00
100 * 0x04: Number of valid bits in the following fields
101 * 0x05-N: Datafields holding the number of bits specified in 0x04
102 *
103 * Returns: (none)
104 *
105 * TODO:
106 * BeginHighPower/EndHighPower should be send in the periodic handler,
107 * depending on the current play status
108 */
109 case 0x01:
110 {
111 unsigned char lingo = buf[2];
112
113 /* This is sufficient even for Lingo 0x05, as we are
114 * not actually reading from the extended bits for now
115 */
116 CHECKLEN(3);
117
118 /* Issuing this command exits any extended interface states
119 * and resets authentication
120 */
121 iap_interface_state_change(IST_STANDARD);
122 iap_reset_device(&device);
123
124 switch (lingo) {
125 case 0x04:
126 {
127 /* A single lingo device negotiating the
128 * extended interface lingo. This causes an interface
129 * state change.
130 */
131 iap_interface_state_change(IST_EXTENDED);
132 break;
133 }
134
135 case 0x05:
136 {
137 /* FM transmitter sends this: */
138 /* FF 55 06 00 01 05 00 02 01 F1 (mode switch) */
139 sleep(HZ/3);
140 /* RF Transmitter: Begin transmission */
141 IAP_TX_INIT(0x05, 0x02);
142
143 iap_send_tx();
144 break;
145 }
146 }
147
148 if (lingo < 32) {
149 /* All devices that Identify get access to Lingoes 0x00 and 0x02 */
150 device.lingoes = BIT_N(0x00) | BIT_N(0x02);
151
152 device.lingoes |= BIT_N(lingo);
153
154 /* Devices that Identify with Lingo 0x04 also gain access
155 * to Lingo 0x03
156 */
157 if (lingo == 0x04)
158 device.lingoes |= BIT_N(0x03);
159 } else {
160 device.lingoes = 0;
161 }
162 break;
163 }
164
165 /* ACK (0x02)
166 *
167 * Sent from the iPod to the device
168 */
169
170 /* RequestRemoteUIMode (0x03)
171 *
172 * Request the current Extended Interface Mode state
173 * This command may be used only if the accessory requests Lingo 0x04
174 * during its identification process.
175 *
176 * Packet format (offset in buf[]: Description)
177 * 0x00: Lingo ID: General Lingo, always 0x00
178 * 0x01: Command, always 0x03
179 *
180 * Returns on success:
181 * ReturnRemoteUIMode
182 *
183 * Packet format (offset in data[]: Description)
184 * 0x00: Lingo ID: General Lingo, always 0x00
185 * 0x01: Command, always 0x04
186 * 0x02: Current Extended Interface Mode (zero: false, non-zero: true)
187 *
188 * Returns on failure:
189 * IAP_ACK_BAD_PARAM
190 */
191 case 0x03:
192 {
193 if (!DEVICE_LINGO_SUPPORTED(0x04)) {
194 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
195 break;
196 }
197
198 IAP_TX_INIT(0x00, 0x04);
199 if (interface_state == IST_EXTENDED)
200 IAP_TX_PUT(0x01);
201 else
202 IAP_TX_PUT(0x00);
203
204 iap_send_tx();
205 break;
206 }
207
208 /* ReturnRemoteUIMode (0x04)
209 *
210 * Sent from the iPod to the device
211 */
212
213 /* EnterRemoteUIMode (0x05)
214 *
215 * Request Extended Interface Mode
216 * This command may be used only if the accessory requests Lingo 0x04
217 * during its identification process.
218 *
219 * Packet format (offset in buf[]: Description)
220 * 0x00: Lingo ID: General Lingo, always 0x00
221 * 0x01: Command, always 0x05
222 *
223 * Returns on success:
224 * IAP_ACK_PENDING
225 * IAP_ACK_OK
226 *
227 * Returns on failure:
228 * IAP_ACK_BAD_PARAM
229 */
230 case 0x05:
231 {
232 if (!DEVICE_LINGO_SUPPORTED(0x04)) {
233 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
234 break;
235 }
236
237 cmd_pending(cmd, 1000);
238 iap_interface_state_change(IST_EXTENDED);
239 cmd_ok(cmd);
240 break;
241 }
242
243 /* ExitRemoteUIMode (0x06)
244 *
245 * Leave Extended Interface Mode
246 * This command may be used only if the accessory requests Lingo 0x04
247 * during its identification process.
248 *
249 * Packet format (offset in buf[]: Description)
250 * 0x00: Lingo ID: General Lingo, always 0x00
251 * 0x01: Command, always 0x06
252 *
253 * Returns on success:
254 * IAP_ACK_PENDING
255 * IAP_ACK_OK
256 *
257 * Returns on failure:
258 * IAP_ACK_BAD_PARAM
259 */
260 case 0x06:
261 {
262 if (!DEVICE_LINGO_SUPPORTED(0x04)) {
263 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
264 break;
265 }
266
267 cmd_pending(cmd, 1000);
268 iap_interface_state_change(IST_STANDARD);
269 cmd_ok(cmd);
270 break;
271 }
272
273 /* RequestiPodName (0x07)
274 *
275 * Retrieves the name of the iPod
276 *
277 * Packet format (offset in buf[]: Description)
278 * 0x00: Lingo ID: General Lingo, always 0x00
279 * 0x01: Command, always 0x07
280 *
281 * Returns:
282 * ReturniPodName
283 *
284 * Packet format (offset in data[]: Description)
285 * 0x00: Lingo ID: General Lingo, always 0x00
286 * 0x01: Command, always 0x08
287 * 0x02-0xNN: iPod name as NULL-terminated UTF8 string
288 */
289 case 0x07:
290 {
291 IAP_TX_INIT(0x00, 0x08);
292 IAP_TX_PUT_STRING("ROCKBOX");
293
294 iap_send_tx();
295 break;
296 }
297
298 /* ReturniPodName (0x08)
299 *
300 * Sent from the iPod to the device
301 */
302
303 /* RequestiPodSoftwareVersion (0x09)
304 *
305 * Returns the major, minor and revision numbers of the iPod
306 * software version. This not any Lingo protocol version.
307 *
308 * Packet format (offset in buf[]: Description)
309 * 0x00: Lingo ID: General Lingo, always 0x00
310 * 0x01: Command, always 0x09
311 *
312 * Returns:
313 * ReturniPodSoftwareVersion
314 *
315 * Packet format (offset in data[]: Description)
316 * 0x00: Lingo ID: General Lingo, always 0x00
317 * 0x01: Command, always 0x0A
318 * 0x02: iPod major software version
319 * 0x03: iPod minor software version
320 * 0x04: iPod revision software version
321 */
322 case 0x09:
323 {
324 IAP_TX_INIT(0x00, 0x0A);
325 IAP_TX_PUT(IAP_IPOD_FIRMWARE_MAJOR);
326 IAP_TX_PUT(IAP_IPOD_FIRMWARE_MINOR);
327 IAP_TX_PUT(IAP_IPOD_FIRMWARE_REV);
328
329 iap_send_tx();
330 break;
331 }
332
333 /* ReturniPodSoftwareVersion (0x0A)
334 *
335 * Sent from the iPod to the device
336 */
337
338 /* RequestiPodSerialNum (0x0B)
339 *
340 * Returns the iPod serial number
341 *
342 * Packet format (offset in buf[]: Description)
343 * 0x00: Lingo ID: General Lingo, always 0x00
344 * 0x01: Command, always 0x0B
345 *
346 * Returns:
347 * ReturniPodSerialNumber
348 *
349 * Packet format (offset in data[]: Description)
350 * 0x00: Lingo ID: General Lingo, always 0x00
351 * 0x01: Command, always 0x0C
352 * 0x02-0xNN: Serial number as NULL-terminated UTF8 string
353 */
354 case 0x0B:
355 {
356 IAP_TX_INIT(0x00, 0x0C);
357 IAP_TX_PUT_STRING("0123456789");
358
359 iap_send_tx();
360 break;
361 }
362
363 /* ReturniPodSerialNum (0x0C)
364 *
365 * Sent from the iPod to the device
366 */
367
368 /* RequestiPodModelNum (0x0D)
369 *
370 * Returns the model number as a 32bit unsigned integer and
371 * as a string.
372 *
373 * Packet format (offset in buf[]: Description)
374 * 0x00: Lingo ID: General Lingo, always 0x00
375 * 0x01: Command, always 0x0D
376 *
377 * Returns:
378 * ReturniPodModelNum
379 *
380 * Packet format (offset in data[]: Description)
381 * 0x00: Lingo ID: General Lingo, always 0x00
382 * 0x01: Command, always 0x0E
383 * 0x02-0x05: Model number as 32bit integer
384 * 0x06-0xNN: Model number as NULL-terminated UTF8 string
385 */
386 case 0x0D:
387 {
388 IAP_TX_INIT(0x00, 0x0E);
389 IAP_TX_PUT_U32(IAP_IPOD_MODEL);
390 IAP_TX_PUT_STRING("ROCKBOX");
391
392 iap_send_tx();
393 break;
394 }
395
396 /* ReturniPodSerialNum (0x0E)
397 *
398 * Sent from the iPod to the device
399 */
400
401 /* RequestLingoProtocolVersion (0x0F)
402 *
403 * Packet format (offset in buf[]: Description)
404 * 0x00: Lingo ID: General Lingo, always 0x00
405 * 0x01: Command, always 0x0F
406 * 0x02: Lingo for which to request version information
407 *
408 * Returns on success:
409 * ReturnLingoProtocolVersion
410 *
411 * Packet format (offset in data[]: Description)
412 * 0x00: Lingo ID: General Lingo, always 0x00
413 * 0x01: Command, always 0x10
414 * 0x02: Lingo for which version information is returned
415 * 0x03: Major protocol version for the given lingo
416 * 0x04: Minor protocol version for the given lingo
417 *
418 * Returns on failure:
419 * IAP_ACK_BAD_PARAM
420 */
421 case 0x0F:
422 {
423 unsigned char lingo = buf[2];
424
425 CHECKLEN(3);
426
427 /* Supported lingos and versions are read from the lingo_versions
428 * array
429 */
430 if (LINGO_SUPPORTED(lingo)) {
431 IAP_TX_INIT(0x00, 0x10);
432 IAP_TX_PUT(lingo);
433 IAP_TX_PUT(LINGO_MAJOR(lingo));
434 IAP_TX_PUT(LINGO_MINOR(lingo));
435
436 iap_send_tx();
437 } else {
438 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
439 }
440 break;
441 }
442
443 /* ReturnLingoProtocolVersion (0x10)
444 *
445 * Sent from the iPod to the device
446 */
447
448 /* IdentifyDeviceLingoes (0x13);
449 *
450 * Used by a device to inform the iPod of the devices
451 * presence and of the lingoes the device supports.
452 *
453 * Packet format (offset in buf[]: Description)
454 * 0x00: Lingo ID: General Lingo, always 0x00
455 * 0x01: Command, always 0x13
456 * 0x02-0x05: Device lingoes spoken
457 * 0x06-0x09: Device options
458 * 0x0A-0x0D: Device ID. Only important for authentication
459 *
460 * Returns on success:
461 * IAP_ACK_OK
462 *
463 * Returns on failure:
464 * IAP_ACK_CMD_FAILED
465 */
466 case 0x13:
467 {
468 uint32_t lingoes = get_u32(&buf[2]);
469 uint32_t options = get_u32(&buf[6]);
470 uint32_t deviceid = get_u32(&buf[0x0A]);
471 bool seen_unsupported = false;
472 unsigned char i;
473
474 CHECKLEN(14);
475
476 /* Issuing this command exits any extended interface states */
477 iap_interface_state_change(IST_STANDARD);
478
479 /* Loop through the lingoes advertised by the device.
480 * If it tries to use a lingo we do not support, return
481 * a Command Failed ACK.
482 */
483 for(i=0; i<32; i++) {
484 if (lingoes & BIT_N(i)) {
485 /* Bit set by device */
486 if (!LINGO_SUPPORTED(i)) {
487 seen_unsupported = true;
488 }
489 }
490 }
491
492 /* Bit 0 _must_ be set by the device */
493 if (!(lingoes & 1)) {
494 seen_unsupported = true;
495 }
496
497 /* Specifying a deviceid without requesting authentication is
498 * an error
499 */
500 if (deviceid && !(options & 0x03))
501 seen_unsupported = true;
502
503 /* Specifying authentication without a deviceid is an error */
504 if (!deviceid && (options & 0x03))
505 seen_unsupported = true;
506
507 device.lingoes = 0;
508 if (seen_unsupported) {
509 cmd_ack(cmd, IAP_ACK_CMD_FAILED);
510 break;
511 }
512 iap_reset_device(&device);
513 device.lingoes = lingoes;
514
515 /* Devices using IdentifyDeviceLingoes get power off notifications */
516 device.do_power_notify = true;
517
518 /* If a new authentication is requested, start the auth
519 * process.
520 * The periodic handler will take care of sending out the
521 * GetDevAuthenticationInfo packet
522 *
523 * If no authentication is requested, schedule the start of
524 * GetAccessoryInfo
525 */
526 if (deviceid && (options & 0x03) && !DEVICE_AUTH_RUNNING) {
527 device.auth.state = AUST_INIT;
528 } else {
529 device.accinfo = ACCST_INIT;
530 }
531
532 cmd_ok(cmd);
533
534 /* Bit 5: RF Transmitter lingo */
535 if (lingoes & (1 << 5))
536 {
537 /* FM transmitter sends this: */
538 /* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/
539
540 /* GetAccessoryInfo */
541 unsigned char data2[] = {0x00, 0x27, 0x00};
542 iap_send_pkt(data2, sizeof(data2));
543 /* RF Transmitter: Begin transmission */
544 unsigned char data3[] = {0x05, 0x02};
545 iap_send_pkt(data3, sizeof(data3));
546 }
547
548
549#if 0
550 /* Bit 7: RF Tuner lingo */
551 if (lingoes & (1 << 7))
552 {
553 /* ipod fm remote sends this: */
554 /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 */
555 radio_present = 1;
556 /* GetDevAuthenticationInfo */
557 unsigned char data4[] = {0x00, 0x14};
558 iap_send_pkt(data4, sizeof(data4));
559 }
560#endif
561 break;
562 }
563
564 /* GetDevAuthenticationInfo (0x14)
565 *
566 * Sent from the iPod to the device
567 */
568
569 /* RetDevAuthenticationInfo (0x15)
570 *
571 * Send certificate information from the device to the iPod.
572 * The certificate may come in multiple parts and has
573 * to be reassembled.
574 *
575 * Packet format (offset in buf[]: Description)
576 * 0x00: Lingo ID: General Lingo, always 0x00
577 * 0x01: Command, always 0x15
578 * 0x02: Authentication major version
579 * 0x03: Authentication minor version
580 * 0x04: Certificate current section index
581 * 0x05: Certificate maximum section index
582 * 0x06-0xNN: Certificate data
583 *
584 * Returns on success:
585 * IAP_ACK_OK for intermediate sections
586 * AckDevAuthenticationInfo for the last section
587 *
588 * Returns on failure:
589 * IAP_ACK_BAD_PARAMETER
590 * AckDevAuthenticationInfo for version mismatches
591 *
592 */
593 case 0x15:
594 {
595 /* There are two formats of this packet. One with only
596 * the version information bytes (for Auth version 1.0)
597 * and the long form shown above
598 */
599 CHECKLEN(4);
600
601 if (!DEVICE_AUTH_RUNNING) {
602 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
603 break;
604 }
605
606 /* We only support version 2.0 */
607 if ((buf[2] != 2) || (buf[3] != 0)) {
608 /* Version mismatches are signalled by AckDevAuthenticationInfo
609 * with the status set to Authentication Information unsupported
610 */
611 iap_reset_auth(&(device.auth));
612
613 IAP_TX_INIT(0x00, 0x16);
614 IAP_TX_PUT(0x08);
615
616 iap_send_tx();
617 break;
618 }
619
620 /* There must be at least one byte of certificate data
621 * in the packet
622 */
623 CHECKLEN(7);
624
625 switch (device.auth.state)
626 {
627 /* This is the first packet. Note the maximum section number
628 * so we can check it later.
629 */
630 case AUST_CERTREQ:
631 {
632 device.auth.max_section = buf[5];
633 device.auth.state = AUST_CERTBEG;
634
635 /* Intentional fall-through */
636 }
637 /* All following packets */
638 case AUST_CERTBEG:
639 {
640 /* Check if this is the expected section */
641 if (buf[4] != device.auth.next_section) {
642 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
643 break;
644 }
645
646 /* Is this the last section? */
647 if (device.auth.next_section == device.auth.max_section) {
648 /* If we could really do authentication we'd have to
649 * check the certificate here. Since we can't, just acknowledge
650 * the packet with an "everything OK" AckDevAuthenticationInfo
651 *
652 * Also, start GetAccessoryInfo process
653 */
654 IAP_TX_INIT(0x00, 0x16);
655 IAP_TX_PUT(0x00);
656
657 iap_send_tx();
658 device.auth.state = AUST_CERTDONE;
659 device.accinfo = ACCST_INIT;
660 } else {
661 device.auth.next_section++;
662 cmd_ok(cmd);
663 }
664 break;
665 }
666
667 default:
668 {
669 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
670 break;
671 }
672 }
673
674 break;
675 }
676
677 /* AckDevAuthenticationInfo (0x16)
678 *
679 * Sent from the iPod to the device
680 */
681
682 /* GetDevAuthenticationSignature (0x17)
683 *
684 * Sent from the iPod to the device
685 */
686
687 /* RetDevAuthenticationSignature (0x18)
688 *
689 * Return a calculated signature based on the device certificate
690 * and the challenge sent with GetDevAuthenticationSignature
691 *
692 * Packet format (offset in buf[]: Description)
693 * 0x00: Lingo ID: General Lingo, always 0x00
694 * 0x01: Command, always 0x17
695 * 0x02-0xNN: Certificate data
696 *
697 * Returns on success:
698 * AckDevAuthenticationStatus
699 *
700 * Packet format (offset in data[]: Description)
701 * 0x00: Lingo ID: General Lingo, always 0x00
702 * 0x01: Command, always 0x19
703 * 0x02: Status (0x00: OK)
704 *
705 * Returns on failure:
706 * IAP_ACK_BAD_PARAM
707 *
708 * TODO:
709 * There is a timeout of 75 seconds between GetDevAuthenticationSignature
710 * and RetDevAuthenticationSignature for Auth 2.0. This is currently not
711 * checked.
712 */
713 case 0x18:
714 {
715 if (device.auth.state != AUST_CHASENT) {
716 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
717 break;
718 }
719
720 /* Here we could check the signature. Since we can't, just
721 * acknowledge and go to authenticated status
722 */
723 IAP_TX_INIT(0x00, 0x19);
724 IAP_TX_PUT(0x00);
725
726 iap_send_tx();
727 device.auth.state = AUST_AUTH;
728 break;
729 }
730
731 /* AckDevAuthenticationStatus (0x19)
732 *
733 * Sent from the iPod to the device
734 */
735
736 /* GetiPodAuthenticationInfo (0x1A)
737 *
738 * Obtain authentication information from the iPod.
739 * This cannot be implemented without posessing an Apple signed
740 * certificate and the corresponding private key.
741 *
742 * Packet format (offset in buf[]: Description)
743 * 0x00: Lingo ID: General Lingo, always 0x00
744 * 0x01: Command, always 0x1A
745 *
746 * This command requires authentication
747 *
748 * Returns:
749 * IAP_ACK_CMD_FAILED
750 */
751 case 0x1A:
752 {
753 CHECKAUTH;
754
755 cmd_ack(cmd, IAP_ACK_CMD_FAILED);
756 break;
757 }
758
759 /* RetiPodAuthenticationInfo (0x1B)
760 *
761 * Sent from the iPod to the device
762 */
763
764 /* AckiPodAuthenticationInfo (0x1C)
765 *
766 * Confirm authentication information from the iPod.
767 * This cannot be implemented without posessing an Apple signed
768 * certificate and the corresponding private key.
769 *
770 * Packet format (offset in buf[]: Description)
771 * 0x00: Lingo ID: General Lingo, always 0x00
772 * 0x01: Command, always 0x1C
773 * 0x02: Authentication state (0x00: OK)
774 *
775 * This command requires authentication
776 *
777 * Returns: (none)
778 */
779 case 0x1C:
780 {
781 CHECKAUTH;
782
783 break;
784 }
785
786 /* GetiPodAuthenticationSignature (0x1D)
787 *
788 * Send challenge information to the iPod.
789 * This cannot be implemented without posessing an Apple signed
790 * certificate and the corresponding private key.
791 *
792 * Packet format (offset in buf[]: Description)
793 * 0x00: Lingo ID: General Lingo, always 0x00
794 * 0x01: Command, always 0x1D
795 * 0x02-0x15: Challenge
796 *
797 * This command requires authentication
798 *
799 * Returns:
800 * IAP_ACK_CMD_FAILED
801 */
802 case 0x1D:
803 {
804 CHECKAUTH;
805
806 cmd_ack(cmd, IAP_ACK_CMD_FAILED);
807 break;
808 }
809
810 /* RetiPodAuthenticationSignature (0x1E)
811 *
812 * Sent from the iPod to the device
813 */
814
815 /* AckiPodAuthenticationStatus (0x1F)
816 *
817 * Confirm chellenge information from the iPod.
818 * This cannot be implemented without posessing an Apple signed
819 * certificate and the corresponding private key.
820 *
821 * Packet format (offset in buf[]: Description)
822 * 0x00: Lingo ID: General Lingo, always 0x00
823 * 0x01: Command, always 0x1C
824 * 0x02: Challenge state (0x00: OK)
825 *
826 * This command requires authentication
827 *
828 * Returns: (none)
829 */
830 case 0x1F:
831 {
832 CHECKAUTH;
833
834 break;
835 }
836
837 /* NotifyiPodStateChange (0x23)
838 *
839 * Sent from the iPod to the device
840 */
841
842 /* GetIpodOptions (0x24)
843 *
844 * Request supported features of the iPod
845 *
846 * Packet format (offset in buf[]: Description)
847 * 0x00: Lingo ID: General Lingo, always 0x00
848 * 0x01: Command, always 0x24
849 *
850 * Retuns:
851 * RetiPodOptions
852 *
853 * Packet format (offset in data[]: Description)
854 * 0x00: Lingo ID: General Lingo, always 0x00
855 * 0x01: Command, always 0x25
856 * 0x02-0x09: Options as a bitfield
857 */
858 case 0x24:
859 {
860 /* There are only two features that can be communicated via this
861 * function, video support and the ability to control line-out usage.
862 * Rockbox supports neither
863 */
864 IAP_TX_INIT(0x00, 0x25);
865 IAP_TX_PUT_U32(0x00);
866 IAP_TX_PUT_U32(0x00);
867
868 iap_send_tx();
869 break;
870 }
871
872 /* RetiPodOptions (0x25)
873 *
874 * Sent from the iPod to the device
875 */
876
877 /* GetAccessoryInfo (0x27)
878 *
879 * Sent from the iPod to the device
880 */
881
882 /* RetAccessoryInfo (0x28)
883 *
884 * Send information about the device
885 *
886 * Packet format (offset in buf[]: Description)
887 * 0x00: Lingo ID: General Lingo, always 0x00
888 * 0x01: Command, always 0x28
889 * 0x02: Accessory info type
890 * 0x03-0xNN: Accessory information (depends on 0x02)
891 *
892 * Returns: (none)
893 *
894 * TODO: Actually do something with the information received here.
895 * Some devices actually expect us to request the data they
896 * offer, so completely ignoring this does not work, either.
897 */
898 case 0x28:
899 {
900 CHECKLEN(3);
901
902 switch (buf[0x02])
903 {
904 /* Info capabilities */
905 case 0x00:
906 {
907 CHECKLEN(7);
908
909 device.capabilities = get_u32(&buf[0x03]);
910 /* Type 0x00 was already queried, that's where this information comes from */
911 device.capabilities_queried = 0x01;
912 device.capabilities &= ~0x01;
913 break;
914 }
915
916 /* For now, ignore all other information */
917 default:
918 {
919 break;
920 }
921 }
922
923 /* If there are any unqueried capabilities left, do so */
924 if (device.capabilities)
925 device.accinfo = ACCST_DATA;
926
927 break;
928 }
929
930 /* GetiPodPreferences (0x29)
931 *
932 * Retrieve information about the current state of the
933 * iPod.
934 *
935 * Packet format (offset in buf[]: Description)
936 * 0x00: Lingo ID: General Lingo, always 0x00
937 * 0x01: Command, always 0x29
938 * 0x02: Information class requested
939 *
940 * This command requires authentication
941 *
942 * Returns on success:
943 * RetiPodPreferences
944 *
945 * Packet format (offset in data[]: Description)
946 * 0x00: Lingo ID: General Lingo, always 0x00
947 * 0x01: Command, always 0x2A
948 * 0x02: Information class provided
949 * 0x03: Information
950 *
951 * Returns on failure:
952 * IAP_ACK_BAD_PARAM
953 */
954 case 0x29:
955 {
956 CHECKLEN(3);
957 CHECKAUTH;
958
959 IAP_TX_INIT(0x00, 0x2A);
960 /* The only information really supported is 0x03, Line-out usage.
961 * All others are video related
962 */
963 if (buf[2] == 0x03) {
964 IAP_TX_PUT(0x03);
965 IAP_TX_PUT(0x01); /* Line-out enabled */
966
967 iap_send_tx();
968 } else {
969 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
970 }
971
972 break;
973 }
974
975 /* RetiPodPreference (0x2A)
976 *
977 * Sent from the iPod to the device
978 */
979
980 /* SetiPodPreferences (0x2B)
981 *
982 * Set preferences on the iPod
983 *
984 * Packet format (offset in buf[]: Description)
985 * 0x00: Lingo ID: General Lingo, always 0x00
986 * 0x01: Command, always 0x29
987 * 0x02: Prefecence class requested
988 * 0x03: Preference setting
989 * 0x04: Restore on exit
990 *
991 * This command requires authentication
992 *
993 * Returns on success:
994 * IAP_ACK_OK
995 *
996 * Returns on failure:
997 * IAP_ACK_BAD_PARAM
998 * IAP_ACK_CMD_FAILED
999 */
1000 case 0x2B:
1001 {
1002 CHECKLEN(5);
1003 CHECKAUTH;
1004
1005 /* The only information really supported is 0x03, Line-out usage.
1006 * All others are video related
1007 */
1008 if (buf[2] == 0x03) {
1009 /* If line-out disabled is requested, reply with IAP_ACK_CMD_FAILED,
1010 * otherwise with IAP_ACK_CMD_OK
1011 */
1012 if (buf[3] == 0x00) {
1013 cmd_ack(cmd, IAP_ACK_CMD_FAILED);
1014 } else {
1015 cmd_ok(cmd);
1016 }
1017 } else {
1018 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
1019 }
1020
1021 break;
1022 }
1023
1024 /* The default response is IAP_ACK_BAD_PARAM */
1025 default:
1026 {
1027#ifdef LOGF_ENABLE
1028 logf("iap: Unsupported Mode00 Command");
1029#else
1030 cmd_ack(cmd, IAP_ACK_BAD_PARAM);
1031#endif
1032 break;
1033 }
1034 }
1035}