summaryrefslogtreecommitdiff
path: root/tools/iap/iap-verbose.pl
diff options
context:
space:
mode:
Diffstat (limited to 'tools/iap/iap-verbose.pl')
-rw-r--r--tools/iap/iap-verbose.pl1856
1 files changed, 1856 insertions, 0 deletions
diff --git a/tools/iap/iap-verbose.pl b/tools/iap/iap-verbose.pl
new file mode 100644
index 0000000000..ed25de7548
--- /dev/null
+++ b/tools/iap/iap-verbose.pl
@@ -0,0 +1,1856 @@
1#!/usr/bin/perl -w
2
3package iap::decode;
4
5use Device::iPod;
6use Data::Dumper;
7use strict;
8
9sub new {
10 my $class = shift;
11 my $self = {-state => {}};
12
13 return bless($self, $class);
14}
15
16sub display {
17 my $self = shift;
18 my $lingo = shift;
19 my $command = shift;
20 my $data = shift;
21 my $name;
22 my $handler;
23 my $r;
24
25
26 $name = sprintf("_h_%02x_%04x", $lingo, $command);
27 $handler = $self->can($name);
28 if ($handler) {
29 unless(exists($self->{-state}->{$name})) {
30 $self->{-state}->{$name} = {};
31 }
32 $r = $handler->($self, $data, $self->{-state}->{$name});
33 } else {
34 $r = $self->generic($lingo, $command, $data);
35 }
36
37 printf("\n");
38 return $r;
39}
40
41sub generic {
42 my $self = shift;
43 my $lingo = shift;
44 my $command = shift;
45 my $data = shift;
46
47 printf("Unknown command\n");
48 printf(" Lingo: 0x%02x\n", $lingo);
49 printf(" Command 0x%04x\n", $command);
50 printf(" Data: %s\n", Device::iPod->_hexstring($data));
51
52 exit(1);
53
54 return 1;
55}
56
57sub _h_00_0001 {
58 my $self = shift;
59 my $data = shift;
60 my $state = shift;
61 my $lingo = shift;
62
63 $lingo = unpack("C", $data);
64
65 printf("Identify (0x00, 0x01) D->I\n");
66 printf(" Lingo: 0x%02x\n", $lingo);
67
68 return 1;
69}
70
71sub _h_00_0002 {
72 my $self = shift;
73 my $data = shift;
74 my $state = shift;
75 my $res;
76 my $cmd;
77 my $delay;
78
79 ($res, $cmd, $delay) = unpack("CCN", $data);
80
81 printf("ACK (0x00, 0x02) I->D\n");
82 printf(" Acknowledged command: 0x%02x\n", $cmd);
83 printf(" Status: %s (%d)\n",
84 ("Success",
85 "ERROR: Unknown Database Category",
86 "ERROR: Command Failed",
87 "ERROR: Out Of Resource",
88 "ERROR: Bad Parameter",
89 "ERROR: Unknown ID",
90 "Command Pending",
91 "ERROR: Not Authenticated",
92 "ERROR: Bad Authentication Version",
93 "ERROR: Accessory Power Mode Request Failed",
94 "ERROR: Certificate Invalid",
95 "ERROR: Certificate permissions invalid",
96 "ERROR: File is in use",
97 "ERROR: Invalid file handle",
98 "ERROR: Directory not empty",
99 "ERROR: Operation timed out",
100 "ERROR: Command unavailable in this iPod mode",
101 "ERROR: Invalid accessory resistor ID",
102 "Reserved",
103 "Reserved",
104 "Reserved",
105 "ERROR: Maximum number of accessory connections already reached")[$res], $res);
106 if ($res == 6) {
107 $delay = unpack("xxN", $data);
108 printf(" Delay: %d ms\n", $delay);
109 }
110
111 return 1;
112}
113
114sub _h_00_0005 {
115 my $self = shift;
116 my $data = shift;
117 my $state = shift;
118
119 printf("EnterRemoteUIMode (0x00, 0x05) D->I\n");
120
121 return 1;
122}
123
124sub _h_00_000d {
125 my $self = shift;
126 my $data = shift;
127 my $state = shift;
128
129 printf("RequestiPodModelNum (0x00, 0x0D) D->I\n");
130
131 return 1;
132}
133
134sub _h_00_000e {
135 my $self = shift;
136 my $data = shift;
137 my $state = shift;
138 my ($modelnum, $name);
139
140 ($modelnum, $name) = unpack("NZ*", $data);
141
142 printf("ReturniPodModelNum (0x00, 0x0E) I->D\n");
143 printf(" Model number: %08x\n", $modelnum);
144 printf(" Model name: %s\n", $name);
145
146 return 1;
147}
148
149sub _h_00_000f {
150 my $self = shift;
151 my $data = shift;
152 my $state = shift;
153 my $lingo;
154
155 $lingo = unpack("C", $data);
156
157 printf("RequestLingoProtocolVersion (0x00, 0x0F) D->I\n");
158 printf(" Lingo: 0x%02x\n", $lingo);
159
160 return 1;
161}
162
163sub _h_00_0010 {
164 my $self = shift;
165 my $data = shift;
166 my $state = shift;
167 my ($lingo, $maj, $min);
168
169 ($lingo, $maj, $min) = unpack("CCC", $data);
170
171 printf("ReturnLingoProtocolVersion (0x00, 0x10) I->D\n");
172 printf(" Lingo: 0x%02x\n", $lingo);
173 printf(" Version: %d.%02d\n", $maj, $min);
174
175 return 1;
176}
177
178
179sub _h_00_0013 {
180 my $self = shift;
181 my $data = shift;
182 my $state = shift;
183 my @lingolist;
184 my ($lingoes, $options, $devid);
185
186 ($lingoes, $options, $devid) = unpack("N3", $data);
187
188 foreach (0..31) {
189 push(@lingolist, $_) if ($lingoes & (1 << $_));
190 }
191
192 printf("IdentifyDeviceLingoes (0x00, 0x13) D->I\n");
193 printf(" Supported lingoes: %s\n", join(", ", @lingolist));
194 printf(" Options:\n");
195 printf(" Authentication: %s\n", ("None", "Defer (1.0)", "Immediate (2.0)", "Reserved")[$options & 0x03]);
196 printf(" Power: %s\n", ("Low", "Intermittent high", "Reserved", "Constant high")[($options & 0x0C) >> 2]);
197 printf(" Device ID: 0x%08x\n", $devid);
198
199 delete($self->{-state}->{'_h_00_0015'});
200
201 return 1;
202}
203
204sub _h_00_0014 {
205 my $self = shift;
206 my $data = shift;
207 my $state = shift;
208
209 printf("GetDevAuthenticationInfo (0x00, 0x14) I->D\n");
210
211 return 1;
212}
213
214sub _h_00_0015 {
215 my $self = shift;
216 my $data = shift;
217 my $state = shift;
218 my ($amaj, $amin, $curidx, $maxidx, $certdata);
219
220 $state->{-curidx} = -1 unless(exists($state->{-curidx}));
221 $state->{-maxidx} = -1 unless(exists($state->{-maxidx}));
222 $state->{-cert} = '' unless(exists($state->{-cert}));
223
224 ($amaj, $amin, $curidx, $maxidx, $certdata) = unpack("CCCCa*", $data);
225
226 printf("RetDevAuthenticationInfo (0x00, 0x15) D->I\n");
227 printf(" Authentication version: %d.%d\n", $amaj, $amin);
228 printf(" Segment: %d of %d\n", $curidx, $maxidx);
229
230 if ($curidx-1 != $state->{-curidx}) {
231 printf(" WARNING! Out of order segment\n");
232 return 0;
233 }
234
235 if (($maxidx != $state->{-maxidx}) && ($state->{-maxidx} != -1)) {
236 printf(" WARNING! maxidx changed midstream\n");
237 return 0;
238 }
239
240 if ($curidx > $maxidx) {
241 printf(" WARNING! Too many segments\n");
242 return 0;
243 }
244
245 $state->{-curidx} = $curidx;
246 $state->{-maxidx} = $maxidx;
247 $state->{-cert} .= $certdata;
248
249 if ($curidx == $maxidx) {
250 printf(" Certificate: %s\n", Device::iPod->_hexstring($state->{-cert}));
251 }
252
253 return 1;
254}
255
256sub _h_00_0016 {
257 my $self = shift;
258 my $data = shift;
259 my $state = shift;
260 my $res;
261
262 $res = unpack("C", $data);
263
264 printf("AckDevAuthenticationInfo (0x00, 0x16) I->D\n");
265 printf(" Result: ");
266 if ($res == 0x00) {
267 printf("Authentication information supported\n");
268 } elsif ($res == 0x08) {
269 printf("Authentication information unpported\n");
270 } elsif ($res == 0x0A) {
271 printf("Certificate invalid\n");
272 } elsif ($res == 0x0B) {
273 printf("Certificate permissions are invalid\n");
274 } else {
275 printf("Unknown result 0x%02x\n", $res);
276 }
277
278 return 1;
279}
280
281sub _h_00_0017 {
282 my $self = shift;
283 my $data = shift;
284 my $state = shift;
285 my ($challenge, $retry);
286
287 printf("GetDevAuthenticationSignature (0x00, 0x17) I->D\n");
288
289 if (length($data) == 17) {
290 ($challenge, $retry) = unpack("a16C", $data);
291 } elsif (length($data) == 21) {
292 ($challenge, $retry) = unpack("a20C", $data);
293 } else {
294 printf(" WARNING! Unsupported data length: %d\n", length($data));
295 return 0;
296 }
297
298 printf(" Challenge: %s (%d bytes)\n", Device::iPod->_hexstring($challenge), length($challenge));
299 printf(" Retry counter: %d\n", $retry);
300
301 return 1;
302}
303
304sub _h_00_0018 {
305 my $self = shift;
306 my $data = shift;
307 my $state = shift;
308 my $reply;
309
310 printf("RetDevAuthenticationSignature (0x00, 0x18) D->I\n");
311 printf(" Data: %s\n", Device::iPod->_hexstring($data));
312
313 return 1;
314}
315
316sub _h_00_0019 {
317 my $self = shift;
318 my $data = shift;
319 my $state = shift;
320 my $res;
321
322 $res = unpack("C", $data);
323
324 printf("AckiPodAuthenticationInfo (0x00, 0x19) I->D\n");
325 printf(" Status: %s (%d)\n", (
326 "OK")[$res], $res);
327
328 return 1;
329}
330
331sub _h_00_0024 {
332 my $self = shift;
333 my $data = shift;
334 my $state = shift;
335
336 printf("GetiPodOptions (0x00, 0x24) D->I\n");
337
338 return 1;
339}
340
341sub _h_00_0025 {
342 my $self = shift;
343 my $data = shift;
344 my $state = shift;
345 my ($ophi, $oplo);
346
347 ($ophi, $oplo) = unpack("NN", $data);
348
349 printf("RetiPodOptions (0x00, 0x25) I->D\n");
350 printf(" Options:\n");
351 printf(" iPod supports SetiPodPreferences\n") if ($oplo & 0x02);
352 printf(" iPod supports video\n") if ($oplo & 0x01);
353
354 return 1;
355}
356
357
358sub _h_00_0027 {
359 my $self = shift;
360 my $data = shift;
361 my $state = shift;
362 my $acctype;
363 my $accparam;
364
365 $acctype = unpack("C", $data);
366
367 printf("GetAccessoryInfo (0x00, 0x27) I->D\n");
368 printf(" Accessory Info Type: %s (%d)\n", (
369 "Info capabilities",
370 "Name",
371 "Minimum supported iPod firmware version",
372 "Minimum supported lingo version",
373 "Firmware version",
374 "Hardware version",
375 "Manufacturer",
376 "Model Number",
377 "Serial Number",
378 "Maximum payload size")[$acctype], $acctype);
379 if ($acctype == 0x02) {
380 my ($modelid, $maj, $min, $rev);
381
382 ($modelid, $maj, $min, $rev) = unpack("xNCCC", $data);
383 printf(" Model ID: 0x%04x\n", $modelid);
384 printf(" iPod Firmware: %d.%d.%d\n", $maj, $min, $rev);
385 } elsif ($acctype == 0x03) {
386 my $lingo;
387
388 $lingo = unpack("xC", $data);
389 printf(" Lingo: 0x%02x\n", $lingo);
390 }
391
392 return 1;
393}
394
395sub _h_00_0028 {
396 my $self = shift;
397 my $data = shift;
398 my $state = shift;
399 my $acctype;
400 my $accparam;
401
402 $acctype = unpack("C", $data);
403
404 printf("RetAccessoryInfo (0x00, 0x28) D->I\n");
405 printf(" Accessory Info Type: %s (%d)\n", (
406 "Info capabilities",
407 "Name",
408 "Minimum supported iPod firmware version",
409 "Minimum supported lingo version",
410 "Firmware version",
411 "Hardware version",
412 "Manufacturer",
413 "Model Number",
414 "Serial Number",
415 "Maximum payload size")[$acctype], $acctype);
416
417 if ($acctype == 0x00) {
418 $accparam = unpack("xN", $data);
419 printf(" Accessory Info capabilities\n") if ($accparam & 0x01);
420 printf(" Accessory name\n") if ($accparam & 0x02);
421 printf(" Accessory minimum supported iPod firmware\n") if ($accparam & 0x04);
422 printf(" Accessory minimum supported lingo version\n") if ($accparam & 0x08);
423 printf(" Accessory firmware version\n") if ($accparam & 0x10);
424 printf(" Accessory hardware version\n") if ($accparam & 0x20);
425 printf(" Accessory manufacturer\n") if ($accparam & 0x40);
426 printf(" Accessory model number\n") if ($accparam & 0x80);
427 printf(" Accessory serial number\n") if ($accparam & 0x100);
428 printf(" Accessory incoming max packet size\n") if ($accparam & 0x200);
429 }
430
431 if ($acctype ~~ [0x01, 0x06, 0x07, 0x08]) {
432 $accparam = unpack("xZ*", $data);
433 printf(" Data: %s\n", $accparam);
434 }
435
436 if ($acctype == 0x02) {
437 $accparam = [ unpack("xNCCC", $data) ];
438 printf(" Model ID: %08x\n", $accparam->[0]);
439 printf(" Firmware version: %d.%02d.%02d\n", $accparam->[1], $accparam->[2], $accparam->[3]);
440 }
441
442 if ($acctype == 0x03) {
443 $accparam = [ unpack("xCCC", $data) ];
444 printf(" Lingo: %02x\n", $accparam->[0]);
445 printf(" Version: %d.%02d\n", $accparam->[1], $accparam->[2]);
446 }
447
448 if ($acctype ~~ [0x04, 0x05]) {
449 $accparam = [ unpack("xCCC", $data) ];
450 printf(" Version: %d.%02d.%02d\n", @{$accparam});
451 }
452
453 return 1;
454}
455
456sub _h_00_0029 {
457 my $self = shift;
458 my $data = shift;
459 my $state = shift;
460 my $class;
461
462 $class = unpack("C", $data);
463
464 printf("GetiPodPreferences (0x00, 0x29) D->I\n");
465 printf(" Class: %s (%d)\n", (
466 "Video out setting",
467 "Screen configuration",
468 "Video signal format",
469 "Line Out usage",
470 "(Reserved)",
471 "(Reserved)",
472 "(Reserved)",
473 "(Reserved)",
474 "Video out connection",
475 "Closed captioning",
476 "Video aspect ratio",
477 "(Reserved)",
478 "Subtitles",
479 "Video alternate audio channel")[$class], $class);
480
481 return 1;
482}
483
484sub _h_00_002b {
485 my $self = shift;
486 my $data = shift;
487 my $state = shift;
488 my ($class, $setting);
489
490 ($class, $setting) = unpack("CC", $data);
491
492 printf("SetiPodPreferences (0x00, 0x2B) D->I\n");
493 printf(" Class: %s (%d)\n", (
494 "Video out setting",
495 "Screen configuration",
496 "Video signal format",
497 "Line out usage",
498 "Reserved",
499 "Reserved",
500 "Reserved",
501 "Reserved",
502 "Video-out connection",
503 "Closed captioning",
504 "Video monitor aspect ratio",
505 "Reserved",
506 "Subtitles",
507 "Video alternate audio channel")[$class], $class);
508 printf(" Setting: %s (%d)\n", (
509 ["Off",
510 "On",
511 "Ask user"],
512 ["Fill screen",
513 "Fit to screen edge"],
514 ["NTSC",
515 "PAL"],
516 ["Not used",
517 "Used"],
518 [],
519 [],
520 [],
521 [],
522 ["None",
523 "Composite",
524 "S-video",
525 "Component"],
526 ["Off",
527 "On"],
528 ["4:3",
529 "16:9"],
530 [],
531 ["Off",
532 "On"],
533 ["Off",
534 "On"])[$class][$setting], $setting);
535
536 return 1;
537}
538
539sub _h_00_0038 {
540 my $self = shift;
541 my $data = shift;
542 my $state = shift;
543 my $transid;
544
545 $transid = unpack("n", $data);
546
547 printf("StartIDPS (0x00, 0x38) D->I\n");
548 printf(" TransID: %d\n", $transid);
549
550 return 1;
551}
552
553sub _h_00_003b {
554 my $self = shift;
555 my $data = shift;
556 my $state = shift;
557 my ($transid, $status);
558
559 ($transid, $status) = unpack("nC", $data);
560
561 printf("EndIDPS (0x00, 0x3B) D->I\n");
562 printf(" TransID: %d\n", $transid);
563 printf(" Action: %s (%d)\n", (
564 "Finished",
565 "Reset")[$status], $status);
566
567 return 1;
568}
569
570sub _h_00_004b {
571 my $self = shift;
572 my $data = shift;
573 my $state = shift;
574 my $lingo;
575
576 $lingo = unpack("C", $data);
577
578 printf("GetiPodOptionsForLingo (0x00, 0x4B) D->I\n");
579 printf(" Lingo: 0x%02x\n", $lingo);
580
581 return 1;
582}
583
584sub _h_02_0000 {
585 my $self = shift;
586 my $data = shift;
587 my $state = shift;
588 my @keys;
589
590 @keys = unpack("CCCC", $data);
591
592 printf("ContextButtonStatus (0x02, 0x00) D->I\n");
593 printf(" Buttons:\n");
594 printf(" Play/Pause\n") if ($keys[0] & 0x01);
595 printf(" Volume Up\n") if ($keys[0] & 0x02);
596 printf(" Volume Down\n") if ($keys[0] & 0x04);
597 printf(" Next Track\n") if ($keys[0] & 0x08);
598 printf(" Previous Track\n") if ($keys[0] & 0x10);
599 printf(" Next Album\n") if ($keys[0] & 0x20);
600 printf(" Previous Album\n") if ($keys[0] & 0x40);
601 printf(" Stop\n") if ($keys[0] & 0x80);
602
603 if (exists($keys[1])) {
604 printf(" Play/Resume\n") if ($keys[1] & 0x01);
605 printf(" Pause\n") if ($keys[1] & 0x02);
606 printf(" Mute toggle\n") if ($keys[1] & 0x04);
607 printf(" Next Chapter\n") if ($keys[1] & 0x08);
608 printf(" Previous Chapter\n") if ($keys[1] & 0x10);
609 printf(" Next Playlist\n") if ($keys[1] & 0x20);
610 printf(" Previous Playlist\n") if ($keys[1] & 0x40);
611 printf(" Shuffle Setting Advance\n") if ($keys[1] & 0x80);
612 }
613
614 if (exists($keys[2])) {
615 printf(" Repeat Setting Advance\n") if ($keys[2] & 0x01);
616 printf(" Power On\n") if ($keys[2] & 0x02);
617 printf(" Power Off\n") if ($keys[2] & 0x04);
618 printf(" Backlight for 30 seconds\n") if ($keys[2] & 0x08);
619 printf(" Begin FF\n") if ($keys[2] & 0x10);
620 printf(" Begin REW\n") if ($keys[2] & 0x20);
621 printf(" Menu\n") if ($keys[2] & 0x40);
622 printf(" Select\n") if ($keys[2] & 0x80);
623 }
624
625 if (exists($keys[3])) {
626 printf(" Up Arrow\n") if ($keys[3] & 0x01);
627 printf(" Down Arrow\n") if ($keys[3] & 0x02);
628 printf(" Backlight off\n") if ($keys[3] & 0x04);
629 }
630
631 return 1;
632}
633
634sub _h_02_0001 {
635 my $self = shift;
636 my $data = shift;
637 my $state = shift;
638 my $res;
639 my $cmd;
640
641 ($res, $cmd) = unpack("CC", $data);
642
643 printf("ACK (0x02, 0x01) I->D\n");
644 printf(" Acknowledged command: 0x%02x\n", $cmd);
645 printf(" Status: %s (%d)\n",
646 ("Success",
647 "ERROR: Unknown Database Category",
648 "ERROR: Command Failed",
649 "ERROR: Out Of Resource",
650 "ERROR: Bad Parameter",
651 "ERROR: Unknown ID",
652 "Command Pending",
653 "ERROR: Not Authenticated",
654 "ERROR: Bad Authentication Version",
655 "ERROR: Accessory Power Mode Request Failed",
656 "ERROR: Certificate Invalid",
657 "ERROR: Certificate permissions invalid",
658 "ERROR: File is in use",
659 "ERROR: Invalid file handle",
660 "ERROR: Directory not empty",
661 "ERROR: Operation timed out",
662 "ERROR: Command unavailable in this iPod mode",
663 "ERROR: Invalid accessory resistor ID",
664 "Reserved",
665 "Reserved",
666 "Reserved",
667 "ERROR: Maximum number of accessory connections already reached")[$res], $res);
668
669 return 1;
670}
671
672sub _h_03_0000 {
673 my $self = shift;
674 my $data = shift;
675 my $state = shift;
676 my $res;
677 my $cmd;
678
679 ($res, $cmd) = unpack("CC", $data);
680
681 printf("ACK (0x03, 0x00) I->D\n");
682 printf(" Acknowledged command: 0x%02x\n", $cmd);
683 printf(" Status: %s (%d)\n",
684 ("Success",
685 "ERROR: Unknown Database Category",
686 "ERROR: Command Failed",
687 "ERROR: Out Of Resource",
688 "ERROR: Bad Parameter",
689 "ERROR: Unknown ID",
690 "Command Pending",
691 "ERROR: Not Authenticated",
692 "ERROR: Bad Authentication Version",
693 "ERROR: Accessory Power Mode Request Failed",
694 "ERROR: Certificate Invalid",
695 "ERROR: Certificate permissions invalid",
696 "ERROR: File is in use",
697 "ERROR: Invalid file handle",
698 "ERROR: Directory not empty",
699 "ERROR: Operation timed out",
700 "ERROR: Command unavailable in this iPod mode",
701 "ERROR: Invalid accessory resistor ID",
702 "Reserved",
703 "Reserved",
704 "Reserved",
705 "ERROR: Maximum number of accessory connections already reached")[$res], $res);
706
707 return 1;
708}
709
710sub _h_03_0008 {
711 my $self = shift;
712 my $data = shift;
713 my $state = shift;
714 my $events;;
715
716 $events = unpack("N", $data);
717
718 printf("SetRemoteEventsNotification (0x03, 0x08) D->I\n");
719 printf(" Events:\n");
720 printf(" Track position in ms\n") if ($events & 0x00000001);
721 printf(" Track playback index\n") if ($events & 0x00000002);
722 printf(" Chapter index\n") if ($events & 0x00000004);
723 printf(" Play status\n") if ($events & 0x00000008);
724 printf(" Mute/UI volume\n") if ($events & 0x00000010);
725 printf(" Power/Battery\n") if ($events & 0x00000020);
726 printf(" Equalizer setting\n") if ($events & 0x00000040);
727 printf(" Shuffle setting\n") if ($events & 0x00000080);
728 printf(" Repeat setting\n") if ($events & 0x00000100);
729 printf(" Date and time setting\n") if ($events & 0x00000200);
730 printf(" Alarm setting\n") if ($events & 0x00000400);
731 printf(" Backlight state\n") if ($events & 0x00000800);
732 printf(" Hold switch state\n") if ($events & 0x00001000);
733 printf(" Sound check state\n") if ($events & 0x00002000);
734 printf(" Audiobook speed\n") if ($events & 0x00004000);
735 printf(" Track position in s\n") if ($events & 0x00008000);
736 printf(" Mute/UI/Absolute volume\n") if ($events & 0x00010000);
737
738 return 1;
739}
740
741sub _h_03_0009 {
742 my $self = shift;
743 my $data = shift;
744 my $state = shift;
745 my $event;
746 my $eventdata;
747
748 $event = unpack("C", $data);
749
750 printf("RemoteEventNotification (0x03, 0x09) I->D\n");
751 printf(" Event: %s (%d)\n", (
752 "Track position in ms",
753 "Track playback index",
754 "Chapter index",
755 "Play status",
756 "Mute/UI volume",
757 "Power/Battery",
758 "Equalizer setting",
759 "Shuffle setting",
760 "Repeat setting",
761 "Date and time setting",
762 "Alarm setting",
763 "Backlight state",
764 "Hold switch state",
765 "Sound check state",
766 "Audiobook speed",
767 "Track position in s",
768 "Mute/UI/Absolute volume")[$event], $event);
769
770 if ($event == 0x00) {
771 $eventdata = unpack("xN", $data);
772 printf(" Position: %d ms\n", $eventdata);
773 } elsif ($event == 0x01) {
774 $eventdata = unpack("xN", $data);
775 printf(" Track: %d\n", $eventdata);
776 } elsif ($event == 0x02) {
777 $eventdata = [ unpack("xNnn", $data) ];
778 printf(" Track: %d\n", $eventdata->[0]);
779 printf(" Chapter count: %d\n", $eventdata->[1]);
780 printf(" Chapter index: %d\n", $eventdata->[2]);
781 } elsif ($event == 0x03) {
782 $eventdata = unpack("xC", $data);
783 printf(" Status: %s (%d)\n", (
784 "Stopped",
785 "Playing",
786 "Paused",
787 "FF",
788 "REW",
789 "End FF/REW")[$eventdata], $eventdata);
790 } elsif ($event == 0x04) {
791 $eventdata = [ unpack("xCC") ];
792 printf(" Mute: %s\n", $eventdata->[0]?"Off":"On");
793 printf(" Volume: %d\n", $eventdata->[1]);
794 } elsif ($event == 0x0F) {
795 $eventdata = unpack("xn", $data);
796 printf(" Position: %d s\n", $eventdata);
797 }
798
799 return 1;
800}
801
802sub _h_03_000c {
803 my $self = shift;
804 my $data = shift;
805 my $state = shift;
806 my $info;
807
808 $info = unpack("C", $data);
809
810 printf("GetiPodStateInfo (0x03, 0x0C) D->I\n");
811 printf(" Info to get: %s (%d)\n", (
812 "Track time in ms",
813 "Track playback index",
814 "Chapter information",
815 "Play status",
816 "Mute and volume information",
817 "Power and battery status",
818 "Equalizer setting",
819 "Shuffle setting",
820 "Repeat setting",
821 "Date and time",
822 "Alarm state and time",
823 "Backlight state",
824 "Hold switch state",
825 "Audiobook speed",
826 "Track time in seconds",
827 "Mute/UI/Absolute volume")[$info], $info);
828
829 return 1;
830}
831
832sub _h_03_000d {
833 my $self = shift;
834 my $data = shift;
835 my $state = shift;
836 my $type;
837 my $info;
838
839 $type = unpack("C", $data);
840
841 printf("RetiPodStateInfo (0x03, 0x0E) D->I\n");
842
843 if ($type == 0x00) {
844 $info = unpack("xN", $data);
845 printf(" Type: Track position\n");
846 printf(" Position: %d ms\n", $info);
847 } elsif ($type == 0x01) {
848 $info = unpack("xN", $data);
849 printf(" Type: Track index\n");
850 printf(" Index: %d\n", $info);
851 } elsif ($type == 0x02) {
852 $info = [ unpack("xNnn", $data) ];
853 printf(" Type: Chapter Information\n");
854 printf(" Playing Track: %d\n", $info->[0]);
855 printf(" Chapter count: %d\n", $info->[1]);
856 printf(" Chapter index: %d\n", $info->[2]);
857 } elsif ($type == 0x03) {
858 $info = unpack("xC", $data);
859 printf(" Type: Play status\n");
860 printf(" Status: %s (%d)\n", (
861 "Stopped",
862 "Playing",
863 "Paused",
864 "FF",
865 "REW",
866 "End FF/REW")[$info], $info);
867 } elsif ($type == 0x04) {
868 $info = [unpack("xCC", $data)];
869 printf(" Type: Mute/Volume\n");
870 printf(" Mute State: %s\n", $info->[0]?"On":"Off");
871 printf(" Volume level: %d\n", $info->[1]);
872 } elsif ($type == 0x05) {
873 $info = [unpack("xCC", $data)];
874 printf(" Type: Battery Information\n");
875 printf(" Power state: %s (%d)\n", (
876 "Internal, low power (<30%)",
877 "Internal",
878 "External battery pack, no charging",
879 "External power, no charging",
880 "External power, charging",
881 "External power, charged")[$info->[0]], $info->[0]);
882 printf(" Battery level: %d%%\n", $info->[1]*100/255);
883 } elsif ($type == 0x06) {
884 $info = [unpack("xN", $data)];
885 printf(" Type: Equalizer\n");
886 printf(" Index: %d\n", $info->[0]);
887 } elsif ($type == 0x07) {
888 $info = [unpack("xC", $data)];
889 printf(" Type: Shuffle\n");
890 printf(" Shuffle State: %s\n", $info->[0]?"On":"Off");
891 } elsif ($type == 0x08) {
892 $info = [unpack("xC", $data)];
893 printf(" Type: Repeat\n");
894 printf(" Repeat State: %s\n", $info->[0]?"On":"Off");
895 } elsif ($type == 0x09) {
896 $info = [unpack("xnCCCC", $data)];
897 printf(" Type: Date\n");
898 printf(" Date: %02d.%02d.%04d %02d:%02d\n", $info->[2], $info->[1], $info->[0], $info->[3], $info->[4]);
899 } elsif ($type == 0x0A) {
900 $info = [unpack("xCCC", $data)];
901 printf(" Type: Alarm\n");
902 printf(" Alarm State: %s\n", $info->[0]?"On":"Off");
903 printf(" Time: %02d:%02d\n", $info->[1], $info->[2]);
904 } elsif ($type == 0x0B) {
905 $info = [unpack("xC", $data)];
906 printf(" Type: Backlight\n");
907 printf(" Backlight State: %s\n", $info->[0]?"On":"Off");
908 } elsif ($type == 0x0C) {
909 $info = [unpack("xC", $data)];
910 printf(" Type: Hold switch\n");
911 printf(" Switch State: %s\n", $info->[0]?"On":"Off");
912 } elsif ($type == 0x0D) {
913 $info = [unpack("xC", $data)];
914 printf(" Type: Sound check\n");
915 printf(" Sound check: %s\n", $info->[0]?"On":"Off");
916 } elsif ($type == 0x0E) {
917 $info = [unpack("xC", $data)];
918 printf(" Type: Audiobook speed\n");
919 printf(" Speed: %s\n", $info->[0]==0x00?"Normal":$info->[0]==0x01?"Faster":$info->[0]==0xFF?"Slower":"Reserved");
920 } elsif ($type == 0x0F) {
921 $info = unpack("xN", $data);
922 printf(" Type: Track position\n");
923 printf(" Position: %d s\n", $info);
924 } elsif ($type == 0x10) {
925 $info = [unpack("xCCC", $data)];
926 printf(" Type: Mute/UI/Absolute volume\n");
927 printf(" Mute State: %s\n", $info->[0]?"On":"Off");
928 printf(" UI Volume level: %d\n", $info->[1]);
929 printf(" Absolute Volume: %d\n", $info->[2]);
930 } else {
931 printf(" Reserved\n");
932 }
933
934 return 1;
935}
936
937
938sub _h_03_000e {
939 my $self = shift;
940 my $data = shift;
941 my $state = shift;
942 my $type;
943 my $info;
944
945 $type = unpack("C", $data);
946
947 printf("SetiPodStateInfo (0x03, 0x0E) D->I\n");
948
949 if ($type == 0x00) {
950 $info = unpack("xN", $data);
951 printf(" Type: Track position\n");
952 printf(" Position: %d ms\n", $info);
953 } elsif ($type == 0x01) {
954 $info = unpack("xN", $data);
955 printf(" Type: Track index\n");
956 printf(" Index: %d\n", $info);
957 } elsif ($type == 0x02) {
958 $info = unpack("xn", $data);
959 printf(" Type: Chapter index\n");
960 printf(" Index: %d\n", $info);
961 } elsif ($type == 0x03) {
962 $info = unpack("xC", $data);
963 printf(" Type: Play status\n");
964 printf(" Status: %s (%d)\n", (
965 "Stopped",
966 "Playing",
967 "Paused",
968 "FF",
969 "REW",
970 "End FF/REW")[$info], $info);
971 } elsif ($type == 0x04) {
972 $info = [unpack("xCCC", $data)];
973 printf(" Type: Mute/Volume\n");
974 printf(" Mute State: %s\n", $info->[0]?"On":"Off");
975 printf(" Volume level: %d\n", $info->[1]);
976 printf(" Restore on exit: %s\n", $info->[2]?"Yes":"No");
977 } elsif ($type == 0x06) {
978 $info = [unpack("xNC", $data)];
979 printf(" Type: Equalizer\n");
980 printf(" Index: %d\n", $info->[0]);
981 printf(" Restore on exit: %s\n", $info->[1]?"Yes":"No");
982 } elsif ($type == 0x07) {
983 $info = [unpack("xCC", $data)];
984 printf(" Type: Shuffle\n");
985 printf(" Shuffle State: %s\n", $info->[0]?"On":"Off");
986 printf(" Restore on exit: %s\n", $info->[1]?"Yes":"No");
987 } elsif ($type == 0x08) {
988 $info = [unpack("xCC", $data)];
989 printf(" Type: Repeat\n");
990 printf(" Repeat State: %s\n", $info->[0]?"On":"Off");
991 printf(" Restore on exit: %s\n", $info->[1]?"Yes":"No");
992 } elsif ($type == 0x09) {
993 $info = [unpack("xnCCCC", $data)];
994 printf(" Type: Date\n");
995 printf(" Date: %02d.%02d.%04d %02d:%02d\n", $info->[2], $info->[1], $info->[0], $info->[3], $info->[4]);
996 } elsif ($type == 0x0A) {
997 $info = [unpack("xCCCC", $data)];
998 printf(" Type: Alarm\n");
999 printf(" Alarm State: %s\n", $info->[0]?"On":"Off");
1000 printf(" Time: %02d:%02d\n", $info->[1], $info->[2]);
1001 printf(" Restore on exit: %s\n", $info->[3]?"Yes":"No");
1002 } elsif ($type == 0x0B) {
1003 $info = [unpack("xCC", $data)];
1004 printf(" Type: Backlight\n");
1005 printf(" Backlight State: %s\n", $info->[0]?"On":"Off");
1006 printf(" Restore on exit: %s\n", $info->[1]?"Yes":"No");
1007 } elsif ($type == 0x0D) {
1008 $info = [unpack("xCC", $data)];
1009 printf(" Type: Sound check\n");
1010 printf(" Sound check: %s\n", $info->[0]?"On":"Off");
1011 printf(" Restore on exit: %s\n", $info->[1]?"Yes":"No");
1012 } elsif ($type == 0x0E) {
1013 $info = [unpack("xCC", $data)];
1014 printf(" Type: Audiobook speed\n");
1015 printf(" Speed: %s\n", $info->[0]==0x00?"Normal":$info->[0]==0x01?"Faster":$info->[0]==0xFF?"Slower":"Reserved");
1016 printf(" Restore on exit: %s\n", $info->[1]?"Yes":"No");
1017 } elsif ($type == 0x0F) {
1018 $info = unpack("xN", $data);
1019 printf(" Type: Track position\n");
1020 printf(" Position: %d s\n", $info);
1021 } elsif ($type == 0x10) {
1022 $info = [unpack("xCCCC", $data)];
1023 printf(" Type: Mute/UI/Absolute volume\n");
1024 printf(" Mute State: %s\n", $info->[0]?"On":"Off");
1025 printf(" UI Volume level: %d\n", $info->[1]);
1026 printf(" Absolute Volume: %d\n", $info->[2]);
1027 printf(" Restore on exit: %s\n", $info->[3]?"Yes":"No");
1028 } else {
1029 printf(" Reserved\n");
1030 }
1031
1032 return 1;
1033}
1034
1035sub _h_03_000f {
1036 my $self = shift;
1037 my $data = shift;
1038 my $state = shift;
1039
1040 print("GetPlayStatus (0x03, 0x0F) D->I\n");
1041
1042 return 1;
1043}
1044
1045sub _h_03_0010 {
1046 my $self = shift;
1047 my $data = shift;
1048 my $state = shift;
1049 my ($status, $idx, $len, $pos);
1050
1051 ($status, $idx, $len, $pos) = unpack("CNNN", $data);
1052
1053 printf("RetPlayStatus (0x03, 0x10) I->D\n");
1054 printf(" Status: %s (%d)\n", (
1055 "Stopped",
1056 "Playing",
1057 "Paused")[$status], $status);
1058 if ($status != 0x00) {
1059 printf(" Track index: %d\n", $idx);
1060 printf(" Track length: %d\n", $len);
1061 printf(" Track position: %d\n", $pos);
1062 }
1063
1064 return 1;
1065}
1066
1067sub _h_03_0012 {
1068 my $self = shift;
1069 my $data = shift;
1070 my $state = shift;
1071 my ($info, $tidx, $cidx);
1072
1073 ($info, $tidx, $cidx) = unpack("CNn", $data);
1074
1075 printf("GetIndexedPlayingTrackInfo (0x03, 0x12) D->I\n");
1076 printf(" Requested info: %s (%d)\n", (
1077 "Track caps/info",
1078 "Chapter time/name",
1079 "Artist name",
1080 "Album name",
1081 "Genre name",
1082 "Track title",
1083 "Composer name",
1084 "Lyrics",
1085 "Artwork count")[$info], $info);
1086 printf(" Track index: %d\n", $tidx);
1087 printf(" Chapter index: %d\n", $cidx);
1088
1089 return 1;
1090}
1091
1092sub _h_03_0013 {
1093 my $self = shift;
1094 my $data = shift;
1095 my $state = shift;
1096 my $info;
1097
1098 $info = unpack("C", $data);
1099 printf("RetIndexedPlayingTrackInfo (0x03, 0x13) I->D\n");
1100 printf(" Returned info: %s (%d)\n", (
1101 "Track caps/info",
1102 "Chapter time/name",
1103 "Artist name",
1104 "Album name",
1105 "Genre name",
1106 "Track title",
1107 "Composer name",
1108 "Lyrics",
1109 "Artwork count")[$info], $info);
1110 if ($info == 0x00) {
1111 my ($caps, $len, $chap) = unpack("xNNn", $data);
1112 printf(" Track is audiobook\n") if ($caps & 0x01);
1113 printf(" Track has chapters\n") if ($caps & 0x02);
1114 printf(" Track has artwork\n") if ($caps & 0x04);
1115 printf(" Track contains video\n") if ($caps & 0x80);
1116 printf(" Track queued as video\n") if ($caps & 0x100);
1117
1118 printf(" Track length: %d ms\n", $len);
1119 printf(" Track chapters: %d\n", $chap);
1120 } elsif ($info == 0x01) {
1121 my ($len, $name) = unpack("xNZ*");
1122 printf(" Chapter time: %d ms\n", $len);
1123 printf(" Chapter name: %s\n", $name);
1124 } elsif ($info >= 0x02 && $info <= 0x06) {
1125 my $name = unpack("xZ*", $data);
1126 printf(" Name/Title: %s\n", $name)
1127 } elsif ($info == 0x07) {
1128 my ($info, $index, $data) = unpack("xCnZ*");
1129 printf(" Part of multiple packets\n") if ($info & 0x01);
1130 printf(" Is last packet\n") if ($info & 0x02);
1131 printf(" Packet index: %d\n", $index);
1132 printf(" Data: %s\n", $data);
1133 } elsif ($info == 0x08) {
1134
1135 }
1136
1137 return 1;
1138}
1139
1140sub _h_04_0001 {
1141 my $self = shift;
1142 my $data = shift;
1143 my $state = shift;
1144 my $res;
1145 my $cmd;
1146
1147 ($res, $cmd) = unpack("Cn", $data);
1148
1149 printf("ACK (0x04, 0x0001) I->D\n");
1150 printf(" Acknowledged command: 0x%02x\n", $cmd);
1151 printf(" Status: %s (%d)\n",
1152 ("Success",
1153 "ERROR: Unknown Database Category",
1154 "ERROR: Command Failed",
1155 "ERROR: Out Of Resource",
1156 "ERROR: Bad Parameter",
1157 "ERROR: Unknown ID",
1158 "Reserved",
1159 "ERROR: Not Authenticated")[$res], $res);
1160
1161 return 1;
1162}
1163
1164sub _h_04_000c {
1165 my $self = shift;
1166 my $data = shift;
1167 my $state = shift;
1168 my ($info, $track, $chapter);
1169
1170 ($info, $track, $chapter) = unpack("CNn", $data);
1171
1172 printf("GetIndexedPlayingTrackInfo (0x04, 0x000C) D->I\n");
1173 printf(" Track: %d\n", $track);
1174 printf(" Chapter: %d\n", $chapter);
1175 printf(" Info requested: %s (%d)\n", (
1176 "Capabilities and information",
1177 "Podcast name",
1178 "Track release date",
1179 "Track description",
1180 "Track song lyrics",
1181 "Track genre",
1182 "Track Composer",
1183 "Tracn Artwork count")[$info], $info);
1184
1185 return 1;
1186}
1187
1188sub _h_04_000d {
1189 my $self = shift;
1190 my $data = shift;
1191 my $state = shift;
1192 my $info;
1193
1194 $info = unpack("C", $data);
1195
1196 printf("ReturnIndexedPlayingTrackInfo (0x04, 0x000D) I->D\n");
1197 if ($info == 0x00) {
1198 my ($capability, $length, $chapter);
1199
1200 ($capability, $length, $chapter) = unpack("xNNn", $data);
1201 printf(" Capabilities:\n");
1202 printf(" Is audiobook\n") if ($capability & 0x00000001);
1203 printf(" Has chapters\n") if ($capability & 0x00000002);
1204 printf(" Has album artwork\n") if ($capability & 0x00000004);
1205 printf(" Has song lyrics\n") if ($capability & 0x00000008);
1206 printf(" Is a podcast episode\n") if ($capability & 0x00000010);
1207 printf(" Has release date\n") if ($capability & 0x00000020);
1208 printf(" Has description\n") if ($capability & 0x00000040);
1209 printf(" Contains video\n") if ($capability & 0x00000080);
1210 printf(" Queued to play as video\n") if ($capability & 0x00000100);
1211
1212 printf(" Length: %d ms\n", $length);
1213 printf(" Chapters: %d\n", $chapter);
1214 } else {
1215 printf(" WARNING: Unknown info\n");
1216 return 1;
1217 }
1218
1219 return 1;
1220}
1221
1222sub _h_04_0012 {
1223 my $self = shift;
1224 my $data = shift;
1225 my $state = shift;
1226
1227 printf("RequestProtocolVersion (0x04, 0x0012) D->I\n");
1228
1229 return 1;
1230}
1231
1232sub _h_04_0013 {
1233 my $self = shift;
1234 my $data = shift;
1235 my $state = shift;
1236 my ($maj, $min);
1237
1238 ($maj, $min) = unpack("CC", $data);
1239
1240 printf("ReturnProtocolVersion (0x04, 0x0013) I->D\n");
1241 printf(" Lingo 0x04 version: %d.%02d\n", $maj, $min);
1242
1243 return 1;
1244}
1245
1246sub _h_04_0016 {
1247 my $self = shift;
1248 my $data = shift;
1249 my $state = shift;
1250
1251 printf("ResetDBSelection (0x04, 0x0016) D->I\n");
1252
1253 return 1;
1254}
1255
1256sub _h_04_0018 {
1257 my $self = shift;
1258 my $data = shift;
1259 my $state = shift;
1260 my $category;
1261
1262 $category = unpack("C", $data);
1263
1264 printf("GetNumberCategorizedDBRecords (0x04, 0x0018) D->I\n");
1265 printf(" Category: %s (%d)\n", (
1266 "Reserved",
1267 "Playlist",
1268 "Artist",
1269 "Album",
1270 "Genre",
1271 "Track",
1272 "Composer",
1273 "Audiobook",
1274 "Podcast",
1275 "Nested Playlist")[$category], $category);
1276
1277 return 1;
1278}
1279
1280sub _h_04_0019 {
1281 my $self = shift;
1282 my $data = shift;
1283 my $state = shift;
1284 my $count;
1285
1286 $count = unpack("N", $data);
1287
1288 printf("ReturnNumberCategorizedDBRecords (0x04, 0x0019) I->D\n");
1289 printf(" Count: %d\n", $count);
1290
1291 return 1;
1292}
1293
1294sub _h_04_001c {
1295 my $self = shift;
1296 my $data = shift;
1297 my $state = shift;
1298
1299 printf("GetPlayStatus (0x04, 0x001C) D->I\n");
1300
1301 return 1;
1302}
1303
1304sub _h_04_001d {
1305 my $self = shift;
1306 my $data = shift;
1307 my $state = shift;
1308 my ($len, $pos, $s);
1309
1310 ($len, $pos, $s) = unpack("NNC", $data);
1311
1312 printf("ReturnPlayStatus (0x04, 0x001D) I->D\n");
1313 printf(" Song length: %d ms\n", $len);
1314 printf(" Song position: %d ms\n", $pos);
1315 printf(" Player state: ");
1316 if ($s == 0x00) {
1317 printf("Stopped\n");
1318 } elsif ($s == 0x01) {
1319 printf("Playing\n");
1320 } elsif ($s == 0x02) {
1321 printf("Paused\n");
1322 } elsif ($s == 0xFF) {
1323 printf("Error\n");
1324 } else {
1325 printf("Reserved\n");
1326 }
1327
1328 return 1;
1329}
1330
1331sub _h_04_001e {
1332 my $self = shift;
1333 my $data = shift;
1334 my $state = shift;
1335
1336 printf("GetCurrentPlayingTrackIndex (0x04, 0x001E) D->I\n");
1337
1338 return 1;
1339}
1340
1341sub _h_04_001f {
1342 my $self = shift;
1343 my $data = shift;
1344 my $state = shift;
1345 my $num;
1346
1347 $num = unpack("N", $data);
1348
1349 printf("ReturnCurrentPlayingTrackIndex (0x04, 0x001F) I->D\n");
1350 printf(" Index: %d\n", $num);
1351
1352 return 1;
1353}
1354
1355sub _h_04_0020 {
1356 my $self = shift;
1357 my $data = shift;
1358 my $state = shift;
1359 my $track;
1360
1361 $track = unpack("N", $data);
1362
1363 printf("GetIndexedPlayingTrackTitle (0x04, 0x0020) D->I\n");
1364 printf(" Track: %d\n", $track);
1365
1366 return 1;
1367}
1368
1369sub _h_04_0021 {
1370 my $self = shift;
1371 my $data = shift;
1372 my $state = shift;
1373 my $title;
1374
1375 $title = unpack("Z*", $data);
1376
1377 printf("ReturnIndexedPlayingTrackTitle (0x04, 0x0021) I->D\n");
1378 printf(" Title: %s\n", $title);
1379
1380 return 1;
1381}
1382
1383sub _h_04_0022 {
1384 my $self = shift;
1385 my $data = shift;
1386 my $state = shift;
1387 my $track;
1388
1389 $track = unpack("N", $data);
1390
1391 printf("GetIndexedPlayingTrackArtistName (0x04, 0x0022) D->I\n");
1392 printf(" Track: %d\n", $track);
1393
1394 return 1;
1395}
1396
1397sub _h_04_0023 {
1398 my $self = shift;
1399 my $data = shift;
1400 my $state = shift;
1401 my $artist;
1402
1403 $artist = unpack("Z*", $data);
1404
1405 printf("ReturnIndexedPlayingTrackArtistName (0x04, 0x0023) I->D\n");
1406 printf(" Artist: %s\n", $artist);
1407
1408 return 1;
1409}
1410
1411sub _h_04_0024 {
1412 my $self = shift;
1413 my $data = shift;
1414 my $state = shift;
1415 my $track;
1416
1417 $track = unpack("N", $data);
1418
1419 printf("GetIndexedPlayingTrackAlbumName (0x04, 0x0024) D->I\n");
1420 printf(" Track: %d\n", $track);
1421
1422 return 1;
1423}
1424
1425sub _h_04_0025 {
1426 my $self = shift;
1427 my $data = shift;
1428 my $state = shift;
1429 my $title;
1430
1431 $title = unpack("Z*", $data);
1432
1433 printf("ReturnIndexedPlayingTrackAlbumName (0x04, 0x0025) I->D\n");
1434 printf(" Album: %s\n", $title);
1435
1436 return 1;
1437}
1438
1439sub _h_04_0026 {
1440 my $self = shift;
1441 my $data = shift;
1442 my $state = shift;
1443 my $notification;
1444
1445 if (length($data) == 1) {
1446 $notification = unpack("C", $data);
1447 } elsif (length($data) == 4) {
1448 $notification = unpack("N", $data);
1449 }
1450
1451 printf("SetPlayStatusChangeNotification (0x04, 0x0026) D->I\n");
1452
1453 if (length($data) == 1) {
1454 printf(" Events for: %s (%d)\n", (
1455 "Disable all",
1456 "Basic play state, track index, track time position, FFW/REW seek stop, and chapter index changes")[$notification], $notification);
1457 } elsif (length($data) == 4) {
1458 printf(" Events for:\n");
1459 printf(" Basic play state changes\n") if ($notification & 0x00000001);
1460 printf(" Extended play state changes\n") if ($notification & 0x00000002);
1461 printf(" Track index\n") if ($notification & 0x00000004);
1462 printf(" Track time offset (ms)\n") if ($notification & 0x00000008);
1463 printf(" Track time offset (s)\n") if ($notification & 0x00000010);
1464 printf(" Chapter index\n") if ($notification & 0x00000020);
1465 printf(" Chapter time offset (ms)\n") if ($notification & 0x00000040);
1466 printf(" Chapter time offset (s)\n") if ($notification & 0x00000080);
1467 printf(" Track unique identifier\n") if ($notification & 0x00000100);
1468 printf(" Track media tyoe\n") if ($notification & 0x00000200);
1469 printf(" Track lyrics\n") if ($notification & 0x00000400);
1470 } else {
1471 printf(" WARNING: Unknown length for state\n");
1472 return 0;
1473 }
1474
1475 return 1;
1476}
1477
1478sub _h_04_0027 {
1479 my $self = shift;
1480 my $data = shift;
1481 my $state = shift;
1482 my $info;
1483
1484 $info = unpack("C", $data);
1485
1486 printf("PlayStatusChangeNotification (0x04, 0x0029) I->D\n");
1487 printf(" Status:\n");
1488 if ($info == 0x00) {
1489 printf(" Playback stopped\n");
1490 } elsif ($info == 0x01) {
1491 my $index = unpack("xN", $data);
1492
1493 printf(" Track index: %d\n", $index);
1494 } elsif ($info == 0x02) {
1495 printf(" Playback FF seek stop\n");
1496 } elsif ($info == 0x03) {
1497 printf(" Playback REW seek stop\n");
1498 } elsif ($info == 0x04) {
1499 my $offset = unpack("xN", $data);
1500
1501 printf(" Track time offset: %d ms\n", $offset);
1502 } elsif ($info == 0x05) {
1503 my $index = unpack("xN", $data);
1504
1505 printf(" Chapter index: %d\n", $index);
1506 } elsif ($info == 0x06) {
1507 my $status = unpack("xC", $data);
1508
1509 printf(" Playback status extended: %s (%d)\n", (
1510 "Reserved",
1511 "Reserved",
1512 "Stopped",
1513 "Reserved",
1514 "Reserved",
1515 "FF seek started",
1516 "REW seek started",
1517 "FF/REW seek stopped",
1518 "Reserved",
1519 "Reserved",
1520 "Playing",
1521 "Paused")[$status], $status);
1522 } elsif ($info == 0x07) {
1523 my $offset = unpack("xN", $data);
1524
1525 printf(" Track time offset: %d s\n", $offset);
1526 } elsif ($info == 0x08) {
1527 my $offset = unpack("xN", $data);
1528
1529 printf(" Chapter time offset %d ms\n", $offset);
1530 } elsif ($info == 0x09) {
1531 my $offset = unpack("xN", $data);
1532
1533 printf(" Chapter time offset %d s\n", $offset);
1534 } elsif ($info == 0x0A) {
1535 my ($uidhi, $uidlo) = unpack("xNN", $data);
1536
1537 printf(" Track UID: %08x%08x\n", $uidhi, $uidlo);
1538 } elsif ($info == 0x0B) {
1539 my $mode = unpack("xC", $data);
1540
1541 printf(" Track mode: %s (%d)\n", (
1542 "Audio track",
1543 "Video track")[$mode], $mode);
1544 } elsif ($info == 0x0C) {
1545 printf(" Track lyrics ready\n");
1546 } else {
1547 printf(" Reserved\n");
1548 }
1549
1550 return 1;
1551}
1552
1553sub _h_04_0029 {
1554 my $self = shift;
1555 my $data = shift;
1556 my $state = shift;
1557 my $control;
1558
1559 $control = unpack("C", $data);
1560
1561 printf("PlayControl (0x04, 0x0029) D->I\n");
1562 printf(" Command: %s (%d)\n", (
1563 "Reserved",
1564 "Toggle Play/Pause",
1565 "Stop",
1566 "Next track",
1567 "Previous track",
1568 "Start FF",
1569 "Start Rev",
1570 "Stop FF/Rev",
1571 "Next",
1572 "Previous",
1573 "Play",
1574 "Pause",
1575 "Next chapter",
1576 "Previous chapter")[$control], $control);
1577
1578 return 1;
1579}
1580
1581sub _h_04_002c {
1582 my $self = shift;
1583 my $data = shift;
1584 my $state = shift;
1585
1586 printf("GetShuffle (0x04, 0x002C) D->I\n");
1587
1588 return 1;
1589}
1590
1591sub _h_04_002d {
1592 my $self = shift;
1593 my $data = shift;
1594 my $state = shift;
1595 my $mode;
1596
1597 $mode = unpack("C", $data);
1598
1599 printf("ReturnShuffle (0x04, 0x002D) I->D\n");
1600 printf(" Mode: %s (%d)\n", (
1601 "Off",
1602 "Tracks",
1603 "Albums")[$mode], $mode);
1604
1605 return 1;
1606}
1607
1608sub _h_04_002f {
1609 my $self = shift;
1610 my $data = shift;
1611 my $state = shift;
1612
1613 printf("GetRepeat (0x04, 0x002F) D->I\n");
1614
1615 return 1;
1616}
1617
1618sub _h_04_0030 {
1619 my $self = shift;
1620 my $data = shift;
1621 my $state = shift;
1622 my $mode;
1623
1624 $mode = unpack("C", $data);
1625
1626 printf("ReturnRepeat (0x04, 0x0030) I->D\n");
1627 printf(" Mode: %s (%d)\n", (
1628 "Off",
1629 "One Track",
1630 "All Tracks")[$mode], $mode);
1631
1632 return 1;
1633}
1634
1635sub _h_04_0032 {
1636 my $self = shift;
1637 my $data = shift;
1638 my $state = shift;
1639 my ($index, $format, $width, $height, $stride, $imagedata);
1640
1641 $state->{-index} = -1 unless(exists($state->{-index}));
1642 $state->{-image} = '' unless(exists($state->{-image}));
1643
1644 ($index, $format, $width, $height, $stride, $imagedata) = unpack("nCnnNa*", $data);
1645
1646 printf("SetDisplayImage (0x04, 0x0032) D->I\n");
1647 if ($index == 0) {
1648 printf(" Width: %d\n", $width);
1649 printf(" Height: %d\n", $height);
1650 printf(" Stride: %d\n", $stride);
1651 printf(" Format: %s (%d)\n", (
1652 "Reserved",
1653 "Monochrome, 2 bps",
1654 "RGB 565, little endian",
1655 "RGB 565, big endian")[$format], $format);
1656
1657 $state->{-imagelength} = $height * $stride;
1658 } else {
1659 ($index, $imagedata) = unpack("na*", $data);
1660 }
1661
1662 if ($index-1 != $state->{-index}) {
1663 printf(" WARNING! Out of order segment\n");
1664 return 0;
1665 }
1666
1667 $state->{-index} = $index;
1668 $state->{-image} .= $imagedata;
1669
1670 if (length($state->{-image}) >= $state->{-imagelength}) {
1671 printf(" Image data: %s\n", Device::iPod->_hexstring($state->{-image}));
1672 }
1673
1674 return 1;
1675}
1676
1677sub _h_04_0033 {
1678 my $self = shift;
1679 my $data = shift;
1680 my $state = shift;
1681
1682 printf("GetMonoDisplayImageLimits (0x04, 0x0033) D->I\n");
1683
1684 return 1;
1685}
1686
1687sub _h_04_0034 {
1688 my $self = shift;
1689 my $data = shift;
1690 my $state = shift;
1691 my ($width, $height, $format);
1692
1693 ($width, $height, $format) = unpack("nnC", $data);
1694
1695 printf("ReturnMonoDisplayImageLimits (0x04, 0x0034) I->D\n");
1696 printf(" Width: %d\n", $width);
1697 printf(" Height: %d\n", $height);
1698 printf(" Format: %s (%d)\n", (
1699 "Reserved",
1700 "Monochrome, 2 bps",
1701 "RGB 565, little endian",
1702 "RGB 565, big endian")[$format], $format);
1703
1704 return 1;
1705}
1706
1707sub _h_04_0035 {
1708 my $self = shift;
1709 my $data = shift;
1710 my $state = shift;
1711
1712 printf("GetNumPlayingTracks (0x04, 0x0035) D->I\n");
1713
1714 return 1;
1715}
1716
1717sub _h_04_0036 {
1718 my $self = shift;
1719 my $data = shift;
1720 my $state = shift;
1721 my $num;
1722
1723 $num = unpack("N", $data);
1724
1725 printf("ReturnNumPlayingTracks (0x04, 0x0036) I->D\n");
1726 printf(" Number: %d\n", $num);
1727
1728 return 1;
1729}
1730
1731sub _h_04_0037 {
1732 my $self = shift;
1733 my $data = shift;
1734 my $state = shift;
1735 my $num;
1736
1737 $num = unpack("N", $data);
1738
1739 printf("SetCurrentPlayingTrack (0x04, 0x0037) D->I\n");
1740 printf(" Track: %d\n", $num);
1741
1742 return 1;
1743}
1744
1745sub _h_07_0005 {
1746 my $self = shift;
1747 my $data = shift;
1748 my $state = shift;
1749 my $control;
1750
1751 $control = unpack("C", $data);
1752
1753 printf("SetTunerCtrl (0x07, 0x05) I->D\n");
1754 printf(" Options:\n");
1755 printf(" Power %s\n", ($control & 0x01)?"on":"off");
1756 printf(" Status change notifications %s\n", ($control & 0x02)?"on":"off");
1757 printf(" Raw mode %s\n", ($control & 0x04)?"on":"off");
1758}
1759
1760sub _h_07_0020 {
1761 my $self = shift;
1762 my $data = shift;
1763 my $state = shift;
1764 my $options;
1765
1766 $options = unpack("N", $data);
1767
1768 printf("SetRDSNotifyMask (0x07, 0x20) I->D\n");
1769 printf(" Options:\n");
1770 printf(" Radiotext\n") if ($options & 0x00000010);
1771 printf(" Program Service Name\n") if ($options & 0x40000000);
1772 printf(" Reserved\n") if ($options & 0xBFFFFFEF);
1773
1774 return 1;
1775}
1776
1777sub _h_07_0024 {
1778 my $self = shift;
1779 my $data = shift;
1780 my $state = shift;
1781
1782 printf("Reserved command (0x07, 0x24) I->D\n");
1783
1784 return 1;
1785}
1786
1787
1788package main;
1789
1790use Device::iPod;
1791use Getopt::Long;
1792use strict;
1793
1794my $decoder;
1795my $device;
1796my $unpacker;
1797my $line;
1798
1799sub unpack_hexstring {
1800 my $line = shift;
1801 my $m;
1802 my @m;
1803
1804 $line =~ s/(..)/chr(hex($1))/ge;
1805 $device->{-inbuf} = $line;
1806
1807 $m = $device->_message();
1808 next unless defined($m);
1809 @m = $device->_unframe_cmd($m);
1810 unless(@m) {
1811 printf("Line %d: Error decoding frame: %s\n", $., $device->error());
1812 return ();
1813 }
1814
1815 return @m;
1816}
1817
1818sub unpack_iaplog {
1819 my $line = shift;
1820 my @m;
1821
1822 unless ($line =~ /^(?:\[\d+\] )?[RT]::? /) {
1823 printf("Skipped: %s\n", $line);
1824 return ();
1825 }
1826
1827 $line =~ s/^(?:\[\d+\] )?[RT]::? //;
1828 $line =~ s/\\x(..)/chr(hex($1))/ge;
1829 $line =~ s/\\\\/\\/g;
1830
1831 @m = unpack("CCa*", $line);
1832 if ($m[0] == 0x04) {
1833 @m = unpack("Cna*", $line);
1834 }
1835
1836 return @m;
1837}
1838
1839
1840$decoder = iap::decode->new();
1841$device = Device::iPod->new();
1842$unpacker = \&unpack_iaplog;
1843
1844GetOptions("hexstring" => sub {$unpacker = \&unpack_hexstring});
1845
1846while ($line = <>) {
1847 my @m;
1848
1849 chomp($line);
1850
1851 @m = $unpacker->($line);
1852 next unless (@m);
1853
1854 printf("Line %d: ", $.);
1855 $decoder->display(@m);
1856}