1#------------------------------------------------------------------------------
2# File:         CanonCustom.pm
3#
4# Description:  Read and write Canon Custom functions
5#
6# Revisions:    11/25/2003  - P. Harvey Created
7#
8# References:   1) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html
9#               2) Christian Koller private communication (20D)
10#               3) Rainer Honle private communication (5D)
11#               4) David Pitcher private communication (1DmkIII firmware upgrade)
12#------------------------------------------------------------------------------
13
14package Image::ExifTool::CanonCustom;
15
16use strict;
17use vars qw($VERSION);
18use Image::ExifTool qw(:DataAccess);
19use Image::ExifTool::Canon;
20use Image::ExifTool::Exif;
21
22$VERSION = '1.58';
23
24sub ProcessCanonCustom($$$);
25sub ProcessCanonCustom2($$$);
26sub WriteCanonCustom($$$);
27sub WriteCanonCustom2($$$);
28sub CheckCanonCustom($$$);
29sub ConvertPFn($);
30sub ConvertPFnInv($);
31
32my %onOff = ( 0 => 'On', 1 => 'Off' );
33my %offOn = ( 0 => 'Off', 1 => 'On' );
34my %disableEnable = ( 0 => 'Disable', 1 => 'Enable' );
35my %enableDisable = ( 0 => 'Enable', 1 => 'Disable' );
36my %convPFn = ( PrintConv => \&ConvertPfn, PrintConvInv => \&ConvertPfnInv );
37
38#------------------------------------------------------------------------------
39# Custom functions for the 1D
40# CanonCustom (keys are custom function number)
41%Image::ExifTool::CanonCustom::Functions1D = (
42    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
43    PROCESS_PROC => \&ProcessCanonCustom,
44    WRITE_PROC => \&WriteCanonCustom,
45    CHECK_PROC => \&CheckCanonCustom,
46    WRITABLE => 'int8u',
47    NOTES => q{
48        These custom functions are used by all 1D models up to but not including the
49        Mark III.
50    },
51    0 => {
52        Name => 'FocusingScreen',
53        PrintConv => {
54            0 => 'Ec-N, R',
55            1 => 'Ec-A,B,C,CII,CIII,D,H,I,L',
56        },
57    },
58    1 => {
59        Name => 'FinderDisplayDuringExposure',
60        PrintConv => \%offOn,
61    },
62    2 => {
63        Name => 'ShutterReleaseNoCFCard',
64        Description => 'Shutter Release W/O CF Card',
65        PrintConv => {
66            0 => 'Yes',
67            1 => 'No',
68        },
69    },
70    3 => {
71        Name => 'ISOSpeedExpansion',
72        Description => 'ISO Speed Expansion',
73        PrintConv => {
74            0 => 'No',
75            1 => 'Yes',
76        },
77    },
78    4 => {
79        Name => 'ShutterAELButton',
80        Description => 'Shutter Button/AEL Button',
81        PrintConv => {
82            0 => 'AF/AE lock stop',
83            1 => 'AE lock/AF',
84            2 => 'AF/AF lock, No AE lock',
85            3 => 'AE/AF, No AE lock',
86        },
87    },
88    5 => {
89        Name => 'ManualTv',
90        Description => 'Manual Tv/Av For M',
91        PrintConv => {
92            0 => 'Tv=Main/Av=Control',
93            1 => 'Tv=Control/Av=Main',
94            2 => 'Tv=Main/Av=Main w/o lens',
95            3 => 'Tv=Control/Av=Main w/o lens',
96        },
97    },
98    6 => {
99        Name => 'ExposureLevelIncrements',
100        PrintConv => {
101            0 => '1/3-stop set, 1/3-stop comp.',
102            1 => '1-stop set, 1/3-stop comp.',
103            2 => '1/2-stop set, 1/2-stop comp.',
104        },
105    },
106    7 => {
107        Name => 'USMLensElectronicMF',
108        PrintConv => {
109            0 => 'Turns on after one-shot AF',
110            1 => 'Turns off after one-shot AF',
111            2 => 'Always turned off',
112        },
113    },
114    8 => {
115        Name => 'LCDPanels',
116        Description => 'Top/Back LCD Panels',
117        PrintConv => {
118            0 => 'Remain. shots/File no.',
119            1 => 'ISO/Remain. shots',
120            2 => 'ISO/File no.',
121            3 => 'Shots in folder/Remain. shots',
122        },
123    },
124    9 => {
125        Name => 'AEBSequenceAutoCancel',
126        Description => 'AEB Sequence/Auto Cancel',
127        PrintConv => {
128            0 => '0,-,+/Enabled',
129            1 => '0,-,+/Disabled',
130            2 => '-,0,+/Enabled',
131            3 => '-,0,+/Disabled',
132        },
133    },
134    10 => {
135        Name => 'AFPointIllumination',
136        PrintConv => {
137            0 => 'On',
138            1 => 'Off',
139            2 => 'On without dimming',
140            3 => 'Brighter',
141        },
142    },
143    11 => {
144        Name => 'AFPointSelection',
145        PrintConv => {
146            0 => 'H=AF+Main/V=AF+Command',
147            1 => 'H=Comp+Main/V=Comp+Command',
148            2 => 'H=Command only/V=Assist+Main',
149            3 => 'H=FEL+Main/V=FEL+Command',
150        },
151    },
152    12 => {
153        Name => 'MirrorLockup',
154        PrintConv => \%disableEnable,
155    },
156    13 => {
157        Name => 'AFPointSpotMetering',
158        Description => 'No. AF Points/Spot Metering',
159        PrintConv => {
160            0 => '45/Center AF point',
161            1 => '11/Active AF point',
162            2 => '11/Center AF point',
163            3 => '9/Active AF point',
164        },
165    },
166    14 => {
167        Name => 'FillFlashAutoReduction',
168        PrintConv => \%enableDisable,
169    },
170    15 => {
171        Name => 'ShutterCurtainSync',
172        PrintConv => {
173            0 => '1st-curtain sync',
174            1 => '2nd-curtain sync',
175        },
176    },
177    16 => {
178        Name => 'SafetyShiftInAvOrTv',
179        PrintConv => \%disableEnable,
180    },
181    17 => {
182        Name => 'AFPointActivationArea',
183        PrintConv => {
184            0 => 'Single AF point',
185            1 => 'Expanded (TTL. of 7 AF points)',
186            2 => 'Automatic expanded (max. 13)',
187        },
188    },
189    18 => {
190        Name => 'SwitchToRegisteredAFPoint',
191        PrintConv => {
192            0 => 'Assist + AF',
193            1 => 'Assist',
194            2 => 'Only while pressing assist',
195        },
196    },
197    19 => {
198        Name => 'LensAFStopButton',
199        PrintConv => {
200            0 => 'AF stop',
201            1 => 'AF start',
202            2 => 'AE lock while metering',
203            3 => 'AF point: M -> Auto / Auto -> Ctr.',
204            4 => 'AF mode: ONE SHOT <-> AI SERVO',
205            5 => 'IS start',
206        },
207    },
208    20 => {
209        Name => 'AIServoTrackingSensitivity',
210        PrintConv => {
211            0 => 'Standard',
212            1 => 'Slow',
213            2 => 'Moderately slow',
214            3 => 'Moderately fast',
215            4 => 'Fast',
216        },
217    },
218    21 => {
219        Name => 'AIServoContinuousShooting',
220        PrintConv => {
221            0 => 'Shooting not possible without focus',
222            1 => 'Shooting possible without focus',
223        },
224    },
225);
226
227# Custom functions for the 5D (ref 3)
228%Image::ExifTool::CanonCustom::Functions5D = (
229    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
230    PROCESS_PROC => \&ProcessCanonCustom,
231    WRITE_PROC => \&WriteCanonCustom,
232    CHECK_PROC => \&CheckCanonCustom,
233    WRITABLE => 'int8u',
234    0 => {
235        Name => 'FocusingScreen',
236        PrintConv => {
237            0 => 'Ee-A',
238            1 => 'Ee-D',
239            2 => 'Ee-S',
240        },
241    },
242    1 => {
243        Name => 'SetFunctionWhenShooting',
244        PrintConv => {
245            0 => 'Default (no function)',
246            1 => 'Change quality',
247            2 => 'Change Parameters',
248            3 => 'Menu display',
249            4 => 'Image replay',
250        },
251    },
252    2 => {
253        Name => 'LongExposureNoiseReduction',
254        PrintConv => {
255            0 => 'Off',
256            1 => 'Auto',
257            2 => 'On',
258        },
259    },
260    3 => {
261        Name => 'FlashSyncSpeedAv',
262        PrintConv => {
263            0 => 'Auto',
264            1 => '1/200 Fixed',
265        },
266    },
267    4 => {
268        Name => 'Shutter-AELock',
269        PrintConv => {
270            0 => 'AF/AE lock',
271            1 => 'AE lock/AF',
272            2 => 'AF/AF lock, No AE lock',
273            3 => 'AE/AF, No AE lock',
274        },
275    },
276    5 => {
277        Name => 'AFAssistBeam',
278        PrintConv => {
279            0 => 'Emits',
280            1 => 'Does not emit',
281        },
282    },
283    6 => {
284        Name => 'ExposureLevelIncrements',
285        PrintConv => {
286            0 => '1/3 Stop',
287            1 => '1/2 Stop',
288        },
289    },
290    7 => {
291        Name => 'FlashFiring',
292        PrintConv => {
293            0 => 'Fires',
294            1 => 'Does not fire',
295        },
296    },
297    8 => {
298        Name => 'ISOExpansion',
299        PrintConv => \%offOn,
300    },
301    9 => {
302        Name => 'AEBSequenceAutoCancel',
303        Description => 'AEB Sequence/Auto Cancel',
304        PrintConv => {
305            0 => '0,-,+/Enabled',
306            1 => '0,-,+/Disabled',
307            2 => '-,0,+/Enabled',
308            3 => '-,0,+/Disabled',
309        },
310    },
311    10 => {
312        Name => 'SuperimposedDisplay',
313        PrintConv => \%onOff,
314    },
315    11 => {
316        Name => 'MenuButtonDisplayPosition',
317        PrintConv => {
318            0 => 'Previous (top if power off)',
319            1 => 'Previous',
320            2 => 'Top',
321        },
322    },
323    12 => {
324        Name => 'MirrorLockup',
325        PrintConv => \%disableEnable,
326    },
327    13 => {
328        Name => 'AFPointSelectionMethod',
329        PrintConv => {
330            0 => 'Normal',
331            1 => 'Multi-controller direct',
332            2 => 'Quick Control Dial direct',
333        },
334    },
335    14 => {
336        Name => 'ETTLII',
337        Description => 'E-TTL II',
338        PrintConv => {
339            0 => 'Evaluative',
340            1 => 'Average',
341        },
342    },
343    15 => {
344        Name => 'ShutterCurtainSync',
345        PrintConv => {
346            0 => '1st-curtain sync',
347            1 => '2nd-curtain sync',
348        },
349    },
350    16 => {
351        Name => 'SafetyShiftInAvOrTv',
352        PrintConv => \%disableEnable,
353    },
354    17 => {
355        Name => 'AFPointActivationArea',
356        PrintConv => {
357            0 => 'Standard',
358            1 => 'Expanded',
359        },
360    },
361    18 => {
362        Name => 'LCDDisplayReturnToShoot',
363        PrintConv => {
364            0 => 'With Shutter Button only',
365            1 => 'Also with * etc.',
366        },
367    },
368    19 => {
369        Name => 'LensAFStopButton',
370        PrintConv => {
371            0 => 'AF stop',
372            1 => 'AF start',
373            2 => 'AE lock while metering',
374            3 => 'AF point: M -> Auto / Auto -> Ctr.',
375            4 => 'ONE SHOT <-> AI SERVO',
376            5 => 'IS start',
377        },
378    },
379    20 => {
380        Name => 'AddOriginalDecisionData',
381        PrintConv => \%offOn,
382    },
383);
384
385# Custom functions for 10D
386%Image::ExifTool::CanonCustom::Functions10D = (
387    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
388    PROCESS_PROC => \&ProcessCanonCustom,
389    WRITE_PROC => \&WriteCanonCustom,
390    CHECK_PROC => \&CheckCanonCustom,
391    WRITABLE => 'int8u',
392    1 => {
393        Name => 'SetButtonWhenShooting',
394        PrintConv => {
395            0 => 'Normal (disabled)',
396            1 => 'Image quality',
397            2 => 'Change parameters',
398            3 => 'Menu display',
399            4 => 'Image playback',
400        },
401    },
402    2 => {
403        Name => 'ShutterReleaseNoCFCard',
404        Description => 'Shutter Release W/O CF Card',
405        PrintConv => {
406            0 => 'Yes',
407            1 => 'No',
408        },
409    },
410    3 => {
411        Name => 'FlashSyncSpeedAv',
412        PrintConv => {
413            0 => 'Auto',
414            1 => '1/200 Fixed',
415        },
416    },
417    4 => {
418        Name => 'Shutter-AELock',
419        PrintConv => {
420            0 => 'AF/AE lock',
421            1 => 'AE lock/AF',
422            2 => 'AF/AF lock, No AE lock',
423            3 => 'AE/AF, No AE lock',
424        },
425    },
426    5 => {
427        Name => 'AFAssist',
428        Description => 'AF Assist/Flash Firing',
429        PrintConv => {
430            0 => 'Emits/Fires',
431            1 => 'Does not emit/Fires',
432            2 => 'Only ext. flash emits/Fires',
433            3 => 'Emits/Does not fire',
434        },
435    },
436    6 => {
437        Name => 'ExposureLevelIncrements',
438        PrintConv => {
439            0 => '1/2 Stop',
440            1 => '1/3 Stop',
441        },
442    },
443    7 => {
444        Name => 'AFPointRegistration',
445        PrintConv => {
446            0 => 'Center',
447            1 => 'Bottom',
448            2 => 'Right',
449            3 => 'Extreme Right',
450            4 => 'Automatic',
451            5 => 'Extreme Left',
452            6 => 'Left',
453            7 => 'Top',
454        },
455    },
456    8 => {
457        Name => 'RawAndJpgRecording',
458        PrintConv => {
459            0 => 'RAW+Small/Normal',
460            1 => 'RAW+Small/Fine',
461            2 => 'RAW+Medium/Normal',
462            3 => 'RAW+Medium/Fine',
463            4 => 'RAW+Large/Normal',
464            5 => 'RAW+Large/Fine',
465        },
466    },
467    9 => {
468        Name => 'AEBSequenceAutoCancel',
469        Description => 'AEB Sequence/Auto Cancel',
470        PrintConv => {
471            0 => '0,-,+/Enabled',
472            1 => '0,-,+/Disabled',
473            2 => '-,0,+/Enabled',
474            3 => '-,0,+/Disabled',
475        },
476    },
477    10 => {
478        Name => 'SuperimposedDisplay',
479        PrintConv => \%onOff,
480    },
481    11 => {
482        Name => 'MenuButtonDisplayPosition',
483        PrintConv => {
484            0 => 'Previous (top if power off)',
485            1 => 'Previous',
486            2 => 'Top',
487        },
488    },
489    12 => {
490        Name => 'MirrorLockup',
491        PrintConv => \%disableEnable,
492    },
493    13 => {
494        Name => 'AssistButtonFunction',
495        PrintConv => {
496            0 => 'Normal',
497            1 => 'Select Home Position',
498            2 => 'Select HP (while pressing)',
499            3 => 'Av+/- (AF point by QCD)',
500            4 => 'FE lock',
501        },
502    },
503    14 => {
504        Name => 'FillFlashAutoReduction',
505        PrintConv => \%enableDisable,
506    },
507    15 => {
508        Name => 'ShutterCurtainSync',
509        PrintConv => {
510            0 => '1st-curtain sync',
511            1 => '2nd-curtain sync',
512        },
513    },
514    16 => {
515        Name => 'SafetyShiftInAvOrTv',
516        PrintConv => \%disableEnable,
517    },
518    17 => {
519        Name => 'LensAFStopButton',
520        PrintConv => {
521            0 => 'AF stop',
522            1 => 'AF start',
523            2 => 'AE lock while metering',
524            3 => 'AF point: M->Auto/Auto->ctr',
525            4 => 'One Shot <-> AI servo',
526            5 => 'IS start',
527        },
528    },
529);
530
531# Custom functions for the 20D (ref 2)
532%Image::ExifTool::CanonCustom::Functions20D = (
533    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
534    PROCESS_PROC => \&ProcessCanonCustom,
535    WRITE_PROC => \&WriteCanonCustom,
536    CHECK_PROC => \&CheckCanonCustom,
537    WRITABLE => 'int8u',
538    0 => {
539        Name => 'SetFunctionWhenShooting',
540        PrintConv => {
541            0 => 'Default (no function)',
542            1 => 'Change quality',
543            2 => 'Change Parameters',
544            3 => 'Menu display',
545            4 => 'Image replay',
546        },
547    },
548    1 => {
549        Name => 'LongExposureNoiseReduction',
550        PrintConv => \%offOn,
551    },
552    2 => {
553        Name => 'FlashSyncSpeedAv',
554        PrintConv => {
555            0 => 'Auto',
556            1 => '1/250 Fixed',
557        },
558    },
559    3 => {
560        Name => 'Shutter-AELock',
561        PrintConv => {
562            0 => 'AF/AE lock',
563            1 => 'AE lock/AF',
564            2 => 'AF/AF lock, No AE lock',
565            3 => 'AE/AF, No AE lock',
566        },
567    },
568    4 => {
569        Name => 'AFAssistBeam',
570        PrintConv => {
571            0 => 'Emits',
572            1 => 'Does not emit',
573            2 => 'Only ext. flash emits',
574        },
575    },
576    5 => {
577        Name => 'ExposureLevelIncrements',
578        PrintConv => {
579            0 => '1/3 Stop',
580            1 => '1/2 Stop',
581        },
582    },
583    6 => {
584        Name => 'FlashFiring',
585        PrintConv => {
586            0 => 'Fires',
587            1 => 'Does not fire',
588        },
589    },
590    7 => {
591        Name => 'ISOExpansion',
592        PrintConv => \%offOn,
593    },
594    8 => {
595        Name => 'AEBSequenceAutoCancel',
596        Description => 'AEB Sequence/Auto Cancel',
597        PrintConv => {
598            0 => '0,-,+/Enabled',
599            1 => '0,-,+/Disabled',
600            2 => '-,0,+/Enabled',
601            3 => '-,0,+/Disabled',
602        },
603    },
604    9 => {
605        Name => 'SuperimposedDisplay',
606        PrintConv => \%onOff,
607    },
608    10 => {
609        Name => 'MenuButtonDisplayPosition',
610        PrintConv => {
611            0 => 'Previous (top if power off)',
612            1 => 'Previous',
613            2 => 'Top',
614        },
615    },
616    11 => {
617        Name => 'MirrorLockup',
618        PrintConv => \%disableEnable,
619    },
620    12 => {
621        Name => 'AFPointSelectionMethod',
622        PrintConv => {
623            0 => 'Normal',
624            1 => 'Multi-controller direct',
625            2 => 'Quick Control Dial direct',
626        },
627    },
628    13 => {
629        Name => 'ETTLII',
630        Description => 'E-TTL II',
631        PrintConv => {
632            0 => 'Evaluative',
633            1 => 'Average',
634        },
635    },
636    14 => {
637        Name => 'ShutterCurtainSync',
638        PrintConv => {
639            0 => '1st-curtain sync',
640            1 => '2nd-curtain sync',
641        },
642    },
643    15 => {
644        Name => 'SafetyShiftInAvOrTv',
645        PrintConv => \%disableEnable,
646    },
647    16 => {
648        Name => 'LensAFStopButton',
649        PrintConv => {
650            0 => 'AF stop',
651            1 => 'AF start',
652            2 => 'AE lock while metering',
653            3 => 'AF point: M -> Auto / Auto -> Ctr.',
654            4 => 'ONE SHOT <-> AI SERVO',
655            5 => 'IS start',
656        },
657    },
658    17 => {
659        Name => 'AddOriginalDecisionData',
660        PrintConv => \%offOn,
661    },
662);
663
664# Custom functions for the 30D (PH)
665%Image::ExifTool::CanonCustom::Functions30D = (
666    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
667    PROCESS_PROC => \&ProcessCanonCustom,
668    WRITE_PROC => \&WriteCanonCustom,
669    CHECK_PROC => \&CheckCanonCustom,
670    WRITABLE => 'int8u',
671    1 => {
672        Name => 'SetFunctionWhenShooting',
673        PrintConv => {
674            0 => 'Default (no function)',
675            1 => 'Change quality',
676            2 => 'Change Picture Style',
677            3 => 'Menu display',
678            4 => 'Image replay',
679        },
680    },
681    2 => {
682        Name => 'LongExposureNoiseReduction',
683        PrintConv => {
684            0 => 'Off',
685            1 => 'Auto',
686            2 => 'On',
687        },
688    },
689    3 => {
690        Name => 'FlashSyncSpeedAv',
691        PrintConv => {
692            0 => 'Auto',
693            1 => '1/250 Fixed',
694        },
695    },
696    4 => {
697        Name => 'Shutter-AELock',
698        PrintConv => {
699            0 => 'AF/AE lock',
700            1 => 'AE lock/AF',
701            2 => 'AF/AF lock, No AE lock',
702            3 => 'AE/AF, No AE lock',
703        },
704    },
705    5 => {
706        Name => 'AFAssistBeam',
707        PrintConv => {
708            0 => 'Emits',
709            1 => 'Does not emit',
710            2 => 'Only ext. flash emits',
711        },
712    },
713    6 => {
714        Name => 'ExposureLevelIncrements',
715        PrintConv => {
716            0 => '1/3 Stop',
717            1 => '1/2 Stop',
718        },
719    },
720    7 => {
721        Name => 'FlashFiring',
722        PrintConv => {
723            0 => 'Fires',
724            1 => 'Does not fire',
725        },
726    },
727    8 => {
728        Name => 'ISOExpansion',
729        PrintConv => \%offOn,
730    },
731    9 => {
732        Name => 'AEBSequenceAutoCancel',
733        Description => 'AEB Sequence/Auto Cancel',
734        PrintConv => {
735            0 => '0,-,+/Enabled',
736            1 => '0,-,+/Disabled',
737            2 => '-,0,+/Enabled',
738            3 => '-,0,+/Disabled',
739        },
740    },
741    10 => {
742        Name => 'SuperimposedDisplay',
743        PrintConv => \%onOff,
744    },
745    11 => {
746        Name => 'MenuButtonDisplayPosition',
747        PrintConv => {
748            0 => 'Previous (top if power off)',
749            1 => 'Previous',
750            2 => 'Top',
751        },
752    },
753    12 => {
754        Name => 'MirrorLockup',
755        PrintConv => \%disableEnable,
756    },
757    13 => {
758        Name => 'AFPointSelectionMethod',
759        PrintConv => {
760            0 => 'Normal',
761            1 => 'Multi-controller direct',
762            2 => 'Quick Control Dial direct',
763        },
764    },
765    14 => {
766        Name => 'ETTLII',
767        Description => 'E-TTL II',
768        PrintConv => {
769            0 => 'Evaluative',
770            1 => 'Average',
771        },
772    },
773    15 => {
774        Name => 'ShutterCurtainSync',
775        PrintConv => {
776            0 => '1st-curtain sync',
777            1 => '2nd-curtain sync',
778        },
779    },
780    16 => {
781        Name => 'SafetyShiftInAvOrTv',
782        PrintConv => \%disableEnable,
783    },
784    17 => {
785        Name => 'MagnifiedView',
786        PrintConv => {
787            0 => 'Image playback only',
788            1 => 'Image review and playback',
789        },
790    },
791    18 => {
792        Name => 'LensAFStopButton',
793        PrintConv => {
794            0 => 'AF stop',
795            1 => 'AF start',
796            2 => 'AE lock while metering',
797            3 => 'AF point: M -> Auto / Auto -> Ctr.',
798            4 => 'ONE SHOT <-> AI SERVO',
799            5 => 'IS start',
800        },
801    },
802    19 => {
803        Name => 'AddOriginalDecisionData',
804        PrintConv => \%offOn,
805    },
806);
807
808# Custom functions for the 350D (PH)
809%Image::ExifTool::CanonCustom::Functions350D = (
810    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
811    PROCESS_PROC => \&ProcessCanonCustom,
812    WRITE_PROC => \&WriteCanonCustom,
813    CHECK_PROC => \&CheckCanonCustom,
814    WRITABLE => 'int8u',
815    0 => {
816        Name => 'SetButtonCrossKeysFunc',
817        PrintConv => {
818            0 => 'Normal',
819            1 => 'Set: Quality',
820            2 => 'Set: Parameter',
821            3 => 'Set: Playback',
822            4 => 'Cross keys: AF point select',
823        },
824    },
825    1 => {
826        Name => 'LongExposureNoiseReduction',
827        PrintConv => \%offOn,
828    },
829    2 => {
830        Name => 'FlashSyncSpeedAv',
831        PrintConv => {
832            0 => 'Auto',
833            1 => '1/200 Fixed',
834        },
835    },
836    3 => {
837        Name => 'Shutter-AELock',
838        PrintConv => {
839            0 => 'AF/AE lock',
840            1 => 'AE lock/AF',
841            2 => 'AF/AF lock, No AE lock',
842            3 => 'AE/AF, No AE lock',
843        },
844    },
845    4 => {
846        Name => 'AFAssistBeam',
847        PrintConv => {
848            0 => 'Emits',
849            1 => 'Does not emit',
850            2 => 'Only ext. flash emits',
851        },
852    },
853    5 => {
854        Name => 'ExposureLevelIncrements',
855        PrintConv => {
856            0 => '1/3 Stop',
857            1 => '1/2 Stop',
858        },
859    },
860    6 => {
861        Name => 'MirrorLockup',
862        PrintConv => \%disableEnable,
863    },
864    7 => {
865        Name => 'ETTLII',
866        Description => 'E-TTL II',
867        PrintConv => {
868            0 => 'Evaluative',
869            1 => 'Average',
870        },
871    },
872    8 => {
873        Name => 'ShutterCurtainSync',
874        PrintConv => {
875            0 => '1st-curtain sync',
876            1 => '2nd-curtain sync',
877        },
878    },
879);
880
881# Custom functions for the 400D (PH)
882%Image::ExifTool::CanonCustom::Functions400D = (
883    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
884    PROCESS_PROC => \&ProcessCanonCustom,
885    WRITE_PROC => \&WriteCanonCustom,
886    CHECK_PROC => \&CheckCanonCustom,
887    WRITABLE => 'int8u',
888    0 => {
889        Name => 'SetButtonCrossKeysFunc',
890        PrintConv => {
891            0 => 'Set: Picture Style',
892            1 => 'Set: Quality',
893            2 => 'Set: Flash Exposure Comp',
894            3 => 'Set: Playback',
895            4 => 'Cross keys: AF point select',
896        },
897    },
898    1 => {
899        Name => 'LongExposureNoiseReduction',
900        PrintConv => {
901            0 => 'Off',
902            1 => 'Auto',
903            2 => 'On',
904        },
905    },
906    2 => {
907        Name => 'FlashSyncSpeedAv',
908        PrintConv => {
909            0 => 'Auto',
910            1 => '1/200 Fixed',
911        },
912    },
913    3 => {
914        Name => 'Shutter-AELock',
915        PrintConv => {
916            0 => 'AF/AE lock',
917            1 => 'AE lock/AF',
918            2 => 'AF/AF lock, No AE lock',
919            3 => 'AE/AF, No AE lock',
920        },
921    },
922    4 => {
923        Name => 'AFAssistBeam',
924        PrintConv => {
925            0 => 'Emits',
926            1 => 'Does not emit',
927            2 => 'Only ext. flash emits',
928        },
929    },
930    5 => {
931        Name => 'ExposureLevelIncrements',
932        PrintConv => {
933            0 => '1/3 Stop',
934            1 => '1/2 Stop',
935        },
936    },
937    6 => {
938        Name => 'MirrorLockup',
939        PrintConv => \%disableEnable,
940    },
941    7 => {
942        Name => 'ETTLII',
943        Description => 'E-TTL II',
944        PrintConv => {
945            0 => 'Evaluative',
946            1 => 'Average',
947        },
948    },
949    8 => {
950        Name => 'ShutterCurtainSync',
951        PrintConv => {
952            0 => '1st-curtain sync',
953            1 => '2nd-curtain sync',
954        },
955    },
956    9 => {
957        Name => 'MagnifiedView',
958        PrintConv => {
959            0 => 'Image playback only',
960            1 => 'Image review and playback',
961        },
962    },
963    10 => {
964        Name => 'LCDDisplayAtPowerOn',
965        PrintConv => {
966            0 => 'Display',
967            1 => 'Retain power off status',
968        },
969    },
970);
971
972# Custom functions for the D30/D60
973%Image::ExifTool::CanonCustom::FunctionsD30 = (
974    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
975    PROCESS_PROC => \&ProcessCanonCustom,
976    WRITE_PROC => \&WriteCanonCustom,
977    CHECK_PROC => \&CheckCanonCustom,
978    NOTES => 'Custom functions for the EOS D30 and D60.',
979    WRITABLE => 'int8u',
980    1 => {
981        Name => 'LongExposureNoiseReduction',
982        PrintConv => \%offOn,
983    },
984    2 => {
985        Name => 'Shutter-AELock',
986        PrintConv => {
987            0 => 'AF/AE lock',
988            1 => 'AE lock/AF',
989            2 => 'AF/AF lock',
990            3 => 'AE+release/AE+AF',
991        },
992    },
993    3 => {
994        Name => 'MirrorLockup',
995        PrintConv => \%disableEnable,
996    },
997    4 => {
998        Name => 'ExposureLevelIncrements',
999        PrintConv => {
1000            0 => '1/2 Stop',
1001            1 => '1/3 Stop',
1002        },
1003    },
1004    5 => {
1005        Name => 'AFAssist',
1006        PrintConv => {
1007            0 => 'Emits/Fires',
1008            1 => 'Does not emit/Fires',
1009            2 => 'Only ext. flash emits/Fires',
1010            3 => 'Emits/Does not fire',
1011        },
1012    },
1013    6 => {
1014        Name => 'FlashSyncSpeedAv',
1015        PrintConv => {
1016            0 => 'Auto',
1017            1 => '1/200 Fixed',
1018        },
1019    },
1020    7 => {
1021        Name => 'AEBSequenceAutoCancel',
1022        Description => 'AEB Sequence/Auto Cancel',
1023        PrintConv => {
1024            0 => '0,-,+/Enabled',
1025            1 => '0,-,+/Disabled',
1026            2 => '-,0,+/Enabled',
1027            3 => '-,0,+/Disabled',
1028        },
1029    },
1030    8 => {
1031        Name => 'ShutterCurtainSync',
1032        PrintConv => {
1033            0 => '1st-curtain sync',
1034            1 => '2nd-curtain sync',
1035        },
1036    },
1037    9 => {
1038        Name => 'LensAFStopButton',
1039        PrintConv => {
1040            0 => 'AF Stop',
1041            1 => 'Operate AF',
1042            2 => 'Lock AE and start timer',
1043        },
1044    },
1045    10 => {
1046        Name => 'FillFlashAutoReduction',
1047        PrintConv => \%enableDisable,
1048    },
1049    11 => {
1050        Name => 'MenuButtonReturn',
1051        PrintConv => {
1052            0 => 'Top',
1053            1 => 'Previous (volatile)',
1054            2 => 'Previous',
1055        },
1056    },
1057    12 => {
1058        Name => 'SetButtonWhenShooting',
1059        PrintConv => {
1060            0 => 'Default (no function)',
1061            1 => 'Image quality',
1062            2 => 'Change ISO speed',
1063            3 => 'Change parameters',
1064        },
1065    },
1066    13 => {
1067        Name => 'SensorCleaning',
1068        PrintConv => \%disableEnable,
1069    },
1070    14 => {
1071        Name => 'SuperimposedDisplay',
1072        PrintConv => \%onOff,
1073    },
1074    15 => {
1075        Name => 'ShutterReleaseNoCFCard',
1076        Description => 'Shutter Release W/O CF Card',
1077        PrintConv => {
1078            0 => 'Yes',
1079            1 => 'No',
1080        },
1081    },
1082);
1083
1084# Custom functions for unknown cameras
1085%Image::ExifTool::CanonCustom::FuncsUnknown = (
1086    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
1087    PROCESS_PROC => \&ProcessCanonCustom,
1088);
1089
1090# 1D personal function settings (ref PH)
1091%Image::ExifTool::CanonCustom::PersonalFuncs = (
1092    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
1093    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1094    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1095    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1096    WRITABLE => 1,
1097    NOTES => 'Personal function settings for the EOS-1D.',
1098    FORMAT => 'int16u',
1099    FIRST_ENTRY => 1,
1100    1 => { Name => 'PF0CustomFuncRegistration', %convPFn },
1101    2 => { Name => 'PF1DisableShootingModes',   %convPFn },
1102    3 => { Name => 'PF2DisableMeteringModes',   %convPFn },
1103    4 => { Name => 'PF3ManualExposureMetering', %convPFn },
1104    5 => { Name => 'PF4ExposureTimeLimits',     %convPFn },
1105    6 => { Name => 'PF5ApertureLimits',         %convPFn },
1106    7 => { Name => 'PF6PresetShootingModes',    %convPFn },
1107    8 => { Name => 'PF7BracketContinuousShoot', %convPFn },
1108    9 => { Name => 'PF8SetBracketShots',        %convPFn },
1109    10 => { Name => 'PF9ChangeBracketSequence', %convPFn },
1110    11 => { Name => 'PF10RetainProgramShift',   %convPFn },
1111    #12 => { Name => 'PF11Unused',               %convPFn },
1112    #13 => { Name => 'PF12Unused',               %convPFn },
1113    14 => { Name => 'PF13DrivePriority',        %convPFn },
1114    15 => { Name => 'PF14DisableFocusSearch',   %convPFn },
1115    16 => { Name => 'PF15DisableAFAssistBeam',  %convPFn },
1116    17 => { Name => 'PF16AutoFocusPointShoot',  %convPFn },
1117    18 => { Name => 'PF17DisableAFPointSel',    %convPFn },
1118    19 => { Name => 'PF18EnableAutoAFPointSel', %convPFn },
1119    20 => { Name => 'PF19ContinuousShootSpeed', %convPFn },
1120    21 => { Name => 'PF20LimitContinousShots',  %convPFn },
1121    22 => { Name => 'PF21EnableQuietOperation', %convPFn },
1122    #23 => { Name => 'PF22Unused',               %convPFn },
1123    24 => { Name => 'PF23SetTimerLengths',      %convPFn },
1124    25 => { Name => 'PF24LightLCDDuringBulb',   %convPFn },
1125    26 => { Name => 'PF25DefaultClearSettings', %convPFn },
1126    27 => { Name => 'PF26ShortenReleaseLag',    %convPFn },
1127    28 => { Name => 'PF27ReverseDialRotation',  %convPFn },
1128    29 => { Name => 'PF28NoQuickDialExpComp',   %convPFn },
1129    30 => { Name => 'PF29QuickDialSwitchOff',   %convPFn },
1130    31 => { Name => 'PF30EnlargementMode',      %convPFn },
1131    32 => { Name => 'PF31OriginalDecisionData', %convPFn },
1132);
1133
1134# 1D personal function values (ref PH)
1135%Image::ExifTool::CanonCustom::PersonalFuncValues = (
1136    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
1137    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1138    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1139    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1140    WRITABLE => 1,
1141    FORMAT => 'int16u',
1142    FIRST_ENTRY => 1,
1143    1 => 'PF1Value',
1144    2 => 'PF2Value',
1145    3 => 'PF3Value',
1146    4 => {
1147        Name => 'PF4ExposureTimeMin',
1148        RawConv => '$val > 0 ? $val : 0',
1149        ValueConv => 'exp(-Image::ExifTool::Canon::CanonEv($val*4)*log(2))*1000/8',
1150        ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(-log($val*8/1000)/log(2))/4',
1151        PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
1152        PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
1153    },
1154    5 => {
1155        Name => 'PF4ExposureTimeMax',
1156        RawConv => '$val > 0 ? $val : 0',
1157        ValueConv => 'exp(-Image::ExifTool::Canon::CanonEv($val*4)*log(2))*1000/8',
1158        ValueConvInv => 'Image::ExifTool::Canon::CanonEvInv(-log($val*8/1000)/log(2))/4',
1159        PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
1160        PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
1161    },
1162    6 => {
1163        Name => 'PF5ApertureMin',
1164        RawConv => '$val > 0 ? $val : 0',
1165        ValueConv => 'exp(Image::ExifTool::Canon::CanonEv($val*4-32)*log(2)/2)',
1166        ValueConvInv => '(Image::ExifTool::Canon::CanonEvInv(log($val)*2/log(2))+32)/4',
1167        PrintConv => 'sprintf("%.2g",$val)',
1168        PrintConvInv => '$val',
1169    },
1170    7 => {
1171        Name => 'PF5ApertureMax',
1172        RawConv => '$val > 0 ? $val : 0',
1173        ValueConv => 'exp(Image::ExifTool::Canon::CanonEv($val*4-32)*log(2)/2)',
1174        ValueConvInv => '(Image::ExifTool::Canon::CanonEvInv(log($val)*2/log(2))+32)/4',
1175        PrintConv => 'sprintf("%.2g",$val)',
1176        PrintConvInv => '$val',
1177    },
1178    8 => 'PF8BracketShots',
1179    9 => 'PF19ShootingSpeedLow',
1180    10 => 'PF19ShootingSpeedHigh',
1181    11 => 'PF20MaxContinousShots',
1182    12 => 'PF23ShutterButtonTime',
1183    13 => 'PF23FELockTime',
1184    14 => 'PF23PostReleaseTime',
1185    15 => 'PF25AEMode',
1186    16 => 'PF25MeteringMode',
1187    17 => 'PF25DriveMode',
1188    18 => 'PF25AFMode',
1189    19 => 'PF25AFPointSel',
1190    20 => 'PF25ImageSize',
1191    21 => 'PF25WBMode',
1192    22 => 'PF25Parameters',
1193    23 => 'PF25ColorMatrix',
1194    24 => 'PF27Value',
1195);
1196
1197# Custom functions used by the 1D Mark III and later models (ref PH)
1198%Image::ExifTool::CanonCustom::Functions2 = (
1199    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
1200    PROCESS_PROC => \&ProcessCanonCustom2,
1201    CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1202    WRITE_PROC => \&WriteCanonCustom2,
1203    WRITABLE => 'int32s',
1204    NOTES => q{
1205        Beginning with the EOS 1D Mark III, Canon finally created a set of custom
1206        function tags which are (reasonably) consistent across models.  The EOS 1D
1207        Mark III has 57 custom function tags divided into four main groups: 1.
1208        Exposure (0x0101-0x010f), 2. Image (0x0201-0x0203), Flash Exposure
1209        (0x0304-0x0306) and Display (0x0407-0x0409), 3. Auto Focus (0x0501-0x050e)
1210        and Drive (0x060f-0x0611), and 4. Operation (0x0701-0x070a) and Others
1211        (0x080b-0x0810).  The table below lists tags used by the EOS 1D Mark III, as
1212        well as newer tags and values added by later models.
1213    },
1214    # grouped in 4 groups:
1215    # 1) Exposure
1216    0x0101 => [
1217        {
1218            Name => 'ExposureLevelIncrements',
1219            Condition => '$$self{Model} =~ /\b1Ds?\b/',
1220            Notes => '1DmkIII and 1DmkIV',
1221            PrintConv => {
1222                0 => '1/3-stop set, 1/3-stop comp.',
1223                1 => '1-stop set, 1/3-stop comp.',
1224                2 => '1/2-stop set, 1/2-stop comp.',
1225            },
1226        },
1227        {
1228            Name => 'ExposureLevelIncrements',
1229            Notes => 'other models',
1230            PrintConv => {
1231                0 => '1/3 Stop',
1232                1 => '1/2 Stop',
1233            },
1234        },
1235    ],
1236    0x0102 => {
1237        Name => 'ISOSpeedIncrements',
1238        PrintConv => {
1239            0 => '1/3 Stop',
1240            1 => '1 Stop',
1241        },
1242    },
1243    0x0103 => [
1244        {
1245            Name => 'ISOSpeedRange',
1246            Condition => '$$self{Model} =~ /\b1D/',
1247            Notes => '1DmkIII and 1DmkIV',
1248            Count => 3,
1249            # (this decoding may not be valid for CR2 images?)
1250            ValueConv => [
1251                undef,
1252                # this may also be set to "H" (Hi6400) -- is this the -1 value I see? - PH
1253                '$val < 2 ? $val : ($val < 1000 ? exp(($val/8-9)*log(2))*100 : 0)', # (educated guess)
1254                # this may also be set to "L" (Lo50) -- is this the 1 value I see? - PH
1255                '$val < 2 ? $val : ($val < 1000 ? exp(($val/8-9)*log(2))*100 : 0)', # (educated guess)
1256            ],
1257            ValueConvInv => [
1258                undef,
1259                '$val < 2 ? $val : int(8*(log($val/100)/log(2)+9) + 0.5)',
1260                '$val < 2 ? $val : int(8*(log($val/100)/log(2)+9) + 0.5)',
1261            ],
1262            PrintConv => [
1263                \%disableEnable,
1264                'sprintf("Max %.0f",$val)',
1265                'sprintf("Min %.0f",$val)',
1266            ],
1267            PrintConvInv => [
1268                undef,
1269                '$val=~/(-?[\d.]+)/ ? $1 : 0',
1270                '$val=~/(-?[\d.]+)/ ? $1 : 0',
1271            ],
1272        },
1273        {
1274            Name => 'ISOExpansion',
1275            Notes => 'other models',
1276            PrintConv => \%offOn,
1277        },
1278    ],
1279    0x0104 => {
1280        Name => 'AEBAutoCancel',
1281        PrintConv => \%onOff,
1282    },
1283    0x0105 => {
1284        Name => 'AEBSequence',
1285        Notes => 'value of 2 not used by 40D, 50D, 60D, 5DmkII and 7D',
1286        PrintConv => {
1287            0 => '0,-,+',
1288            1 => '-,0,+',
1289            2 => '+,0,-',
1290        },
1291    },
1292    0x0106 => [{
1293        Name => 'AEBShotCount',
1294        Condition => '$count == 1',
1295        Notes => 'one value for some models...',
1296        PrintConv => {
1297            0 => '3 shots',
1298            1 => '2 shots',
1299            2 => '5 shots',
1300            3 => '7 shots',
1301        },
1302    },{
1303        Name => 'AEBShotCount',
1304        Count => 2,
1305        Notes => 'two values for others',
1306        PrintConv => {
1307            '3 0' => '3 shots',
1308            '2 1' => '2 shots',
1309            '5 2' => '5 shots',
1310            '7 3' => '7 shots',
1311        },
1312    }],
1313    0x0107 => {
1314        Name => 'SpotMeterLinkToAFPoint',
1315        PrintConv => {
1316            0 => 'Disable (use center AF point)',
1317            1 => 'Enable (use active AF point)',
1318        },
1319    },
1320    0x0108 => {
1321        Name => 'SafetyShift',
1322        Notes => 'value of 2 not used by some models', # eg. 40D, 50D, 60D, 5DmkII, 7D, 250D
1323        PrintConv => {
1324            0 => 'Disable',
1325            1 => 'Enable (Tv/Av)',
1326            2 => 'Enable (ISO speed)',
1327        },
1328    },
1329    0x0109 => [{ # (1DXmkIII)
1330        Name => 'UsableShootingModes',
1331        Condition => '$count == 1',
1332        Count => 1,
1333        PrintConv => 'sprintf("Flags 0x%x",$val)',
1334        PrintConvInv => '$val=~/0x([\dA-F]+)/i ? hex($1) : undef',
1335    },{
1336        Name => 'UsableShootingModes',
1337        Count => 2,
1338        PrintConv => [
1339            \%disableEnable,
1340            'sprintf("Flags 0x%x",$val)', # (M, Tv, Av, P, Bulb)
1341        ],
1342        PrintConvInv => [
1343            undef,
1344            '$val=~/0x([\dA-F]+)/i ? hex($1) : undef',
1345        ],
1346    }],
1347    0x010a => [{ # (1DXmkIII)
1348        Name => 'UsableMeteringModes',
1349        Condition => '$count == 1',
1350        Count => 1,
1351        PrintConv => 'sprintf("Flags 0x%x",$val)',
1352        PrintConvInv => '$val=~/0x([\dA-F]+)/i ? hex($1) : undef',
1353    },{
1354        Name => 'UsableMeteringModes',
1355        Count => 2,
1356        PrintConv => [
1357            \%disableEnable,
1358            'sprintf("Flags 0x%x",$val)', # (evaluative,partial,spot,center-weighted average)
1359        ],
1360        PrintConvInv => [
1361            undef,
1362            '$val=~/0x([\dA-F]+)/i ? hex($1) : undef',
1363        ],
1364    }],
1365    0x010b => {
1366        Name => 'ExposureModeInManual',
1367        PrintConv => {
1368            0 => 'Specified metering mode',
1369            1 => 'Evaluative metering',
1370            2 => 'Partial metering',
1371            3 => 'Spot metering',
1372            4 => 'Center-weighted average',
1373        },
1374    },
1375    0x010c => [{
1376        Name => 'ShutterSpeedRange',
1377        Condition => '$count == 3',
1378        Count => 3,
1379        ValueConv => [
1380            undef,
1381            'exp(-($val/8-7)*log(2))',
1382            'exp(-($val/8-7)*log(2))',
1383        ],
1384        ValueConvInv => [
1385            undef,
1386            'int(-8*(log($val)/log(2)-7) + 0.5)',
1387            'int(-8*(log($val)/log(2)-7) + 0.5)',
1388        ],
1389        PrintConv => [
1390            \%disableEnable,
1391            '"Hi " . Image::ExifTool::Exif::PrintExposureTime($val)',
1392            '"Lo " . Image::ExifTool::Exif::PrintExposureTime($val)',
1393        ],
1394        PrintConvInv => [
1395            undef,
1396            '$val=~m{([\d./]+)} ? eval $1 : 0',
1397            '$val=~m{([\d./]+)} ? eval $1 : 0',
1398        ],
1399    },{ # (EOS R)
1400        Name => 'ShutterSpeedRange',
1401        Condition => '$count == 4',
1402        Count => 4,
1403        ValueConv => [ # (NC)
1404            'exp(-$val/(1600*log(2)))',
1405            'exp(-$val/(1600*log(2)))',
1406            'exp(-$val/(1600*log(2)))',
1407            'exp(-$val/(1600*log(2)))',
1408        ],
1409        ValueConvInv => [
1410            'int(-log($val)*1600*log(2) + 0.5)',
1411            'int(-log($val)*1600*log(2) + 0.5)',
1412            'int(-log($val)*1600*log(2) + 0.5)',
1413            'int(-log($val)*1600*log(2) + 0.5)',
1414        ],
1415        PrintConv => [ # (NC)
1416            '"Manual: Hi " . Image::ExifTool::Exif::PrintExposureTime($val)',
1417            '"Lo " . Image::ExifTool::Exif::PrintExposureTime($val)',
1418            '"Auto: Hi " . Image::ExifTool::Exif::PrintExposureTime($val)',
1419            '"Lo " . Image::ExifTool::Exif::PrintExposureTime($val)',
1420        ],
1421        PrintConvInv => [
1422            '$val=~m{([\d./]+)} ? eval $1 : 0',
1423            '$val=~m{([\d./]+)} ? eval $1 : 0',
1424            '$val=~m{([\d./]+)} ? eval $1 : 0',
1425            '$val=~m{([\d./]+)} ? eval $1 : 0',
1426        ],
1427    }],
1428    0x010d => [{
1429        Name => 'ApertureRange',
1430        Condition => '$count == 3',
1431        Count => 3,
1432        ValueConv => [
1433            undef,
1434            'exp(($val/8-1)*log(2)/2)',
1435            'exp(($val/8-1)*log(2)/2)',
1436        ],
1437        ValueConvInv => [
1438            undef,
1439            'int(8*(log($val)*2/log(2)+1) + 0.5)',
1440            'int(8*(log($val)*2/log(2)+1) + 0.5)',
1441        ],
1442        PrintConv => [
1443            \%disableEnable,
1444            'sprintf("Closed %.2g",$val)',
1445            'sprintf("Open %.2g",$val)',
1446        ],
1447        PrintConvInv => [
1448            undef,
1449            '$val=~/([\d.]+)/ ? $1 : 0',
1450            '$val=~/([\d.]+)/ ? $1 : 0',
1451        ],
1452    },{ # (EOS R)
1453        Name => 'ApertureRange',
1454        Condition => '$count == 4',
1455        Count => 4,
1456        ValueConv => [ # (NC)
1457            'exp($val/2400)',
1458            'exp($val/2400)',
1459            'exp($val/2400)',
1460            'exp($val/2400)',
1461        ],
1462        ValueConvInv => [
1463            'int(log($val)*2400) + 0.5)',
1464            'int(log($val)*2400) + 0.5)',
1465            'int(log($val)*2400) + 0.5)',
1466            'int(log($val)*2400) + 0.5)',
1467        ],
1468        PrintConv => [ # (NC)
1469            'sprintf("Manual: Closed %.2g",$val)',
1470            'sprintf("Open %.2g",$val)',
1471            'sprintf("Auto: Closed %.2g",$val)',
1472            'sprintf("Open %.2g",$val)',
1473        ],
1474        PrintConvInv => [
1475            '$val=~/([\d.]+)/ ? $1 : 0',
1476            '$val=~/([\d.]+)/ ? $1 : 0',
1477            '$val=~/([\d.]+)/ ? $1 : 0',
1478            '$val=~/([\d.]+)/ ? $1 : 0',
1479        ],
1480    }],
1481    0x010e => {
1482        Name => 'ApplyShootingMeteringMode',
1483        Count => 8,
1484        PrintConv => [ \%disableEnable ],
1485    },
1486    0x010f => [
1487        {
1488            Name => 'FlashSyncSpeedAv',
1489            Condition => '$$self{Model} =~ /\b(40D|1Ds Mark III)\b/',
1490            Notes => '40D and 1Ds Mark III',
1491            PrintConv => {
1492                0 => 'Auto',
1493                1 => '1/250 Fixed',
1494            },
1495        },
1496        {
1497            Name => 'FlashSyncSpeedAv',
1498            Condition => '$$self{Model} =~ /\b(50D|60D|7D)\b/',
1499            Notes => '50D, 60D and 7D',
1500            PrintConv => {
1501                0 => 'Auto',
1502                1 => '1/250-1/60 Auto',
1503                2 => '1/250 Fixed',
1504            },
1505        },
1506        {
1507            Name => 'FlashSyncSpeedAv',
1508            Condition => '$$self{Model} =~ /\b(450D|XSi|Kiss X2|1000D|XS|Kiss F)\b/',
1509            Notes => '450D and 1000D',
1510            PrintConv => {
1511                0 => 'Auto',
1512                1 => '1/200 Fixed',
1513            },
1514        },
1515        {
1516            Name => 'FlashSyncSpeedAv',
1517            Condition => '$$self{Model} =~ /\bEOS-1Ds? Mark III\b/',
1518            Notes => '1D Mark III and 1Ds Mark III',
1519            PrintConv => {
1520                0 => 'Auto',
1521                1 => '1/300 Fixed',
1522            },
1523        },
1524        {
1525            Name => 'FlashSyncSpeedAv',
1526            Condition => '$$self{Model} =~ /\bEOS-1D Mark IV\b/',
1527            Notes => '1D Mark IV',
1528            PrintConv => {
1529                0 => 'Auto',
1530                1 => '1/300-1/60 Auto',
1531                2 => '1/300 Fixed',
1532            },
1533        },
1534        {
1535            Name => 'FlashSyncSpeedAv',
1536            Notes => '5D Mark II, 5D Mark III, 500D, 550D, 600D and 1100D',
1537            PrintConv => {
1538                0 => 'Auto',
1539                1 => '1/200-1/60 Auto',
1540                2 => '1/200 Fixed',
1541            },
1542        },
1543    ],
1544    0x0110 => { # new for 1DmkIV
1545        Name => 'AEMicroadjustment',
1546        Count => 3,
1547        PrintConv => [ \%disableEnable ],
1548    },
1549    0x0111 => { # new for 1DmkIV
1550        Name => 'FEMicroadjustment',
1551        Count => 3,
1552        PrintConv => [ \%disableEnable ],
1553    },
1554    0x0112 => [{ # (5DS)
1555        Name => 'SameExposureForNewAperture',
1556        PrintConv => {
1557            0 => 'Disable',
1558            1 => 'ISO Speed',
1559            2 => 'Shutter Speed',
1560        },
1561    },{ # (EOS R)
1562        Name => 'SameExposureForNewAperture',
1563        Notes => 'EOS R',
1564        PrintConv => {
1565            0 => 'Disable',
1566            1 => 'ISO Speed',
1567            2 => 'ISO Speed/Shutter Speed',
1568            3 => 'Shutter Speed',
1569        },
1570    }],
1571    0x0113 => { # (200D)
1572        Name => 'ExposureCompAutoCancel',
1573        PrintConv => \%enableDisable,
1574    },
1575    0x0114 => { # (R)
1576        Name => 'AELockMeterModeAfterFocus',
1577        # metering modes where AE lock after focus applies:
1578        PrintConv => { BITMASK => { # (NC)
1579            0 => 'Evaluative',
1580            1 => 'Partial',
1581            2 => 'Spot',
1582            3 => 'Center-weighted',
1583        }},
1584    },
1585    #### 2a) Image
1586    0x0201 => {
1587        Name => 'LongExposureNoiseReduction',
1588        PrintConv => {
1589            0 => 'Off',
1590            1 => 'Auto',
1591            2 => 'On',
1592        },
1593    },
1594    0x0202 => [
1595        {
1596            Name => 'HighISONoiseReduction',
1597            Condition => q{
1598                $$self{Model} =~ /\b(50D|60D|5D Mark II|7D|500D|T1i|Kiss X3|550D|T2i|Kiss X4)\b/ or
1599                $$self{Model} =~ /\b(600D|T3i|Kiss X5|1100D|T3|Kiss X50)\b/
1600            },
1601            Notes => '50D, 60D, 500D, 550D, 600D, 1100D, 5DmkII and 7D',
1602            PrintConv => {
1603                0 => 'Standard',
1604                1 => 'Low',
1605                2 => 'Strong',
1606                3 => 'Off',
1607            },
1608        },
1609        {
1610            Name => 'HighISONoiseReduction',
1611            Notes => 'other models',
1612            PrintConv => \%offOn,
1613        },
1614    ],
1615    0x0203 => {
1616        Name => 'HighlightTonePriority',
1617        PrintConv => \%disableEnable
1618    },
1619    0x0204 => [
1620        {
1621            Name => 'AutoLightingOptimizer',
1622            Condition => '$$self{Model} =~ /\b(50D|5D Mark II|500D|T1i|Kiss X3|1D Mark IV)\b/',
1623            Notes => '50D, 500D, 5DmkII and 1DmkIV',
1624            PrintConv => {
1625                0 => 'Standard',
1626                1 => 'Low',
1627                2 => 'Strong',
1628                3 => 'Disable',
1629            },
1630        },
1631        {
1632            Name => 'AutoLightingOptimizer',
1633            Notes => 'other models',
1634            PrintConv => \%enableDisable,
1635        },
1636    ],
1637    # 0x0205 - Added in 5DmkII firmware update
1638    #### 2b) Flash exposure
1639    0x0304 => {
1640        Name => 'ETTLII',
1641        Description => 'E-TTL II',
1642        PrintConv => {
1643            0 => 'Evaluative',
1644            1 => 'Average',
1645        },
1646    },
1647    0x0305 => {
1648        Name => 'ShutterCurtainSync',
1649        PrintConv => {
1650            0 => '1st-curtain sync',
1651            1 => '2nd-curtain sync',
1652        },
1653    },
1654    0x0306 => {
1655        Name => 'FlashFiring',
1656        PrintConv => {
1657            0 => 'Fires',
1658            1 => 'Does not fire',
1659        },
1660    },
1661    #### 2c) Display
1662    0x0407 => {
1663        Name => 'ViewInfoDuringExposure',
1664        PrintConv => \%disableEnable,
1665    },
1666    0x0408 => {
1667        Name => 'LCDIlluminationDuringBulb',
1668        PrintConv => \%offOn,
1669    },
1670    0x0409 => [
1671        {
1672            Name => 'InfoButtonWhenShooting',
1673            Condition => '$$self{Model} =~ /\b1Ds? Mark III\b/',
1674            Notes => '1D Mark III',
1675            PrintConv => {
1676                0 => 'Displays camera settings',
1677                1 => 'Displays shooting functions',
1678            },
1679        },
1680        {
1681            Name => 'InfoButtonWhenShooting',
1682            Notes => '1D Mark IV',
1683            PrintConv => {
1684                # reversed from earlier models. grr...
1685                0 => 'Displays shooting functions',
1686                1 => 'Displays camera settings',
1687            },
1688        },
1689    ],
1690    0x040a => { # new for 5DmkIII
1691        Name => 'ViewfinderWarnings',
1692        PrintConv => { BITMASK => { #(NC)
1693            0 => 'Monochrome',              # (have seen for: 5DmkII, 6D, 250D, 90D)
1694            1 => 'WB corrected',            # (have seen for: 5DmkII, 6D, 90D)
1695            2 => 'One-touch image quality', # (have seen for: 5DmkII; doesn't exist for 6D)
1696            3 => 'ISO expansion',           # (have seen for: 5DmkII)
1697            4 => 'Spot metering',           # (have seen for: 5DmkII, 6D)
1698            6 => 'Noise reduction',         # (have seen for: 250D, 90D)
1699            7 => 'HDR',                     # (have seen for: 90D)
1700        }},
1701    },
1702    0x040b => { # new for 5DmkIII
1703        Name => 'LVShootingAreaDisplay',
1704        PrintConv => {
1705            0 => 'Masked',
1706            1 => 'Outlined',
1707        },
1708    },
1709    0x040c => { # (7DmkII)
1710        Name => 'LVShootingAreaDisplay',
1711        PrintConv => {
1712            0 => 'Masked',
1713            1 => 'Outlined',
1714        },
1715    },
1716    #### 3a) Auto focus
1717    0x0501 => {
1718        Name => 'USMLensElectronicMF',
1719        PrintConv => {
1720            0 => 'Enable after one-shot AF',
1721            1 => 'Disable after one-shot AF',
1722            2 => 'Disable in AF mode',
1723        },
1724    },
1725    0x0502 => {
1726        Name => 'AIServoTrackingSensitivity',
1727        PrintConv => {
1728           -2 => 'Slow',        # (Locked on -2 for 6D)
1729           -1 => 'Medium Slow', # (Locked on -1 for 6D)
1730            0 => 'Standard',
1731            1 => 'Medium Fast', # (Responsive +1 for 6D)
1732            2 => 'Fast',        # (Responsive +2 for 6D)
1733        },
1734    },
1735    0x0503 => {
1736        Name => 'AIServoImagePriority',
1737        PrintConv => {
1738            0 => '1: AF, 2: Tracking',
1739            1 => '1: AF, 2: Drive speed',
1740            2 => '1: Release, 2: Drive speed',
1741            3 => '1: Release, 2: Tracking', # 7D/1DmkIV
1742        },
1743    },
1744    0x0504 => {
1745        Name => 'AIServoTrackingMethod',
1746        PrintConv => {
1747            0 => 'Main focus point priority',
1748            1 => 'Continuous AF track priority',
1749        },
1750    },
1751    0x0505 => {
1752        Name => 'LensDriveNoAF',
1753        PrintConv => {
1754            0 => 'Focus search on',
1755            1 => 'Focus search off',
1756        },
1757    },
1758    0x0506 => {
1759        Name => 'LensAFStopButton',
1760        Notes => 'value of 6 not used by 40D, 50D and 5DmkII',
1761        PrintConv => {
1762            0 => 'AF stop',
1763            1 => 'AF start',
1764            2 => 'AE lock',
1765            3 => 'AF point: M->Auto/Auto->ctr',
1766            4 => 'One Shot <-> AI servo',
1767            5 => 'IS start',
1768            6 => 'Switch to registered AF point',
1769            7 => 'Spot AF', # 1DmkIV
1770        },
1771    },
1772    0x0507 => {
1773        Name => 'AFMicroadjustment',
1774        Count => 5,
1775        PrintConv => [
1776            {
1777                0 => 'Disable',
1778                1 => 'Adjust all by same amount',
1779                2 => 'Adjust by lens',
1780            },
1781            # DECODE OTHER VALUES
1782        ],
1783    },
1784    0x0508 => [
1785        {
1786            Name => 'AFPointAreaExpansion',
1787            Condition => '$$self{Model} =~ /\b5D Mark II\b/',
1788            Notes => '5D Mark II',
1789            PrintConv => {
1790                0 => 'Disable',
1791                1 => 'Enable',
1792            },
1793        },
1794        {
1795            Name => 'AFPointAreaExpansion',
1796            Condition => '$$self{Model} =~ /\b1Ds Mark III\b/',
1797            Notes => '1Ds Mark III',
1798            PrintConv => {
1799                0 => 'Disable',
1800                1 => 'Enable (left/right Assist AF points)',
1801                2 => 'Enable (surrounding Assist AF points)',
1802            },
1803        },
1804        {
1805            Name => 'AFPointAreaExpansion',
1806            Notes => 'other models',
1807            PrintConv => {
1808                0 => 'Disable',
1809                1 => 'Left/right AF points',
1810                2 => 'Surrounding AF points',
1811                3 => 'All 45 points area', # 1DmkIV
1812            },
1813        },
1814    ],
1815    0x0509 => [
1816        {
1817            Name => 'SelectableAFPoint',
1818            Condition => '$$self{Model} =~ /\b1D Mark IV\b/',
1819            Notes => '1D Mark IV',
1820            PrintConv => {
1821                 0 => '45 points',
1822                 1 => '19 points',
1823                 2 => '11 points',
1824                 3 => 'Inner 9 points',
1825                 4 => 'Outer 9 points',
1826            },
1827        },
1828        {
1829            Name => 'SelectableAFPoint',
1830            Notes => 'other models',
1831            PrintConv => {
1832                0 => '19 points',
1833                1 => 'Inner 9 points',
1834                2 => 'Outer 9 points',
1835                3 => '19 Points, Multi-controller selectable', #4
1836                4 => 'Inner 9 Points, Multi-controller selectable', #4
1837                5 => 'Outer 9 Points, Multi-controller selectable', #4
1838            },
1839        },
1840    ],
1841    0x050a => [
1842        {
1843            Name => 'SwitchToRegisteredAFPoint',
1844            Condition => '$$self{Model} =~ /\b1D Mark IV\b/',
1845            Notes => '1D Mark IV',
1846            PrintConv => {
1847                0 => 'Disable',
1848                1 => 'Switch with multi-controller',
1849                2 => 'Only while AEL is pressed',
1850            },
1851        },
1852        {
1853            Name => 'SwitchToRegisteredAFPoint',
1854            Notes => 'other models',
1855            PrintConv => \%disableEnable,
1856        },
1857    ],
1858    0x050b => {
1859        Name => 'AFPointAutoSelection',
1860        PrintConv => {
1861            0 => 'Control-direct:disable/Main:enable',
1862            1 => 'Control-direct:disable/Main:disable',
1863            2 => 'Control-direct:enable/Main:enable',
1864        },
1865    },
1866    0x050c => [
1867        {
1868            Name => 'AFPointDisplayDuringFocus',
1869            Condition => '$$self{Model} =~ /\b1D\b/',
1870            Notes => '1D models',
1871            PrintConv => {
1872                0 => 'On',
1873                1 => 'Off',
1874                2 => 'On (when focus achieved)',
1875            },
1876        },
1877        {
1878            Name => 'AFPointDisplayDuringFocus',
1879            Notes => 'other models', # (7D, 70D, 750D, 760D)
1880            PrintConv => {
1881                0 => 'Selected (constant)',
1882                1 => 'All (constant)',
1883                2 => 'Selected (pre-AF, focused)',
1884                3 => 'Selected (focused)',
1885                4 => 'Disable display',
1886            },
1887        },
1888    ],
1889    0x050d => {
1890        Name => 'AFPointBrightness',
1891        PrintConv => {
1892            0 => 'Normal',
1893            1 => 'Brighter',
1894        },
1895    },
1896    0x050e => [
1897        {
1898            Name => 'AFAssistBeam',
1899            Condition => '$$self{Model} =~ /\b(1D Mark IV|6D)\b/',
1900            Notes => '1D Mark IV and 6D',
1901            PrintConv => {
1902                0 => 'Emits',
1903                1 => 'Does not emit',
1904                2 => 'IR AF assist beam only',
1905            },
1906        },
1907        {
1908            Name => 'AFAssistBeam',
1909            Notes => 'other models; values 2-3 not used by 1DmkIII or 5DmkII, value 3 new for 7D',
1910            PrintConv => {
1911                0 => 'Emits',
1912                1 => 'Does not emit',
1913                2 => 'Only ext. flash emits',
1914                3 => 'IR AF assist beam only', # new for 7D
1915            },
1916        },
1917    ],
1918    0x050f => [ # new for 40D
1919        {
1920            Name => 'AFPointSelectionMethod',
1921            Condition => '$$self{Model} !~ /\b60D\b/',
1922            Notes => '40D, 50D and 5DmkII',
1923            PrintConv => {
1924                0 => 'Normal',
1925                1 => 'Multi-controller direct',
1926                2 => 'Quick Control Dial direct',
1927            },
1928        },
1929        {
1930            Name => 'AFPointSelectionMethod',
1931            Notes => '60D',
1932            PrintConv => {
1933                0 => 'AF point button: Activate AF Sel; Rear dial: Select AF points',
1934                1 => 'AF point button: Auto selection; Rear dial: Manual selection',
1935            },
1936        },
1937        # (this is 2 values for 90D,M6mkII, seen: "1046 1046")
1938    ],
1939    0x0510 => [ # new for 40D
1940        {
1941            Name => 'VFDisplayIllumination', # (7D quirk, or decoded incorrectly?)
1942            Condition => '$$self{Model} =~ /\b7D\b/',
1943            Notes => '7D',
1944            PrintConv => {
1945                0 => 'Auto',
1946                1 => 'Enable',
1947                2 => 'Disable',
1948            },
1949        },
1950        {
1951            Name => 'SuperimposedDisplay',
1952            Notes => 'other models',
1953            PrintConv => \%onOff,
1954        },
1955    ],
1956    0x0511 => [ # new for 40D
1957        {
1958            Name => 'AFDuringLiveView',
1959            Condition => '$$self{Model} =~ /\b40D\b/',
1960            Notes => '40D',
1961            PrintConv => \%disableEnable,
1962        },
1963        {
1964            Name => 'AFDuringLiveView',
1965            Notes => '450D and 1000D',
1966            PrintConv => {
1967                0 => 'Disable',
1968                1 => 'Quick mode',
1969                2 => 'Live mode',
1970            },
1971        },
1972    ],
1973    0x0512 => { # new for 7D
1974        Name => 'SelectAFAreaSelectMode',
1975        PrintConv => [
1976            {
1977                0 => 'Disable',
1978                1 => 'Enable',
1979                2 => 'Register',
1980                3 => 'Select AF-modes',
1981                # also seen: 87 (90D), 1142 (RP)
1982            },
1983            'sprintf("Flags 0x%x",$val)', # (70D=Manual 1pt,Manual zone,Auto 19pt)
1984        ],
1985        PrintConvInv => [
1986            undef,
1987            '$val=~/0x([\dA-F]+)/i ? hex($1) : undef',
1988        ],
1989    },
1990    0x0513 => { # new for 7D
1991        Name => 'ManualAFPointSelectPattern',
1992        PrintConv => {
1993            0 => 'Stops at AF area edges',
1994            1 => 'Continuous',
1995        },
1996    },
1997    0x0514 => { # new for 7D
1998        Name => 'DisplayAllAFPoints',
1999        PrintConv => \%enableDisable,
2000    },
2001    0x0515 => { # new for 7D
2002        Name => 'FocusDisplayAIServoAndMF',
2003        PrintConv => \%enableDisable,
2004    },
2005    0x0516 => { # new for 7D and 1DmkIV
2006        Name => 'OrientationLinkedAFPoint',
2007        PrintConv => {
2008            0 => 'Same for vertical and horizontal',
2009            1 => 'Select different AF points',
2010        },
2011    },
2012    0x0517 => { # new for 1DmkIV
2013        Name => 'MultiControllerWhileMetering',
2014        PrintConv => {
2015            0 => 'Off',
2016            1 => 'AF point selection',
2017        },
2018    },
2019    0x0518 => { # new for 6D
2020        Name => 'AccelerationTracking',
2021    },
2022    0x0519 => { # new for 6D
2023        Name => 'AIServoFirstImagePriority',
2024        PrintConv => { #(NC)
2025            -1 => 'Release priority',
2026            0 => 'Equal priority',
2027            1 => 'Focus priority',
2028        },
2029    },
2030    0x051a => { # new for 6D
2031        Name => 'AIServoSecondImagePriority',
2032        PrintConv => { #(NC)
2033            -1 => 'Shooting speed priority',
2034            0 => 'Equal priority',
2035            1 => 'Focus priority',
2036        },
2037    },
2038    0x051b => { # (70D)
2039        Name => 'AFAreaSelectMethod',
2040        PrintConv => {
2041            0 => 'AF area selection button',
2042            1 => 'Main dial',
2043        },
2044    },
2045    0x051c => { # (750D)
2046        Name => 'AutoAFPointColorTracking',
2047        PrintConv => {
2048            0 => 'On-Shot AF only',
2049            1 => 'Disable',
2050        },
2051    },
2052    0x051d => { # (750D/760D)
2053        Name => 'VFDisplayIllumination',
2054        PrintConv => [{
2055            0 => 'Auto',
2056            1 => 'Enable',
2057            2 => 'Disable',
2058        },{
2059            0 => 'Non-illuminated', #(NC)
2060            1 => 'Illuminated', #(NC)
2061        }],
2062    },
2063    0x051e => { # (80D)
2064        Name => 'InitialAFPointAIServoAF',
2065        PrintConv => {
2066            0 => 'Auto',
2067            1 => 'Initial AF point selected',
2068            2 => 'Manual AF point',
2069        },
2070    },
2071    #### 3b) Drive
2072    0x060f => {
2073        Name => 'MirrorLockup',
2074        Notes => 'value of 2 not used by some models',
2075        PrintConv => {
2076            0 => 'Disable',
2077            1 => 'Enable',
2078            2 => 'Enable: Down with Set',
2079        },
2080    },
2081    0x0610 => [{ # (1DXmkIII)
2082        Name => 'ContinuousShootingSpeed',
2083        Condition => '$count == 6',
2084        Count => 6,
2085        PrintConv => [
2086            \%disableEnable,
2087            '"Hi $val"',
2088            '"Cont $val"',
2089            '"Lo $val"',
2090            '"Soft $val"',
2091            '"Soft LS $val"',
2092        ],
2093        PrintConvInv => [
2094            undef,
2095            '$val=~/(\d+)/ ? $1 : 0',
2096            '$val=~/(\d+)/ ? $1 : 0',
2097            '$val=~/(\d+)/ ? $1 : 0',
2098            '$val=~/(\d+)/ ? $1 : 0',
2099            '$val=~/(\d+)/ ? $1 : 0',
2100        ],
2101    },{ # (1DXmkIII firmware 1.3)
2102        Name => 'ContinuousShootingSpeed',
2103        Condition => '$count == 5',
2104        Count => 5,
2105        PrintConv => [
2106            '"Hi $val"',
2107            '"Cont $val"',
2108            '"Lo $val"',
2109            '"Soft $val"',
2110            '"Soft LS $val"',
2111        ],
2112        PrintConvInv => [
2113            '$val=~/(\d+)/ ? $1 : 0',
2114            '$val=~/(\d+)/ ? $1 : 0',
2115            '$val=~/(\d+)/ ? $1 : 0',
2116            '$val=~/(\d+)/ ? $1 : 0',
2117            '$val=~/(\d+)/ ? $1 : 0',
2118        ],
2119    },{ # others
2120        Name => 'ContinuousShootingSpeed',
2121        Count => 3,
2122        PrintConv => [
2123            \%disableEnable,
2124            '"Hi $val"',
2125            '"Lo $val"',
2126        ],
2127        PrintConvInv => [
2128            undef,
2129            '$val=~/(\d+)/ ? $1 : 0',
2130            '$val=~/(\d+)/ ? $1 : 0',
2131        ],
2132    }],
2133    0x0611 => {
2134        Name => 'ContinuousShotLimit',
2135        Count => 2,
2136        PrintConv => [
2137            \%disableEnable,
2138            '"$val shots"',
2139        ],
2140        PrintConvInv => [
2141            undef,
2142            '$val=~/(\d+)/ ? $1 : 0',
2143        ],
2144    },
2145    0x0612 => [{ # (1DXmkIII)
2146        Name => 'RestrictDriveModes',
2147        Condition => '$count == 1',
2148        Count => 1,
2149        PrintConv => 'sprintf("Flags 0x%x",$val)',
2150        PrintConvInv => '$val=~/0x([\dA-F]+)/i ? hex($1) : undef',
2151    },{ # (1DX)
2152        Name => 'RestrictDriveModes',
2153        Count => 2,
2154        PrintConv => [
2155            \%disableEnable,
2156            'sprintf("Flags 0x%x",$val)', # (Single,Cont Hi,Cont Lo,Timer 10,Timer 2,Silent,Super Hi)
2157        ],
2158        PrintConvInv => [
2159            undef,
2160            '$val=~/0x([\dA-F]+)/i ? hex($1) : undef',
2161        ],
2162    }],
2163    #### 4a) Operation
2164    0x0701 => [
2165        {
2166            Name => 'Shutter-AELock',
2167            Condition => q{
2168                $$self{Model} =~ /\b(1000D|XS|Kiss F|500D|T1i|Kiss X3|550D|T2i|Kiss X4)\b/ or
2169                $$self{Model} =~ /\b(600D|T3i|Kiss X5|1100D|T3|Kiss X50)\b/
2170            },
2171            Notes => '500D, 550D, 600D, 1000D and 1100D',
2172            PrintConv => {
2173                0 => 'AF/AE lock',
2174                1 => 'AE lock/AF',
2175                2 => 'AF/AF lock, No AE lock',
2176                3 => 'AE/AF, No AE lock',
2177            },
2178        },
2179        {
2180            Name => 'Shutter-AELock',
2181            Condition => '$count == 2',
2182            Notes => '250D',
2183            PrintConv => {
2184                '0 0' => 'AF/AE lock',
2185                '1 0' => 'AE lock/AF',
2186                '2 0' => 'AF/AF lock, No AE lock',
2187                '3 0' => 'AE/AF, No AE lock',
2188            },
2189        },
2190        {
2191            Name => 'AFAndMeteringButtons',
2192            Condition => '$$self{Model} =~ /\b60D\b/',
2193            Notes => '60D',
2194            PrintConv => {
2195                0 => 'Metering start',
2196                1 => 'Metering + AF start',
2197                2 => 'AE lock',
2198                3 => 'AF stop',
2199                4 => 'No function',
2200            },
2201        },
2202        {
2203            Name => 'ShutterButtonAFOnButton',
2204            Notes => 'other models',
2205            PrintConv => {
2206                0 => 'Metering + AF start',
2207                1 => 'Metering + AF start/AF stop',
2208                2 => 'Metering start/Meter + AF start',
2209                3 => 'AE lock/Metering + AF start',
2210                4 => 'Metering + AF start/disable',
2211            },
2212        },
2213    ],
2214    0x0702 => {
2215        Name => 'AFOnAELockButtonSwitch',
2216        PrintConv => \%disableEnable,
2217    },
2218    0x0703 => {
2219        Name => 'QuickControlDialInMeter',
2220        PrintConv => {
2221            0 => 'Exposure comp/Aperture',
2222            1 => 'AF point selection',
2223            2 => 'ISO speed',
2224            3 => 'AF point selection swapped with Exposure comp', #4
2225            4 => 'ISO speed swapped with Exposure comp', #4
2226        },
2227    },
2228    0x0704 => [
2229        {
2230            Name => 'SetButtonWhenShooting',
2231            Condition => '$$self{Model} =~ /\b(40D|50D|5D Mark II)\b/',
2232            Notes => '40D, 50D and 5DmkII; value of 5 is new for 50D, and 6 is new for 5DmkII',
2233            PrintConv => {
2234                0 => 'Normal (disabled)',
2235                1 => 'Image quality',
2236                2 => 'Picture style',
2237                3 => 'Menu display',
2238                4 => 'Image playback',
2239                5 => 'Quick control screen', #50D
2240                6 => 'Record movie (Live View)', #5DmkII
2241            },
2242        },
2243        {
2244            Name => 'SetButtonWhenShooting',
2245            Condition => '$$self{Model} =~ /\b60D\b/',
2246            Notes => '60D',
2247            PrintConv => {
2248                0 => 'Normal (disabled)',
2249                1 => 'Image quality',
2250                2 => 'Picture style',
2251                3 => 'White balance',
2252                4 => 'Flash exposure compensation',
2253                5 => 'Viewfinder leveling gauge',
2254            },
2255        },
2256        {
2257            Name => 'SetButtonWhenShooting',
2258            Condition => '$$self{Model} =~ /\b(450D|XSi|Kiss X2|550D|T2i|Kiss X4|600D|T3i|Kiss X5)\b/',
2259            Notes => '450D, 550D and 600D; value of 5 is new for 550D',
2260            PrintConv => {
2261                0 => 'Normal (disabled)',
2262                1 => 'Image quality',
2263                2 => 'Flash exposure compensation',
2264                3 => 'LCD monitor On/Off',
2265                4 => 'Menu display',
2266                5 => 'ISO speed',
2267            },
2268        },
2269        {
2270            Name => 'SetButtonWhenShooting',
2271            Condition => '$$self{Model} =~ /\b(1100D|T3|Kiss X50)\b/',
2272            Notes => '1100D',
2273            PrintConv => {
2274                0 => 'Normal (disabled)',
2275                1 => 'Image quality',
2276                2 => 'Flash exposure compensation',
2277                3 => 'LCD monitor On/Off',
2278                4 => 'Menu display',
2279                5 => 'Depth-of-field preview',
2280            },
2281        },
2282        {
2283            Name => 'SetButtonWhenShooting',
2284            Condition => '$$self{Model} =~ /\b(1000D|XS|Kiss F)\b/',
2285            Notes => '1000D',
2286            PrintConv => {
2287                0 => 'LCD monitor On/Off',
2288                1 => 'Image quality',
2289                2 => 'Flash exposure compensation',
2290                3 => 'Menu display',
2291                4 => 'Disabled',
2292            },
2293        },
2294        {
2295            Name => 'SetButtonWhenShooting',
2296            Condition => '$$self{Model} =~ /\b(500D|T1i|Kiss X3)\b/',
2297            Notes => '500D',
2298            PrintConv => {
2299                0 => 'Quick control screen',
2300                1 => 'Image quality',
2301                2 => 'Flash exposure compensation',
2302                3 => 'LCD monitor On/Off',
2303                4 => 'Menu display',
2304                5 => 'Disabled',
2305            },
2306        },
2307        {
2308            Name => 'SetButtonWhenShooting',
2309            Notes => '250D',
2310            Condition => '$count == 2',
2311            # (not sure how to decode this.  seen: "37 0")
2312            PrintConv => { },
2313        },
2314        {
2315            Name => 'SetButtonWhenShooting',
2316            Notes => '1DmkIII and 1DmkIV',
2317            PrintConv => {
2318                0 => 'Normal (disabled)',
2319                1 => 'White balance',
2320                2 => 'Image size',
2321                3 => 'ISO speed',
2322                4 => 'Picture style',
2323                5 => 'Record func. + media/folder',
2324                6 => 'Menu display',
2325                7 => 'Image playback',
2326            },
2327        },
2328    ],
2329    0x0705 => {
2330        Name => 'ManualTv',
2331        Description => 'Manual Tv/Av For M',
2332        PrintConv => {
2333            0 => 'Tv=Main/Av=Control',
2334            1 => 'Tv=Control/Av=Main',
2335        },
2336    },
2337    0x0706 => {
2338        Name => 'DialDirectionTvAv',
2339        PrintConv => {
2340            0 => 'Normal',
2341            1 => 'Reversed',
2342        },
2343    },
2344    0x0707 => {
2345        Name => 'AvSettingWithoutLens',
2346        PrintConv => \%disableEnable,
2347    },
2348    0x0708 => {
2349        Name => 'WBMediaImageSizeSetting',
2350        PrintConv => {
2351            0 => 'Rear LCD panel',
2352            1 => 'LCD monitor',
2353            2 => 'Off (disable button)', # (1DX)
2354        },
2355    },
2356    0x0709 => {
2357        Name => 'LockMicrophoneButton',
2358        PrintConv => [{
2359            # called "sound" in 1DmkIII manual, and "memo" in 1DmkIV manual
2360            0 => 'Protect (hold:record memo)',
2361            1 => 'Record memo (protect:disable)',
2362            2 => 'Play memo (hold:record memo)', # new with 1DmkIV
2363            3 => 'Rating (protect/memo:disable)', # new with 1DX
2364        }],
2365        # (not sure what the 2nd number is -- new for 1DX.  Seen a value of 31.
2366        # Memo quality may be set to 48kHz or 8kHz through another option that
2367        # doesn't seem to be stored separately -- is this it?)
2368    },
2369    0x070a => {
2370        Name => 'ButtonFunctionControlOff',
2371        PrintConv => {
2372            0 => 'Normal (enable)',
2373            1 => 'Disable main, Control, Multi-control',
2374        },
2375    },
2376    0x070b => { # 50D (also, 5DmkII writes this but it isn't in user guide)
2377        Name => 'AssignFuncButton',
2378        PrintConv => {
2379            0 => 'LCD brightness',
2380            1 => 'Image quality',
2381            2 => 'Exposure comp./AEB setting',
2382            3 => 'Image jump with main dial',
2383            4 => 'Live view function settings',
2384        },
2385    },
2386    0x070c => { # new for 7D
2387        Name => 'CustomControls',
2388        # (too much stuff to decode)
2389    },
2390    0x070d => { # new for 1DmkIV
2391        Name => 'StartMovieShooting',
2392        PrintConv => {
2393            0 => 'Default (from LV)',
2394            1 => 'Quick start (FEL button)',
2395        },
2396    },
2397    0x070e => { # new for 1100D
2398        Name => 'FlashButtonFunction',
2399        PrintConv => {
2400            0 => 'Raise built-in flash',
2401            1 => 'ISO speed',
2402        },
2403    },
2404    0x070f => { # new for 5DmkIII
2405        Name => 'MultiFunctionLock',
2406        PrintConv => [
2407            { #(NC)
2408                0 => 'Off',
2409                1 => 'On', # "On (main dial)" for 750D/760D?
2410                2 => 'On (quick control dial)', #(NC)
2411                3 => 'On (main dial and quick control dial)', #(NC)
2412            },
2413            { BITMASK => { #(NC)
2414                0 => 'Main dial',
2415                1 => 'Quick control dial',
2416                2 => 'Multi-controller',
2417            }},
2418        ],
2419    },
2420    0x0710 => { # (M)
2421        Name => 'TrashButtonFunction',
2422        PrintConv => {
2423            0 => 'Normal (set center AF point)',
2424            1 => 'Depth-of-field preview',
2425        },
2426    },
2427    0x0711 => { # (M)
2428        Name => 'ShutterReleaseWithoutLens',
2429        PrintConv => \%disableEnable,
2430    },
2431    0x0712 => { # (R)
2432        Name => 'ControlRingRotation',
2433        PrintConv => {
2434            0 => 'Normal',
2435            1 => 'Reversed',
2436        },
2437    },
2438    0x0713 => { # (R)
2439        Name => 'FocusRingRotation',
2440        PrintConv => {
2441            0 => 'Normal',
2442            1 => 'Reversed',
2443        },
2444    },
2445    0x0714 => { # (R)
2446        Name => 'RFLensMFFocusRingSensitivity',
2447        PrintConv => {
2448            0 => 'Varies With Rotation Speed',
2449            1 => 'Linked To Rotation Angle',
2450        },
2451    },
2452    0x0715 => { # (R)
2453        Name => 'CustomizeDials', # (NC, may be CustomizeM-FnBar)
2454        # (too much stuff to decode)
2455    },
2456    #### 4b) Others
2457    0x080b => [
2458        {
2459            Name => 'FocusingScreen',
2460            Condition => '$$self{Model} =~ /\b(40D|50D|60D)\b/',
2461            Notes => '40D, 50D and 60D',
2462            PrintConv => {
2463                0 => 'Ef-A',
2464                1 => 'Ef-D',
2465                2 => 'Ef-S',
2466            },
2467        },
2468        {
2469            Name => 'FocusingScreen',
2470            Condition => '$$self{Model} =~ /\b5D Mark II\b/',
2471            Notes => '5D Mark II',
2472            PrintConv => {
2473                0 => 'Eg-A',
2474                1 => 'Eg-D',
2475                2 => 'Eg-S',
2476            },
2477        },
2478        {
2479            Name => 'FocusingScreen',
2480            Condition => '$$self{Model} =~ /\b6D\b/',
2481            Notes => '6D',
2482            PrintConv => {
2483                0 => 'Eg-A II',
2484                1 => 'Eg-D',
2485                2 => 'Eg-S',
2486            },
2487        },
2488        {
2489            Name => 'FocusingScreen',
2490            Condition => '$$self{Model} =~ /\b7D Mark II\b/',
2491            Notes => '7D Mark II',
2492            PrintConv => {
2493                0 => 'Eh-A',
2494                1 => 'Eh-S',
2495            },
2496        },
2497        {
2498            Name => 'FocusingScreen',
2499            Condition => '$$self{Model} =~ /\b1D X\b/',
2500            Notes => '1DX',
2501            PrintConv => {
2502                0 => 'Ec-CV',
2503                1 => 'Ec-A,B,D,H,I,L',
2504            },
2505        },
2506        {
2507            Name => 'FocusingScreen',
2508            Notes => '1DmkIII, 1DSmkIII and 1DmkIV',
2509            PrintConv => {
2510                0 => 'Ec-CIV',
2511                1 => 'Ec-A,B,C,CII,CIII,D,H,I,L',
2512                2 => 'Ec-S',
2513                3 => 'Ec-N,R',
2514            },
2515        },
2516    ],
2517    0x080c => [{ # (1DXmkIII)
2518        Name => 'TimerLength',
2519        Condition => '$count == 3',
2520        Count => 3,
2521        PrintConv => [
2522            '"6 s: $val"',
2523            '"16 s: $val"',
2524            '"After release: $val"',
2525        ],
2526        PrintConvInv => [
2527            '$val=~/(\d+)$/ ? $1 : 0',
2528            '$val=~/(\d+)$/ ? $1 : 0',
2529            '$val=~/(\d+)$/ ? $1 : 0',
2530        ],
2531    },{
2532        Name => 'TimerLength',
2533        Count => 4,
2534        PrintConv => [
2535            \%disableEnable,
2536            '"6 s: $val"',
2537            '"16 s: $val"',
2538            '"After release: $val"',
2539        ],
2540        PrintConvInv => [
2541            undef,
2542            '$val=~/(\d+)$/ ? $1 : 0',
2543            '$val=~/(\d+)$/ ? $1 : 0',
2544            '$val=~/(\d+)$/ ? $1 : 0',
2545        ],
2546    }],
2547    0x080d => {
2548        Name => 'ShortReleaseTimeLag',
2549        PrintConv => \%disableEnable,
2550    },
2551    0x080e => {
2552        Name => 'AddAspectRatioInfo',
2553        PrintConv => {
2554            0 => 'Off',
2555            1 => '6:6',
2556            2 => '3:4',
2557            3 => '4:5',
2558            4 => '6:7',
2559            5 => '10:12',
2560            6 => '5:7',
2561        },
2562    },
2563    0x080f => {
2564        Name => 'AddOriginalDecisionData', # called ("image verification" in 1DmkIV manual)
2565        PrintConv => \%offOn,
2566    },
2567    0x0810 => {
2568        Name => 'LiveViewExposureSimulation',
2569        PrintConv => {
2570            0 => 'Disable (LCD auto adjust)',
2571            1 => 'Enable (simulates exposure)',
2572        },
2573    },
2574    0x0811 => {
2575        Name => 'LCDDisplayAtPowerOn',
2576        PrintConv => {
2577            0 => 'Display',
2578            1 => 'Retain power off status',
2579        },
2580    },
2581    0x0812 => { # (1DX)
2582        Name => 'MemoAudioQuality',
2583        PrintConv => {
2584            0 => 'High (48 kHz)',
2585            1 => 'Low (8 kHz)',
2586        },
2587    },
2588    0x0813 => { # (5DmkIII)
2589        Name => 'DefaultEraseOption',
2590        PrintConv => {
2591            0 => 'Cancel selected',
2592            1 => 'Erase selected',
2593            2 => 'Erase RAW selected', # (1DXmkIII)
2594            3 => 'Erase non-RAW selected', # (1DXmkIII)
2595        },
2596    },
2597    0x0814 => { # (5DS)
2598        Name => 'RetractLensOnPowerOff',
2599        PrintConv => \%enableDisable,
2600    },
2601    0x0815 => { # (R)
2602        Name => 'AddIPTCInformation',
2603        PrintConv => \%disableEnable,
2604    },
2605    0x0816 => { # (90D,RP)
2606        Name => 'AudioCompression',
2607        PrintConv => \%enableDisable,
2608    }
2609);
2610
2611#------------------------------------------------------------------------------
2612# Conversion routines
2613# Inputs: 0) value to convert
2614sub ConvertPfn($)
2615{
2616    my $val = shift;
2617    return $val ? ($val==1 ? 'On' : "On ($val)") : "Off";
2618}
2619sub ConvertPfnInv($)
2620{
2621    my $val = shift;
2622    return $1 if $val =~ /(\d+)/;
2623    return  1 if $val =~ /on/i;
2624    return  0 if $val =~ /off/i;
2625    return undef;
2626}
2627
2628#------------------------------------------------------------------------------
2629# Read/Write Canon custom 2 directory (new for 1D Mark III)
2630# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
2631# Returns: 1 on success
2632sub ProcessCanonCustom2($$$)
2633{
2634    my ($et, $dirInfo, $tagTablePtr) = @_;
2635    my $dataPt = $$dirInfo{DataPt};
2636    my $offset = $$dirInfo{DirStart};
2637    my $size = $$dirInfo{DirLen};
2638    my $write = $$dirInfo{Write};
2639    my $verbose = $et->Options('Verbose');
2640    my $newTags;
2641
2642    return 0 if $size < 2;
2643    # first entry in array must be the size
2644    my $len = Get16u($dataPt, $offset);
2645    unless ($len == $size and $len >= 8) {
2646        $et->Warn('Invalid CanonCustom2 data');
2647        return 0;
2648    }
2649    # get group count
2650    my $count = Get32u($dataPt, $offset + 4);
2651    if ($write) {
2652        $newTags = $et->GetNewTagInfoHash($tagTablePtr);
2653        $et->VPrint(0, "  Rewriting CanonCustom2\n");
2654    } elsif ($verbose) {
2655        $et->VerboseDir('CanonCustom2', $count, $len);
2656    }
2657    my $pos = $offset + 8;
2658    my $end = $offset + $size;
2659    # loop through group records
2660    for (; $pos<$end; ) {
2661        last if $pos + 12 > $end;
2662        my $recNum = Get32u($dataPt, $pos);
2663        my $recLen = Get32u($dataPt, $pos + 4);
2664        my $recCount = Get32u($dataPt, $pos + 8);
2665        last if $recLen < 8;    # must be at least 8 bytes for recNum and recLen
2666        $pos += 12;
2667        my $recPos = $pos;
2668        my $recEnd = $pos + $recLen - 8;
2669        if ($recEnd > $end) {
2670            $et->Warn("Corrupted CanonCustom2 group $recNum");
2671            return 0;
2672        }
2673        if ($verbose and not $write) {
2674            $et->VerboseDir("CanonCustom2 group $recNum", $recCount, $recLen);
2675        }
2676        my ($i, $num, $tag);
2677        for ($i=0; $recPos + 8 < $recEnd; ++$i, $recPos+=4*$num) {
2678            $tag = Get32u($dataPt, $recPos);
2679            $num = Get32u($dataPt, $recPos + 4);
2680            my $nextRec = $recPos + 8 + $num * 4;
2681            last if $nextRec > $recEnd;
2682            # patch for EOS-1DXmkIII firmware 1.0.0 bug:
2683            if ($tag == 0x70c and $num == 0x66 and $nextRec + 8 < $recEnd) {
2684                my $tmp = Get32u($dataPt, $nextRec + 4);
2685                if ($tmp == 0x70f) {
2686                    $et->Warn('Fixed incorrect CanonCustom tag 0x70c size', 1);
2687                    ++$num; # (count should be one greater)
2688                }
2689            }
2690            $recPos += 8;
2691            my $val = ReadValue($dataPt, $recPos, 'int32s', $num, $num * 4);
2692            if ($write) {
2693                # write new value
2694                my $tagInfo = $$newTags{$tag};
2695                next unless $$newTags{$tag};
2696                $tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$val, undef, $num) or next;
2697                my $nvHash = $et->GetNewValueHash($tagInfo) or next;
2698                next unless $et->IsOverwriting($nvHash, $val);
2699                my $newVal = $et->GetNewValue($nvHash);
2700                next unless defined $newVal;    # can't delete from a custom table
2701                WriteValue($newVal, 'int32s', $num, $dataPt, $recPos);
2702                $et->VerboseValue("- CanonCustom:$$tagInfo{Name}", $val);
2703                $et->VerboseValue("+ CanonCustom:$$tagInfo{Name}", $newVal);
2704                ++$$et{CHANGED};
2705            } else {
2706                # save extracted tag
2707                my $oldInfo = $$tagTablePtr{$tag};
2708                $et->HandleTag($tagTablePtr, $tag, $val,
2709                    Index  => $i,
2710                    Format => 'int32u',
2711                    Count  => $num,
2712                    Size   => $num * 4,
2713                );
2714                my $tagInfo = $$tagTablePtr{$tag};
2715                # generate properly formatted description if we just added the tag
2716                if ($tagInfo and not $oldInfo) {
2717                    ($$tagInfo{Description} = $$tagInfo{Name}) =~ tr/_/ /;
2718                    $$tagInfo{Description} =~ s/CanonCustom Functions/Canon Custom Functions /;
2719                }
2720            }
2721        }
2722        if ($i != $recCount) {
2723            $et->Warn('Missing '.($recCount-$i)." entries in CanonCustom2 group $recNum directory", 1);
2724        }
2725        $pos = $recEnd;
2726    }
2727    if ($pos != $end) {
2728        # Note: a firmware bug in the EOS M5 and M6 stores an incorrect
2729        # size for the 2nd CanonCustom2 record, so this message is expected
2730        # for these models...
2731        $et->Warn('Possibly corrupted CanonCustom2 data');
2732        return 0;
2733    }
2734    return 1;
2735}
2736
2737#------------------------------------------------------------------------------
2738# Write Canon custom 2 data
2739# Inputs: 0) ExifTool object reference, 1) dirInfo hash ref, 2) tag table ref
2740# Returns: New custom data block or undefined on error
2741sub WriteCanonCustom2($$$)
2742{
2743    my ($et, $dirInfo, $tagTablePtr) = @_;
2744    $et or return 1;    # allow dummy access to autoload this package
2745    my $dataPt = $$dirInfo{DataPt};
2746    # edit a copy of the custom function 2 data
2747    my $buff = substr($$dataPt, $$dirInfo{DirStart}, $$dirInfo{DirLen});
2748    my %dirInfo = (
2749        DataPt   => \$buff,
2750        DirStart => 0,
2751        DirLen   => $$dirInfo{DirLen},
2752        Write    => 1,
2753    );
2754    ProcessCanonCustom2($et, \%dirInfo, $tagTablePtr) or return undef;
2755    return $buff;
2756}
2757
2758#------------------------------------------------------------------------------
2759# Process Canon custom directory
2760# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
2761# Returns: 1 on success
2762sub ProcessCanonCustom($$$)
2763{
2764    my ($et, $dirInfo, $tagTablePtr) = @_;
2765    my $dataPt = $$dirInfo{DataPt};
2766    my $offset = $$dirInfo{DirStart};
2767    my $size = $$dirInfo{DirLen};
2768    my $verbose = $et->Options('Verbose');
2769
2770    # first entry in array must be the size
2771    my $len = Get16u($dataPt,$offset);
2772    unless ($len == $size or ($$et{Model}=~/\bD60\b/ and $len+2 == $size)) {
2773        $et->Warn("Invalid CanonCustom data");
2774        return 0;
2775    }
2776    $verbose and $et->VerboseDir('CanonCustom', $size/2-1);
2777    my $pos;
2778    for ($pos=2; $pos<$size; $pos+=2) {
2779        # ($pos is position within custom directory)
2780        my $val = Get16u($dataPt,$offset+$pos);
2781        my $tag = ($val >> 8);
2782        $val = ($val & 0xff);
2783        $et->HandleTag($tagTablePtr, $tag, $val,
2784            Index  => $pos/2-1,
2785            Format => 'int8u',
2786            Count  => 1,
2787            Size   => 1,
2788        );
2789    }
2790    return 1;
2791}
2792
2793#------------------------------------------------------------------------------
2794# Check new value for Canon custom data block
2795# Inputs: 0) ExifTool object reference, 1) tagInfo hash ref, 2) raw value ref
2796# Returns: error string or undef (and may modify value) on success
2797sub CheckCanonCustom($$$)
2798{
2799    my ($et, $tagInfo, $valPtr) = @_;
2800    return Image::ExifTool::CheckValue($valPtr, 'int8u');
2801}
2802
2803#------------------------------------------------------------------------------
2804# Write Canon custom data
2805# Inputs: 0) ExifTool object reference, 1) dirInfo hash ref, 2) tag table ref
2806# Returns: New custom data block or undefined on error
2807sub WriteCanonCustom($$$)
2808{
2809    my ($et, $dirInfo, $tagTablePtr) = @_;
2810    $et or return 1;    # allow dummy access to autoload this package
2811    my $dataPt = $$dirInfo{DataPt};
2812    my $dirStart = $$dirInfo{DirStart} || 0;
2813    my $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $dirStart;
2814    my $dirName = $$dirInfo{DirName};
2815    my $newData = substr($$dataPt, $dirStart, $dirLen) or return undef;
2816    $dataPt = \$newData;
2817
2818    # first entry in array must be the size
2819    my $len = Get16u($dataPt, 0);
2820    unless ($len == $dirLen or ($$et{Model}=~/\bD60\b/ and $len+2 == $dirLen)) {
2821        $et->Warn("Invalid CanonCustom data");
2822        return undef;
2823    }
2824    my $newTags = $et->GetNewTagInfoHash($tagTablePtr);
2825    my $pos;
2826    for ($pos=2; $pos<$dirLen; $pos+=2) {
2827        my $val = Get16u($dataPt, $pos);
2828        my $tag = ($val >> 8);
2829        my $tagInfo = $$newTags{$tag};
2830        next unless $tagInfo;
2831        my $nvHash = $et->GetNewValueHash($tagInfo);
2832        $val = ($val & 0xff);
2833        next unless $et->IsOverwriting($nvHash, $val);
2834        my $newVal = $et->GetNewValue($nvHash);
2835        next unless defined $newVal;    # can't delete from a custom table
2836        Set16u(($newVal & 0xff) + ($tag << 8), $dataPt, $pos);
2837        $et->VerboseValue("- $dirName:$$tagInfo{Name}", $val);
2838        $et->VerboseValue("+ $dirName:$$tagInfo{Name}", $newVal);
2839        ++$$et{CHANGED};
2840    }
2841    return $newData;
2842}
2843
2844
28451;  # end
2846
2847__END__
2848
2849=head1 NAME
2850
2851Image::ExifTool::CanonCustom - Read and Write Canon custom functions
2852
2853=head1 SYNOPSIS
2854
2855This module is loaded automatically by Image::ExifTool when required.
2856
2857=head1 DESCRIPTION
2858
2859The Canon custom functions meta information is very specific to the
2860camera model, and is found in both the EXIF maker notes and in the
2861Canon RAW files.  This module contains the definitions necessary for
2862Image::ExifTool to read this information.
2863
2864=head1 AUTHOR
2865
2866Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
2867
2868This library is free software; you can redistribute it and/or modify it
2869under the same terms as Perl itself.
2870
2871=head1 REFERENCES
2872
2873=over 4
2874
2875=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html>
2876
2877=back
2878
2879=head1 ACKNOWLEDGEMENTS
2880
2881Thanks to Christian Koller for his work in decoding the 20D custom
2882functions, Rainer Honle for decoding the 5D custom functions and David
2883Pitcher for adding a few undocumented 1DmkIII settings.
2884
2885=head1 SEE ALSO
2886
2887L<Image::ExifTool::TagNames/Canon Tags>,
2888L<Image::ExifTool(3pm)|Image::ExifTool>
2889
2890=cut
2891