1 /*
2  * Copyright (c) 2001-2007, Eric M. Johnston <emj@postal.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Eric M. Johnston.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id: canon.c,v 1.54 2007/12/16 03:06:13 ejohnst Exp $
33  */
34 
35 /*
36  * Exif tag definitions for Canon maker notes.
37  * Developed from http://www.burren.cx/david/canon.html.
38  * EOS 1D and 1Ds contributions from Stan Jirman <stanj@phototrek.org>.
39  * EOS 10D contributions from Jason Montojo <jason.montojo@rogers.com>.
40  * EOS 20D contributions from Per Kristian Hove <Per.Hove@math.ntnu.no>.
41  * EOS 5D contributions from Albert Max Lai <amlai@columbia.edu>.
42  *
43  */
44 
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <math.h>
49 
50 #include "makers.h"
51 
52 
53 /*
54  * Calculate and format an exposure value ("-n.nn EV").
55  */
56 static float
calcev(char * c,int l,int16_t v)57 calcev(char *c, int l, int16_t v)
58 {
59 #if 0	/* Adjustment seems silly.  If someone complains, I'll reconsider. */
60 	int16_t n;
61 
62 	/*
63 	 * XXX 1/3 and 2/3 values seem to be a bit off.  This makes a
64 	 * slight adjustment; may want to revisit.
65 	 */
66 	n = (abs(v) - 32) * (v & 0x8000 ? -1 : 1);
67 	if (n == 20 || n == -12) v++;
68 	else if (n == -20 || n == 12) v--;
69 #endif
70 
71 	if (c) snprintf(c, l, "%.2f EV", (float)v / 32);
72 	return ((float)v / 32);
73 }
74 
75 
76 /* Macro mode. */
77 
78 static struct descrip canon_macro[] = {
79 	{ 1,	"Macro" },
80 	{ 2,	"Normal" },
81 	{ -1,	"Unknown" },
82 };
83 
84 
85 /* Focus type. */
86 
87 static struct descrip canon_focustype[] = {
88 	{ 0,	"Manual" },
89 	{ 1,	"Auto" },
90 	{ 2,	"Auto" },
91 	{ 3,	"Close-Up (Macro Mode)" },
92 	{ 7,	"Infinity Mode" },
93 	{ 8,	"Locked (Pan Mode)" },
94 	{ -1,	"Unknown" },
95 };
96 
97 
98 /* Quality. */
99 
100 static struct descrip canon_quality[] = {
101 	{ 2,	"Normal" },
102 	{ 3,	"Fine" },
103 	{ 5,	"Superfine" },
104 	{ -1,	"Unknown" },
105 };
106 
107 
108 /* Flash mode. */
109 
110 static struct descrip canon_flash[] = {
111 	{ 0,	"Off" },
112 	{ 1,	"Auto" },
113 	{ 2,	"On" },
114 	{ 3,	"Red-Eye Reduction" },
115 	{ 4,	"Slow-Synchro" },
116 	{ 5,	"Red-Eye Reduction (Auto)" },
117 	{ 6,	"Red-Eye Reduction (On)" },
118 	{ 16,	"External Flash" },
119 	{ -1,	"Unknown" },
120 };
121 
122 
123 /* Drive mode. */
124 
125 static struct descrip canon_drive[] = {
126 	{ 0,	"Single" },		/* "Timed" when field 2 is > 0. */
127 	{ 1,	"Continuous" },
128 	{ -1,	"Unknown" },
129 };
130 
131 
132 /* Focus mode. */
133 
134 static struct descrip canon_focus1[] = {
135 	{ 0,	"One-Shot" },
136 	{ 1,	"AI Servo" },
137 	{ 2,	"AI Focus" },
138 	{ 3,	"Manual" },
139 	{ 4,	"Single" },
140 	{ 5,	"Continuous" },
141 	{ 6,	"Manual" },
142 	{ -1,	"Unknown" },
143 };
144 
145 
146 /* Image size. */
147 
148 static struct descrip canon_imagesz[] = {
149 	{ 0,	"Large" },
150 	{ 1,	"Medium" },
151 	{ 2,	"Small" },
152 	{ -1,	"Unknown" },
153 };
154 
155 
156 /* Shooting mode. */
157 
158 static struct descrip canon_shoot[] = {
159 	{ 0,	"Full Auto" },
160 	{ 1,	"Manual" },
161 	{ 2,	"Landscape" },
162 	{ 3,	"Fast Shutter" },
163 	{ 4,	"Slow Shutter" },
164 	{ 5,	"Night" },
165 	{ 6,	"Black & White" },
166 	{ 7,	"Sepia" },
167 	{ 8,	"Portrait" },
168 	{ 9,	"Sports" },
169 	{ 10,	"Macro/Close-Up" },
170 	{ 11,	"Pan Focus" },
171 	{ 19,	"Indoor" },
172 	{ 22,	"Underwater" },
173 	{ 24,	"Kids & Pets" },
174 	{ 25,	"Night Snapshot" },
175 	{ -1,	"Unknown" },
176 };
177 
178 
179 /* Digital zoom. */
180 
181 static struct descrip canon_dzoom[] = {
182 	{ 0,	"None" },
183 	{ 1,	"x2" },
184 	{ 2,	"x4" },
185 	{ -1,	"Unknown" },
186 };
187 
188 
189 /* Contrast, saturation, & sharpness. */
190 
191 static struct descrip canon_range[] = {
192 	{ 0,	"Normal" },
193 	{ 1,	"High" },
194 	{ 0xffff, "Low" },
195 	{ -1,	"Unknown" },
196 };
197 
198 
199 /* ISO speed rating. */
200 
201 static struct descrip canon_iso[] = {
202 	{ 15,	"Auto" },
203 	{ 16,	"50" },
204 	{ 17,	"100" },
205 	{ 18,	"200" },
206 	{ 19,	"400" },
207 	{ -1,	"Unknown" },
208 };
209 
210 
211 /* Metering mode. */
212 
213 static struct descrip canon_meter[] = {
214 	{ 0,	"Default" },
215 	{ 1,	"Spot" },
216 	{ 3,	"Evaluative" },
217 	{ 4,	"Partial" },
218 	{ 5,	"Center-Weighted" },
219 	{ -1,	"Unknown" },
220 };
221 
222 
223 /* Exposure mode. */
224 
225 static struct descrip canon_expmode[] = {
226 	{ 0,	"Easy Shooting" },
227 	{ 1,	"Program" },
228 	{ 2,	"Tv-Priority" },
229 	{ 3,	"Av-Priority" },
230 	{ 4,	"Manual" },
231 	{ 5,	"A-DEP" },
232 	{ 6,	"DEP" },
233 	{ -1,	"Unknown" },
234 };
235 
236 
237 /* White balance. */
238 
239 static struct descrip canon_whitebal[] = {
240 	{ 0,	"Auto" },
241 	{ 1,	"Daylight" },
242 	{ 2,	"Cloudy" },
243 	{ 3,	"Tungsten" },
244 	{ 4,	"Fluorescent" },
245 	{ 5,	"Flash" },
246 	{ 6,	"Custom" },
247 	{ 7,	"Black & White" },
248 	{ 8,	"Shade" },
249 	{ 9,	"Manual Temperature" },
250 	{ 14,	"Daylight Fluorescent" },
251 	{ 15,	"Custom 1" },
252 	{ 16,	"Custom 2" },
253 	{ 17,	"Underwater" },
254 	{ -1,	"Unknown" },
255 };
256 
257 
258 /* Maker note IFD tags. */
259 
260 static struct exiftag canon_tags[] = {
261 	{ 0x0001, TIFF_SHORT, 0,  ED_UNK, "Canon1Tag",
262 	  "Canon Tag1 Offset", NULL },
263 	{ 0x0004, TIFF_SHORT, 0,  ED_UNK, "Canon4Tag",
264 	  "Canon Tag4 Offset", NULL },
265 	{ 0x0006, TIFF_ASCII, 32, ED_VRB, "ImageType",
266 	  "Image Type", NULL },
267 	{ 0x0007, TIFF_ASCII, 24, ED_CAM, "FirmwareVer",
268 	  "Firmware Version", NULL },
269 	{ 0x0008, TIFF_LONG,  1,  ED_IMG, "ImgNum",
270 	  "Image Number", NULL },
271 	{ 0x0009, TIFF_ASCII, 32, ED_CAM, "OwnerName",
272 	  "Owner Name", NULL },
273 	{ 0x000c, TIFF_LONG,  1,  ED_CAM, "Serial",
274 	  "Serial Number", NULL },
275 	{ 0x000f, TIFF_SHORT, 0,  ED_UNK, "CustomFunc",
276 	  "Custom Function", NULL },
277 	{ 0x0090, TIFF_SHORT, 0,  ED_UNK, "CustomFunc",
278 	  "Custom Function", NULL },
279 	{ 0x0093, TIFF_SHORT, 0,  ED_UNK, "Canon93Tag",
280 	  "Canon Tag93 Offset", NULL },
281 	{ 0x0095, TIFF_ASCII, 64, ED_PAS, "LensName",
282 	  "Lens Name", NULL },
283 	{ 0x00a0, TIFF_SHORT, 0,  ED_UNK, "CanonA0Tag",
284 	  "Canon TagA0 Offset", NULL },
285 	{ 0xffff, TIFF_UNKN,  0,  ED_UNK, "CanonUnknown",
286 	  "Canon Unknown", NULL },
287 };
288 
289 
290 /* Fields under tag 0x0001 (camera settings). */
291 
292 static struct exiftag canon_tags01[] = {
293 	{ 0,  TIFF_SHORT, 0, ED_VRB, "Canon1Len",
294 	  "Canon Tag1 Length", NULL },
295 	{ 1,  TIFF_SHORT, 0, ED_IMG, "CanonMacroMode",
296 	  "Macro Mode", canon_macro },
297 	{ 2,  TIFF_SHORT, 0, ED_VRB, "CanonTimerLen",
298 	  "Self-Timer Length", NULL },
299 	{ 3,  TIFF_SHORT, 0, ED_IMG, "CanonQuality",
300 	  "Compression Setting", canon_quality },
301 	{ 4,  TIFF_SHORT, 0, ED_IMG, "CanonFlashMode",
302 	  "Flash Mode", canon_flash },
303 	{ 5,  TIFF_SHORT, 0, ED_IMG, "CanonDriveMode",
304 	  "Drive Mode", canon_drive },
305 	{ 7,  TIFF_SHORT, 0, ED_IMG, "CanonFocusMode",
306 	  "Focus Mode", canon_focus1 },
307 	{ 10, TIFF_SHORT, 0, ED_IMG, "CanonImageSize",
308 	  "Image Size", canon_imagesz },
309 	{ 11, TIFF_SHORT, 0, ED_IMG, "CanonShootMode",
310 	  "Shooting Mode", canon_shoot },
311 	{ 12, TIFF_SHORT, 0, ED_VRB, "CanonDigiZoom",
312 	  "Digital Zoom", NULL },
313 	{ 13, TIFF_SHORT, 0, ED_IMG, "CanonContrast",
314 	  "Contrast", canon_range },
315 	{ 14, TIFF_SHORT, 0, ED_IMG, "CanonSaturate",
316 	  "Saturation", canon_range },
317 	{ 15, TIFF_SHORT, 0, ED_IMG, "CanonSharpness",
318 	  "Sharpness", canon_range },
319 	{ 16, TIFF_SHORT, 0, ED_IMG, "CanonISO",
320 	  "ISO Speed Rating", canon_iso },
321 	{ 17, TIFF_SHORT, 0, ED_IMG, "CanonMeterMode",
322 	  "Metering Mode", canon_meter },
323 	{ 18, TIFF_SHORT, 0, ED_IMG, "CanonFocusType",
324 	  "Focus Type", canon_focustype },
325 	{ 19, TIFF_SHORT, 0, ED_UNK, "CanonAFPoint",
326 	  "Autofocus Point", NULL },
327 	{ 20, TIFF_SHORT, 0, ED_IMG, "CanonExpMode",
328 	  "Exposure Mode", canon_expmode },
329 	{ 23, TIFF_SHORT, 0, ED_UNK, "CanonMaxFocal",
330 	  "Max Focal Length", NULL },
331 	{ 24, TIFF_SHORT, 0, ED_UNK, "CanonMinFocal",
332 	  "Min Focal Length", NULL },
333 	{ 25, TIFF_SHORT, 0, ED_UNK, "CanonFocalUnits",
334 	  "Focal Units/mm", NULL },
335 	{ 28, TIFF_SHORT, 0, ED_UNK, "CanonFlashAct",
336 	  "Flash Activity", NULL },
337 	{ 29, TIFF_SHORT, 0, ED_UNK, "CanonFlashDet",
338 	  "Flash Details", NULL },
339 	{ 36, TIFF_SHORT, 0, ED_VRB, "CanonDZoomRes",
340 	  "Zoomed Resolution", NULL },
341 	{ 37, TIFF_SHORT, 0, ED_VRB, "CanonBZoomRes",
342 	  "Base Zoom Resolution", NULL },
343 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "Canon01Unknown",
344 	  "Canon Tag1 Unknown", NULL },
345 };
346 
347 
348 /* Fields under tag 0x0004 (shot info). */
349 
350 static struct exiftag canon_tags04[] = {
351 	{ 0,  TIFF_SHORT, 0, ED_VRB, "Canon4Len",
352 	  "Canon Tag4 Length", NULL },
353 	{ 2,  TIFF_SHORT, 0, ED_IMG, "CanonSensorSpeed",
354 	  "Sensor ISO Speed", NULL },
355 	{ 6,  TIFF_SHORT, 0, ED_IMG, "CanonExpComp",
356 	  "Exposure Compensation", NULL },
357 	{ 7,  TIFF_SHORT, 0, ED_IMG, "CanonWhiteB",
358 	  "White Balance", canon_whitebal },
359 	{ 9,  TIFF_SHORT, 0, ED_IMG, "CanonSequence",
360 	  "Sequence Number", NULL },
361 	{ 14, TIFF_SHORT, 0, ED_UNK, "CanonAFPoint2",
362 	  "Autofocus Point", NULL },
363 	{ 15, TIFF_SHORT, 0, ED_IMG, "CanonFlashBias",
364 	  "Flash Bias", NULL },
365 	{ 19, TIFF_SHORT, 0, ED_IMG, "CanonSubjDst",
366 	  "Subject Distance", NULL },
367 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "Canon04Unknown",
368 	  "Canon Tag4 Unknown", NULL },
369 };
370 
371 
372 /* Fields under tag 0x00a0 (EOS 1D, 1Ds). */
373 
374 static struct exiftag canon_tagsA0[] = {
375 	{ 0,  TIFF_SHORT, 0, ED_VRB, "CanonA0Len",
376 	  "Canon TagA0 Length", NULL },
377 	{ 9,  TIFF_SHORT, 0, ED_IMG, "CanonColorTemp",
378 	  "Color Temperature", NULL },
379 	{ 10, TIFF_SHORT, 0, ED_IMG, "CanonColorMatrix",
380 	  "Color Matrix", NULL },
381 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "CanonA0Unknown",
382 	  "Canon TagA0 Unknown", NULL },
383 };
384 
385 
386 /* Fields under tag 0x0093 (counter on EOS 1D, 1Ds). */
387 
388 static struct exiftag canon_tags93[] = {
389 	{ 0,  TIFF_SHORT, 0, ED_VRB, "Canon93Len",
390 	  "Canon Tag93 Length", NULL },
391 	{ 1,  TIFF_SHORT, 0, ED_VRB, "CanonActuateMult",
392 	  "Actuation Multiplier", NULL },
393 	{ 2,  TIFF_SHORT, 0, ED_VRB, "CanonActuateCount",
394 	  "Actuation Counter", NULL },
395 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "Canon93Unknown",
396 	  "Canon Tag93 Unknown", NULL },
397 };
398 
399 
400 /* Placeholder for unknown fields. */
401 
402 static struct exiftag canon_tagsunk[] = {
403 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "CanonUnknown",
404 	  "Canon Unknown", NULL },
405 };
406 
407 
408 /* Value descriptions for custom functions. */
409 
410 static struct descrip ccstm_offon[] = {
411 	{ 0,	"Off" },
412 	{ 1,	"On" },
413 	{ -1,	"Unknown" },
414 };
415 
416 static struct descrip ccstm_shutter[] = {
417 	{ 0,	"AF/AE Lock" },
418 	{ 1,	"AE Lock/AF" },
419 	{ 2,	"AF/AF Lock" },
420 	{ 3,	"AE+Release/AE+AF" },
421 	{ -1,	"Unknown" },
422 };
423 
424 static struct descrip ccstm_disen[] = {
425 	{ 0,	"Disabled" },
426 	{ 1,	"Enabled" },
427 	{ -1,	"Unknown" },
428 };
429 
430 static struct descrip ccstm_explvl[] = {
431 	{ 0,	"1/2 Stop" },
432 	{ 1,	"1/3 Stop" },
433 	{ -1,	"Unknown" },
434 };
435 
436 static struct descrip ccstm_autooff[] = {
437 	{ 0,	"Auto" },
438 	{ 1,	"Off" },
439 	{ -1,	"Unknown" },
440 };
441 
442 static struct descrip ccstm_shutspd[] = {
443 	{ 0,	"Auto" },
444 	{ 1,	"1/200 (Fixed)" },
445 	{ -1,	"Unknown" },
446 };
447 
448 static struct descrip ccstm_aebseq[] = {
449 	{ 0,	"0,-,+/Enabled" },
450 	{ 1,	"0,-,+/Disabled" },
451 	{ 2,	"-,0,+/Enabled" },
452 	{ 3,	"-,0,+/Disabled" },
453 	{ -1,	"Unknown" },
454 };
455 
456 static struct descrip ccstm_shutsync[] = {
457 	{ 0,	"1st-Curtain Sync" },
458 	{ 1,	"2nd-Curtain Sync" },
459 	{ -1,	"Unknown" },
460 };
461 
462 static struct descrip ccstm_lensaf[] = {
463 	{ 0,	"AF Stop" },
464 	{ 1,	"Operate AF" },
465 	{ 2,	"Lock AE & Start Timer" },
466 	{ -1,	"Unknown" },
467 };
468 
469 static struct descrip ccstm_endis[] = {
470 	{ 0,	"Enabled" },
471 	{ 1,	"Disabled" },
472 	{ -1,	"Unknown" },
473 };
474 
475 static struct descrip ccstm_menubut[] = {
476 	{ 0,	"Top" },
477 	{ 1,	"Previous (Volatile)" },
478 	{ 2,	"Previous" },
479 	{ -1,	"Unknown" },
480 };
481 
482 static struct descrip ccstm_setbut[] = {
483 	{ 0,	"Not Assigned" },
484 	{ 1,	"Change Quality" },
485 	{ 2,	"Change ISO Speed" },
486 	{ 3,	"Select Parameters" },
487 	{ -1,	"Unknown" },
488 };
489 
490 static struct descrip ccstm_yesno[] = {
491 	{ 0,	"Yes" },
492 	{ 1,	"No" },
493 	{ -1,	"Unknown" },
494 };
495 
496 static struct descrip ccstm_noyes[] = {
497 	{ 0,	"No" },
498 	{ 1,	"Yes" },
499 	{ -1,	"Unknown" },
500 };
501 
502 static struct descrip ccstm_onoff[] = {
503 	{ 0,	"On" },
504 	{ 1,	"Off" },
505 	{ -1,	"Unknown" },
506 };
507 
508 static struct descrip ccstm_afsel[] = {
509 	{ 0,	"H=AF+Main/V=AF+Command" },
510 	{ 1,	"H=Comp+Main/V=Comp+Command" },
511 	{ 2,	"H=Command Only/V=Assist+Main" },
512 	{ 3,	"H=FEL+Main/V=FEL+Command" },
513 	{ -1,	"Unknown" },
514 };
515 
516 static struct descrip ccstm_afill[] = {
517 	{ 0,	"On" },
518 	{ 1,	"Off" },
519 	{ 2,	"On Without Dimming" },
520 	{ 3,	"Brighter" },
521 	{ -1,	"Unknown" },
522 };
523 
524 static struct descrip ccstm_lcdpanels[] = {
525 	{ 0,	"Remain. Shots/File No." },
526 	{ 1,	"ISO/Remain. Shots" },
527 	{ 2,	"ISO/File No." },
528 	{ 3,	"Shots In Folder/Remain. Shots" },
529 	{ -1,	"Unknown" },
530 };
531 
532 static struct descrip ccstm_usmmf[] = {
533 	{ 0,	"Turns On After One-Shot AF" },
534 	{ 1,	"Turns Off After One-Shot AF" },
535 	{ 2,	"Always Turned Off" },
536 	{ -1,	"Unknown" },
537 };
538 
539 static struct descrip ccstm_explvlinc[] = {
540 	{ 0,	"1/3-Stop Set, 1/3-Stop Comp" },
541 	{ 1,	"1-Stop Set, 1/3-Stop Comp" },
542 	{ 2,	"1/2-Stop Set, 1/2-Stop Comp" },
543 	{ -1,	"Unknown" },
544 };
545 
546 static struct descrip ccstm_tvavform[] = {
547 	{ 0,	"Tv=Main/Av=Control" },
548 	{ 1,	"Tv=Control/Av=Main" },
549 	{ 2,	"Tv=Main/Av=Main w/o Lens" },
550 	{ 3,	"Tv=Control/Av=Main w/o Lens" },
551 	{ -1,	"Unknown" },
552 };
553 
554 static struct descrip ccstm_shutterael[] = {
555 	{ 0,	"AF/AE Lock Stop" },
556 	{ 1,	"AE Lock/AF" },
557 	{ 2,	"AF/AF Lock, No AE Lock" },
558 	{ 3,	"AE/AF, No AE Lock" },
559 	{ -1,	"Unknown" },
560 };
561 
562 static struct descrip ccstm_afspot[] = {
563 	{ 0,	"45/Center AF Point" },
564 	{ 1,	"11/Active AF Point" },
565 	{ 2,	"11/Center AF Point" },
566 	{ 3,	"9/Active AF Point" },
567 	{ -1,	"Unknown" },
568 };
569 
570 static struct descrip ccstm_afact[] = {
571 	{ 0,	"Single AF Point" },
572 	{ 1,	"Expanded (TTL. of 7 AF Points)" },
573 	{ 2,	"Automatic Expanded (Max. 13)" },
574 	{ -1,	"Unknown" },
575 };
576 
577 static struct descrip ccstm_regaf[] = {
578 	{ 0,    "Assist + AF" },
579 	{ 1,    "Assist" },
580 	{ 2,    "Only While Pressing Assist" },
581 	{ -1,   "Unknown" },
582 };
583 
584 static struct descrip ccstm_lensaf1[] = {
585 	{ 0,	"AF Stop" },
586 	{ 1,	"AF Start" },
587 	{ 2,	"AE Lock While Metering" },
588 	{ 3,	"AF Point: M->Auto/Auto->Ctr" },
589 	{ 4,	"AF Mode: ONESHOT<->SERVO" },
590 	{ 5,	"IS Start" },
591 	{ -1,	"Unknown" },
592 };
593 
594 static struct descrip ccstm_aisens[] = {
595 	{ 0,	"Standard" },
596 	{ 1,	"Slow" },
597 	{ 2,	"Moderately Slow" },
598 	{ 3,	"Moderately Fast" },
599 	{ 4,	"Fast" },
600 	{ -1,	"Unknown" },
601 };
602 
603 static struct descrip ccstm_fscr[] = {
604 	{ 0,	"Ec-N, R" },
605 	{ 1,	"Ec-A,B,C,CII,CIII,D,H,I,L" },
606 	{ -1,	"Unknown" },
607 };
608 
609 static struct descrip ccstm_10dsetbut[] = {
610 	{ 0,	"Not Assigned" },
611 	{ 1,	"Change Quality" },
612 	{ 2,	"Change Parameters" },
613 	{ 3,	"Menu Display" },
614 	{ 4,	"Image Replay" },
615 	{ -1,	"Unknown" },
616 };
617 
618 static struct descrip ccstm_10dshutter[] = {
619 	{ 0,	"AF/AE Lock" },
620 	{ 1,	"AE Lock/AF" },
621 	{ 2,	"AF/AF Lock, No AE Lock" },
622 	{ 3,	"AE/AF, No AE Lock" },
623 	{ -1,	"Unknown" },
624 };
625 
626 static struct descrip ccstm_assistflash[] = {
627 	{  0,	"Emits/Fires" },
628 	{  1,	"Does Not Emit/Fires" },
629 	{  2,	"Only Ext. Flash Emits/Fires" },
630 	{  3,	"Emits/Does Not Fire" },
631 	{ -1,	"Unknown" },
632 };
633 
634 static struct descrip ccstm_afptreg[] = {
635 	{ 0,	"Center" },
636 	{ 1,	"Bottom" },
637 	{ 2,	"Right" },
638 	{ 3,	"Extreme Right" },
639 	{ 4,	"Automatic" },
640 	{ 5,	"Extreme Left" },
641 	{ 6,	"Left" },
642 	{ 7,	"Top" },
643 	{ -1,	"Unknown" },
644 };
645 
646 static struct descrip ccstm_rawjpeg[] = {
647 	{ 0,	"RAW+Small/Normal" },
648 	{ 1,	"RAW+Small/Fine" },
649 	{ 2,	"RAW+Medium/Normal" },
650 	{ 3,	"RAW+Medium/Fine" },
651 	{ 4,	"RAW+Large/Normal" },
652 	{ 5,	"RAW+Large/Fine" },
653 	{ -1,	"Unknown" },
654 };
655 
656 static struct descrip ccstm_10dmenubut[] = {
657 	{ 0,	"Previous (Volatile)" },
658 	{ 1,	"Previous" },
659 	{ 2,	"Top" },
660 	{ -1,	"Unknown" },
661 };
662 
663 static struct descrip ccstm_assistbut[] = {
664 	{ 0,	"Normal" },
665 	{ 1,	"Select Home Position" },
666 	{ 2,	"Select HP (while pressing)" },
667 	{ 3,	"Av+/- (AF point by QCD)" },
668 	{ 4,	"FE lock" },
669 	{ -1,	"Unknown" },
670 };
671 
672 static struct descrip ccstm_20dexplvl[] = {
673 	{ 0,	"1/3 Stop" },
674 	{ 1,	"1/2 Stop" },
675 	{ -1,	"Unknown" },
676 };
677 
678 static struct descrip ccstm_20dflashsync[] = {
679 	{ 0,	"Auto" },
680 	{ 1,	"1/250 (Fixed)" },
681 	{ -1,	"Unknown" },
682 };
683 
684 static struct descrip ccstm_20dflash[] = {
685 	{  0,	"Fires" },
686 	{  1,	"Does Not Fire" },
687 	{ -1,	"Unknown" },
688 };
689 
690 static struct descrip ccstm_20dafpsel[] = {
691 	{  0,	"Normal" },
692 	{  1,	"Multi-Controller Direct" },
693 	{  2,	"Quick Control Dial Direct" },
694 	{ -1,	"Unknown" },
695 };
696 
697 static struct descrip ccstm_20dettl[] = {
698 	{  0,	"Evaluative" },
699 	{  1,	"Average" },
700 	{ -1,	"Unknown" },
701 };
702 
703 static struct descrip ccstm_5dflashsync[] = {
704 	{ 0,	"Auto" },
705 	{ 1,	"1/200 (Fixed)" },
706 	{ -1,	"Unknown" },
707 };
708 
709 static struct descrip ccstm_5dfscr[] = {
710 	{ 0,	"Ee-A" },
711 	{ 1,	"Ee-D" },
712 	{ 2,	"Ee-S" },
713 	{ -1,	"Unknown" },
714 };
715 
716 
717 /* D30/D60 custom functions. */
718 
719 static struct exiftag canon_d30custom[] = {
720 	{ 1,  TIFF_SHORT, 0, ED_VRB, "D30Custom",
721 	  "Long exposure noise reduction", ccstm_offon },
722 	{ 2,  TIFF_SHORT, 0, ED_VRB, "D30Custom",
723 	  "Shutter/AE lock buttons", ccstm_shutter },
724 	{ 3,  TIFF_SHORT, 0, ED_VRB, "D30Custom",
725 	  "Mirror lockup", ccstm_disen },
726 	{ 4,  TIFF_SHORT, 0, ED_VRB, "D30Custom",
727 	  "Tv/Av and exposure level", ccstm_explvl },
728 	{ 5,  TIFF_SHORT, 0, ED_VRB, "D30Custom",
729 	  "AF-assist light", ccstm_autooff },
730 	{ 6,  TIFF_SHORT, 0, ED_VRB, "D30Custom",
731 	  "Av mode shutter speed", ccstm_shutspd },
732 	{ 7,  TIFF_SHORT, 0, ED_VRB, "D30Custom",
733 	  "AEB sequence/auto cancellation", ccstm_aebseq },
734 	{ 8,  TIFF_SHORT, 0, ED_VRB, "D30Custom",
735 	  "Shutter curtain sync", ccstm_shutsync },
736 	{ 9,  TIFF_SHORT, 0, ED_VRB, "D30Custom",
737 	  "Lens AF stop button", ccstm_lensaf },
738 	{ 10, TIFF_SHORT, 0, ED_VRB, "D30Custom",
739 	  "Fill flash auto reduction", ccstm_endis },
740 	{ 11, TIFF_SHORT, 0, ED_VRB, "D30Custom",
741 	  "Menu button return position", ccstm_menubut },
742 	{ 12, TIFF_SHORT, 0, ED_VRB, "D30Custom",
743 	  "Shooting Set button function", ccstm_setbut },
744 	{ 13, TIFF_SHORT, 0, ED_VRB, "D30Custom",
745 	  "Sensor cleaning", ccstm_disen },
746 	{ 14, TIFF_SHORT, 0, ED_VRB, "D30Custom",
747 	  "Superimposed display", ccstm_onoff },
748 	{ 15, TIFF_SHORT, 0, ED_VRB, "D30Custom",
749 	  "Shutter release w/o CF card", ccstm_yesno },
750 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "D30CustomUnknown",
751 	  "Canon D30/D60 Custom Unknown", NULL },
752 };
753 
754 
755 /* EOS-1D/1Ds custom functions. */
756 
757 static struct exiftag canon_1dcustom[] = {
758 	{ 0,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
759 	  "Focusing screen", ccstm_fscr },
760 	{ 1,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
761 	  "Finder display during exposure", ccstm_offon },
762 	{ 2,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
763 	  "Shutter release w/o CF card", ccstm_yesno },
764 	{ 3,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
765 	  "ISO speed expansion", ccstm_noyes },
766 	{ 4,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
767 	  "Shutter button/AEL button", ccstm_shutterael },
768 	{ 5,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
769 	  "Manual Tv/Av for M", ccstm_tvavform },
770 	{ 6,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
771 	  "Exposure level increments", ccstm_explvlinc },
772 	{ 7,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
773 	  "USM lens electronic MF", ccstm_usmmf },
774 	{ 8,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
775 	  "Top/back LCD panels", ccstm_lcdpanels },
776 	{ 9,  TIFF_SHORT, 0, ED_VRB, "1DCustom",
777 	  "AEB sequence/auto cancellation", ccstm_aebseq },
778 	{ 10, TIFF_SHORT, 0, ED_VRB, "1DCustom",
779 	  "AF point illumination", ccstm_afill },
780 	{ 11, TIFF_SHORT, 0, ED_VRB, "1DCustom",
781 	  "AF point selection", ccstm_afsel },
782 	{ 12, TIFF_SHORT, 0, ED_VRB, "1DCustom",
783 	  "Mirror lockup", ccstm_disen },
784 	{ 13, TIFF_SHORT, 0, ED_VRB, "1DCustom",
785 	  "# AF points/spot metering", ccstm_afspot },
786 	{ 14, TIFF_SHORT, 0, ED_VRB, "1DCustom",
787 	  "Fill flash auto reduction", ccstm_endis },
788 	{ 15, TIFF_SHORT, 0, ED_VRB, "1DCustom",
789 	  "Shutter curtain sync", ccstm_shutsync },
790 	{ 16, TIFF_SHORT, 0, ED_VRB, "1DCustom",
791 	  "Safety shift in Av or Tv", ccstm_disen },
792 	{ 17, TIFF_SHORT, 0, ED_VRB, "1DCustom",
793 	  "AF point activation area", ccstm_afact },
794 	{ 18, TIFF_SHORT, 0, ED_VRB, "1DCustom",
795 	  "Switch to registered AF point", ccstm_regaf },
796 	{ 19, TIFF_SHORT, 0, ED_VRB, "1DCustom",
797 	  "Lens AF stop button", ccstm_lensaf1 },
798 	{ 20, TIFF_SHORT, 0, ED_VRB, "1DCustom",
799 	  "AI servo tracking sensitivity", ccstm_aisens },
800 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "1DCustomUnknown",
801 	  "Canon 1D/1Ds Custom Unknown", NULL },
802 };
803 
804 /* 5D custom functions. */
805 
806 static struct exiftag canon_5dcustom[] = {
807 	{ 0, TIFF_SHORT, 0, ED_VRB, "5DCustom",
808 	  "Focusing Screen", ccstm_5dfscr },
809 	{ 1,  TIFF_SHORT, 0, ED_VRB, "5DCustom",
810 	  "SET button function when shooting", ccstm_10dsetbut },
811 	{ 2,  TIFF_SHORT, 0, ED_VRB, "5DCustom",
812 	  "Long exposure noise reduction", ccstm_offon },
813 	{ 3,  TIFF_SHORT, 0, ED_VRB, "5DCustom",
814 	  "Flash sync speed in Av mode", ccstm_5dflashsync },
815 	{ 4,  TIFF_SHORT, 0, ED_VRB, "5DCustom",
816 	  "Shutter button/AE lock button", ccstm_10dshutter },
817 	{ 5,  TIFF_SHORT, 0, ED_VRB, "5DCustom",
818 	  "AF-assist beam", ccstm_assistflash },
819 	{ 6,  TIFF_SHORT, 0, ED_VRB, "5DCustom",
820 	  "Exposure level increments", ccstm_20dexplvl },
821 	{ 7,  TIFF_SHORT, 0, ED_VRB, "5DCustom",
822 	  "Flash firing", ccstm_20dflash },
823 	{ 8,  TIFF_SHORT, 0, ED_VRB, "5DCustom",
824 	  "ISO expansion", ccstm_offon },
825 	{ 9,  TIFF_SHORT, 0, ED_VRB, "5DCustom",
826 	  "AEB sequence/auto cancellation", ccstm_aebseq },
827 	{ 10, TIFF_SHORT, 0, ED_VRB, "5DCustom",
828 	  "Superimposed display", ccstm_onoff },
829 	{ 11, TIFF_SHORT, 0, ED_VRB, "5DCustom",
830 	  "Menu button display position", ccstm_10dmenubut },
831 	{ 12, TIFF_SHORT, 0, ED_VRB, "5DCustom",
832 	  "Mirror lockup", ccstm_disen },
833 	{ 13, TIFF_SHORT, 0, ED_VRB, "5DCustom",
834 	  "AF point selection method", ccstm_20dafpsel },
835 	{ 14, TIFF_SHORT, 0, ED_VRB, "5DCustom",
836 	  "E-TTL II", ccstm_20dettl },
837 	{ 15, TIFF_SHORT, 0, ED_VRB, "5DCustom",
838 	  "Shutter curtain sync", ccstm_shutsync },
839 	{ 16, TIFF_SHORT, 0, ED_VRB, "5DCustom",
840 	  "Safety shift in Av or Tv", ccstm_disen },
841 	{ 17, TIFF_SHORT, 0, ED_VRB, "5DCustom",
842 	  "Lens AF stop button", ccstm_lensaf1 },
843 	{ 18, TIFF_SHORT, 0, ED_VRB, "5DCustom",
844 	  "Add original decision data", ccstm_offon },
845 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "5DCustomUnknown",
846 	  "Canon 5D Custom Unknown", NULL },
847 };
848 
849 /* 10D custom functions. */
850 
851 static struct exiftag canon_10dcustom[] = {
852 	{ 1,  TIFF_SHORT, 0, ED_VRB, "10DCustom",
853 	  "SET button function when shooting", ccstm_10dsetbut },
854 	{ 2,  TIFF_SHORT, 0, ED_VRB, "10DCustom",
855 	  "Shutter release w/o CF card", ccstm_yesno },
856 	{ 3,  TIFF_SHORT, 0, ED_VRB, "10DCustom",
857 	  "Flash sync speed in Av mode", ccstm_shutspd },
858 	{ 4,  TIFF_SHORT, 0, ED_VRB, "10DCustom",
859 	  "Shutter button/AE lock button", ccstm_10dshutter },
860 	{ 5,  TIFF_SHORT, 0, ED_VRB, "10DCustom",
861 	  "AF-assist beam/Flash firing", ccstm_assistflash },
862 	{ 6,  TIFF_SHORT, 0, ED_VRB, "10DCustom",
863 	  "Exposure level increments", ccstm_explvl },
864 	{ 7,  TIFF_SHORT, 0, ED_VRB, "10DCustom",
865 	  "AF point registration", ccstm_afptreg },
866 	{ 8,  TIFF_SHORT, 0, ED_VRB, "10DCustom",
867 	  "RAW+JPEG recording", ccstm_rawjpeg },
868 	{ 9,  TIFF_SHORT, 0, ED_VRB, "10DCustom",
869 	  "AEB sequence/auto cancellation", ccstm_aebseq },
870 	{ 10, TIFF_SHORT, 0, ED_VRB, "10DCustom",
871 	  "Superimposed display", ccstm_onoff },
872 	{ 11, TIFF_SHORT, 0, ED_VRB, "10DCustom",
873 	  "Menu button display position", ccstm_10dmenubut },
874 	{ 12, TIFF_SHORT, 0, ED_VRB, "10DCustom",
875 	  "Mirror lockup", ccstm_disen },
876 	{ 13, TIFF_SHORT, 0, ED_VRB, "10DCustom",
877 	  "Assist button function", ccstm_assistbut },
878 	{ 14, TIFF_SHORT, 0, ED_VRB, "10DCustom",
879 	  "Fill flash auto reduction", ccstm_endis },
880 	{ 15, TIFF_SHORT, 0, ED_VRB, "10DCustom",
881 	  "Shutter curtain sync", ccstm_shutsync },
882 	{ 16, TIFF_SHORT, 0, ED_VRB, "10DCustom",
883 	  "Safety shift in Av or Tv", ccstm_disen },
884 	{ 17, TIFF_SHORT, 0, ED_VRB, "10DCustom",
885 	  "Lens AF stop button", ccstm_lensaf },
886 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "10DCustomUnknown",
887 	  "Canon 10D Custom Unknown", NULL },
888 };
889 
890 /* 20D custom functions. */
891 
892 static struct exiftag canon_20dcustom[] = {
893 	{ 0,  TIFF_SHORT, 0, ED_VRB, "20DCustom",
894 	  "SET button function when shooting", ccstm_10dsetbut },
895 	{ 1,  TIFF_SHORT, 0, ED_VRB, "20DCustom",
896 	  "Long exposure noise reduction", ccstm_offon },
897 	{ 2,  TIFF_SHORT, 0, ED_VRB, "20DCustom",
898 	  "Flash sync speed in Av mode", ccstm_20dflashsync },
899 	{ 3,  TIFF_SHORT, 0, ED_VRB, "20DCustom",
900 	  "Shutter button/AE lock button", ccstm_10dshutter },
901 	{ 4,  TIFF_SHORT, 0, ED_VRB, "20DCustom",
902 	  "AF-assist beam", ccstm_assistflash },
903 	{ 5,  TIFF_SHORT, 0, ED_VRB, "20DCustom",
904 	  "Exposure level increments", ccstm_20dexplvl },
905 	{ 6,  TIFF_SHORT, 0, ED_VRB, "20DCustom",
906 	  "Flash firing", ccstm_20dflash },
907 	{ 7,  TIFF_SHORT, 0, ED_VRB, "20DCustom",
908 	  "ISO expansion", ccstm_offon },
909 	{ 8,  TIFF_SHORT, 0, ED_VRB, "20DCustom",
910 	  "AEB sequence/auto cancellation", ccstm_aebseq },
911 	{ 9, TIFF_SHORT, 0, ED_VRB, "20DCustom",
912 	  "Superimposed display", ccstm_onoff },
913 	{ 10, TIFF_SHORT, 0, ED_VRB, "20DCustom",
914 	  "Menu button display position", ccstm_10dmenubut },
915 	{ 11, TIFF_SHORT, 0, ED_VRB, "20DCustom",
916 	  "Mirror lockup", ccstm_disen },
917 	{ 12, TIFF_SHORT, 0, ED_VRB, "20DCustom",
918 	  "AF point selection method", ccstm_20dafpsel },
919 	{ 13, TIFF_SHORT, 0, ED_VRB, "20DCustom",
920 	  "E-TTL II", ccstm_20dettl },
921 	{ 14, TIFF_SHORT, 0, ED_VRB, "20DCustom",
922 	  "Shutter curtain sync", ccstm_shutsync },
923 	{ 15, TIFF_SHORT, 0, ED_VRB, "20DCustom",
924 	  "Safety shift in Av or Tv", ccstm_disen },
925 	{ 16, TIFF_SHORT, 0, ED_VRB, "20DCustom",
926 	  "Lens AF stop button", ccstm_lensaf1 },
927 	{ 17, TIFF_SHORT, 0, ED_VRB, "20DCustom",
928 	  "Add original decision data", ccstm_offon },
929 	{ 0xffff, TIFF_SHORT, 0, ED_UNK, "20DCustomUnknown",
930 	  "Canon 20D Custom Unknown", NULL },
931 };
932 
933 
934 /*
935  * Process maker note tag 0x0001 values.
936  */
937 static int
canon_prop01(struct exifprop * aprop,struct exifprop * prop,unsigned char * off,struct exiftags * t)938 canon_prop01(struct exifprop *aprop, struct exifprop *prop,
939     unsigned char *off, struct exiftags *t)
940 {
941 	u_int16_t v = (u_int16_t)aprop->value;
942 
943 	switch (aprop->tag) {
944 	case 2:
945 		aprop->lvl = v ? ED_IMG : ED_VRB;
946 		exifstralloc(&aprop->str, 32);
947 		snprintf(aprop->str, 31, "%d sec", v / 10);
948 		break;
949 	case 5:
950 		/* Change "Single" to "Timed" if #2 > 0. */
951 
952 		if (!v && exif2byte(off + 2 * 2, t->mkrmd.order))
953 			strcpy(aprop->str, "Timed");
954 		break;
955 	case 12:
956 		aprop->lvl = v ? ED_IMG : ED_VRB;
957 
958 		/*
959 		 * Looks like we can calculate zoom level when value
960 		 * is 3 (ref S110).  Calculation is (2 * #37 / #36).
961 		 */
962 
963 		if (v == 3 && prop->count >= 37) {
964 			exifstralloc(&aprop->str, 32);
965 			snprintf(aprop->str, 31, "x%.1f", 2 *
966 			    (float)exif2byte(off + 37 * 2, t->mkrmd.order) /
967 			    (float)exif2byte(off + 36 * 2, t->mkrmd.order));
968 		} else
969 			aprop->str = finddescr(canon_dzoom, v);
970 		break;
971 	case 16:
972 		/* ISO overrides standard one if known. */
973 		if (!strcmp(aprop->str, "Unknown")) {
974 			aprop->lvl = ED_VRB;
975 			break;
976 		}
977 		aprop->override = EXIF_T_ISOSPEED;
978 		break;
979 	case 17:
980 		/* Maker meter mode overrides standard one if known. */
981 		if (!strcmp(aprop->str, "Unknown")) {
982 			aprop->lvl = ED_VRB;
983 			break;
984 		}
985 		aprop->override = EXIF_T_METERMODE;
986 		break;
987 	case 20:
988 		/* With "Easy Shooting", shooting mode is all that matters. */
989 		aprop->lvl = v ? ED_IMG : ED_VRB;
990 		break;
991 	default:
992 		return (FALSE);
993 	}
994 
995 	return (TRUE);
996 }
997 
998 
999 /*
1000  * Process maker note tag 0x0004 values.
1001  */
1002 static int
canon_prop04(struct exifprop * aprop,struct exifprop * prop,unsigned char * off,struct exiftags * t)1003 canon_prop04(struct exifprop *aprop, struct exifprop *prop,
1004     unsigned char *off, struct exiftags *t)
1005 {
1006 	struct exifprop *tmpprop;
1007 	u_int16_t v = (u_int16_t)aprop->value;
1008 	int d;
1009 
1010 	switch (aprop->tag) {
1011 	case 6:
1012 		/* Calculate sensor speed (ISO units). */
1013 		exifstralloc(&aprop->str, 32);
1014 		snprintf(aprop->str, 31, "%d", (int)(exp(calcev(NULL, 0, v) *
1015 		    log(2)) * 100.0 / 32.0 + 0.5));
1016 		break;
1017 
1018 	case 7:
1019 		aprop->override = EXIF_T_WHITEBAL;
1020 		break;
1021 	case 9:
1022 		aprop->lvl = v ? ED_IMG : ED_VRB;
1023 		break;
1024 	case 15:
1025 		exifstralloc(&aprop->str, 16);
1026 		if (calcev(aprop->str, 15, v) == 0.0)
1027 			aprop->lvl = ED_VRB;
1028 		break;
1029 
1030 	/*
1031 	 * Sigh.  Some cameras have a standard Exif subject distance tag,
1032 	 * some do not.  Some express this in mm, some in cm.  (I cannot
1033 	 * for the life of me figure out how to tell what the units are.)
1034 	 * It looks like maybe some of the newer models stick to cm; we'll
1035 	 * assume cm and consider mm by exception.  In any case, we'll only
1036 	 * display the value in the absence of the standard Exif value.
1037 	 * Needless to say, this is pretty ugly.
1038 	 */
1039 
1040 	case 19:
1041 		exifstralloc(&aprop->str, 32);
1042 
1043 		if (!v) {
1044 			aprop->lvl = ED_VRB;
1045 			strcpy(aprop->str, "Unknown");
1046 			break;
1047 		}
1048 
1049 		if (t->model && (!strcmp(t->model, "Canon PowerShot A10") ||
1050 		    !strcmp(t->model, "Canon PowerShot S110") ||
1051 		    !strcmp(t->model, "Canon PowerShot S30") ||
1052 		    !strcmp(t->model, "Canon PowerShot S40") ||
1053 		    !strcmp(t->model, "Canon EOS 10D")))
1054 			d = 1000;
1055 		else
1056 			d = 100;
1057 
1058 		if (v == 0xffff)
1059 			strcpy(aprop->str, "Infinity");
1060 		else
1061 			snprintf(aprop->str, 31, "%.3f m",
1062 			    (float)v / (float)d);
1063 
1064 		if ((tmpprop = findprop(t->props, tags, EXIF_T_DISTANCE))) {
1065 			if (strcmp(tmpprop->str, "Unknown"))
1066 				aprop->lvl = ED_VRB;
1067 			else
1068 				aprop->override = EXIF_T_DISTANCE;
1069 		}
1070 		break;
1071 
1072 	default:
1073 		return (FALSE);
1074 	}
1075 
1076 	return (TRUE);
1077 }
1078 
1079 
1080 /*
1081  * Process maker note tag 0x00a0 values.
1082  */
1083 static int
canon_propA0(struct exifprop * aprop,struct exifprop * prop,unsigned char * off,struct exiftags * t)1084 canon_propA0(struct exifprop *aprop, struct exifprop *prop,
1085     unsigned char *off, struct exiftags *t)
1086 {
1087 
1088 	switch (aprop->tag) {
1089 	case 9:
1090 		exifstralloc(&aprop->str, 32);
1091 		snprintf(aprop->str, 31, "%d K", aprop->value);
1092 		break;
1093 	default:
1094 		return (FALSE);
1095 	}
1096 
1097 	return (TRUE);
1098 }
1099 
1100 
1101 /*
1102  * Common function for a tag's child values.  Pass in the list of tags
1103  * and a function to process them.
1104  */
1105 static int
canon_subval(struct exifprop * prop,struct exiftags * t,struct exiftag * subtags,int (* valfun)())1106 canon_subval(struct exifprop *prop, struct exiftags *t,
1107     struct exiftag *subtags, int (*valfun)())
1108 {
1109 	int i, j;
1110 	u_int16_t v;
1111 	struct exifprop *aprop;
1112 	unsigned char *off = t->mkrmd.btiff + prop->value;
1113 
1114 	/* Check size of tag (first value) if we're not debugging. */
1115 
1116 	if (valfun && exif2byte(off, t->mkrmd.order) != 2 * prop->count) {
1117 		exifwarn("Canon maker tag appears corrupt");
1118 		return (FALSE);
1119 	}
1120 
1121 	if (debug)
1122 		printf("Processing %s (0x%04X) directory, %d entries\n",
1123 		    prop->name, prop->tag, prop->count);
1124 
1125 	for (i = 0; i < (int)prop->count; i++) {
1126 		v = exif2byte(off + i * 2, t->mkrmd.order);
1127 
1128 		aprop = childprop(prop);
1129 		aprop->value = (u_int32_t)v;
1130 		aprop->tag = i;
1131 		aprop->tagset = subtags;
1132 
1133 		/* Lookup property name and description. */
1134 
1135 		for (j = 0; subtags[j].tag < EXIF_T_UNKNOWN &&
1136 		    subtags[j].tag != i; j++);
1137 		aprop->name = subtags[j].name;
1138 		aprop->descr = subtags[j].descr;
1139 		aprop->lvl = subtags[j].lvl;
1140 		if (subtags[j].table)
1141 			aprop->str = finddescr(subtags[j].table, v);
1142 
1143 		dumpprop(aprop, NULL);
1144 
1145 		/* Process individual values.  Returns false if unknown. */
1146 
1147 		if (valfun && !valfun(aprop, prop, off, t)) {
1148 			if (aprop->lvl != ED_UNK)
1149 				continue;
1150 			exifstralloc(&aprop->str, 32);
1151 			snprintf(aprop->str, 31, "num %02d, val 0x%04X", i, v);
1152 		}
1153 	}
1154 
1155 	if (debug)
1156 		printf("\n");
1157 	return (TRUE);
1158 }
1159 
1160 
1161 /*
1162  * Process custom function tag values.
1163  */
1164 static void
canon_custom(struct exifprop * prop,unsigned char * off,enum byteorder o,struct exiftag * table)1165 canon_custom(struct exifprop *prop, unsigned char *off, enum byteorder o,
1166     struct exiftag *table)
1167 {
1168 	int i, j = -1;
1169 	const char *cn;
1170 	char *cv = NULL;
1171 	u_int16_t v;
1172 	struct exifprop *aprop;
1173 
1174 	/*
1175 	 * Check size of tag (first value).
1176 	 * XXX There seems to be a problem with the D60 where it reports the
1177 	 * wrong size, hence the 2nd clause in the if().  Could be related
1178 	 * to the second value being zero?
1179 	 */
1180 
1181 	if (exif2byte(off, o) != 2 * prop->count &&
1182 	    exif2byte(off, o) != 2 * (prop->count - 1)) {
1183 		exifwarn("Canon custom tag appears corrupt");
1184 		return;
1185 	}
1186 
1187 	if (debug)
1188 		printf("Processing %s directory, %d entries\n", prop->name,
1189 		    prop->count);
1190 
1191 	for (i = 1; i < (int)prop->count; i++) {
1192 		v = exif2byte(off + i * 2, o);
1193 
1194 		aprop = childprop(prop);
1195 		aprop->value = v & 0xff;
1196 		aprop->tag = v >> 8 & 0xff;
1197 		aprop->tagset = table;
1198 
1199 		/*
1200 		 * Lookup function name and value.  First byte is function
1201 		 * number; second is function value.
1202 		 */
1203 
1204 		for (j = 0; table[j].tag != EXIF_T_UNKNOWN &&
1205 		    table[j].tag != (v >> 8 & 0xff); j++);
1206 		aprop->name = table[j].name;
1207 		aprop->descr = prop->descr;
1208 		aprop->lvl = table[j].lvl;
1209 		if (table[j].table)
1210 			cv = finddescr(table[j].table,
1211 			    (u_int16_t)(v & 0xff));
1212 		cn = table[j].descr;
1213 
1214 
1215 		dumpprop(aprop, NULL);
1216 
1217 		exifstralloc(&aprop->str, 4 + strlen(cn) +
1218 		    (cv ? strlen(cv) : 10));
1219 
1220 		if (cv && j != -1) {
1221 			snprintf(aprop->str, 4 + strlen(cn) + strlen(cv),
1222 			    "%s - %s", cn, cv);
1223 			free(cv);
1224 			cv = NULL;
1225 		} else {
1226 			snprintf(aprop->str, 4 + strlen(cn) + 10, "%s %d - %d",
1227 			    cn, v >> 8 & 0xff, v & 0xff);
1228 			aprop->str[3 + strlen(cn) + 10] = '\0';
1229 			aprop->lvl = ED_UNK;
1230 		}
1231 	}
1232 
1233 	if (debug)
1234 		printf("\n");
1235 }
1236 
1237 
1238 /*
1239  * Process Canon maker note tags.
1240  */
1241 void
canon_prop(struct exifprop * prop,struct exiftags * t)1242 canon_prop(struct exifprop *prop, struct exiftags *t)
1243 {
1244 	unsigned char *offset;
1245 	u_int16_t flmin = 0, flmax = 0, flunit = 0;
1246 	u_int32_t v, w;
1247 	struct exifprop *tmpprop;
1248 
1249 	switch (prop->tag) {
1250 
1251 	/* Various image data. */
1252 
1253 	case 0x0001:
1254 		if (!canon_subval(prop, t, canon_tags01, canon_prop01))
1255 			break;
1256 
1257 		/*
1258 		 * Create a new value for the lens' focal length range.  If
1259 		 * it's not a zoom lens, we'll make it verbose (it should
1260 		 * match the existing focal length Exif tag).
1261 		 */
1262 
1263 		if (prop->count >= 25) {
1264 			offset = t->mkrmd.btiff + prop->value;
1265 			flmax = exif2byte(offset + 23 * 2, t->mkrmd.order);
1266 			flmin = exif2byte(offset + 24 * 2, t->mkrmd.order);
1267 			flunit = exif2byte(offset + 25 * 2, t->mkrmd.order);
1268 		}
1269 
1270 		if (flunit && (flmin || flmax)) {
1271 			tmpprop = childprop(prop);
1272 			tmpprop->name = "CanonLensSz";
1273 			tmpprop->descr = "Lens Size";
1274 			exifstralloc(&tmpprop->str, 32);
1275 
1276 			if (flmin == flmax) {
1277 				snprintf(tmpprop->str, 31, "%.2f mm",
1278 			    	(float)flmax / (float)flunit);
1279 				tmpprop->lvl = ED_VRB;
1280 			} else {
1281 				snprintf(tmpprop->str, 31, "%.2f - %.2f mm",
1282 				    (float)flmin / (float)flunit,
1283 				    (float)flmax / (float)flunit);
1284 				tmpprop->lvl = ED_PAS;
1285 			}
1286 		}
1287 		break;
1288 
1289 	case 0x0004:
1290 		canon_subval(prop, t, canon_tags04, canon_prop04);
1291 		break;
1292 
1293 	case 0x00a0:
1294 		if (!canon_subval(prop, t, canon_tagsA0, canon_propA0))
1295 			break;
1296 
1297 		/* Color temp is bad if white balance isn't manual. */
1298 
1299 		if ((tmpprop = findprop(t->props, canon_tags04, 7)))
1300 			if (tmpprop->value != 9) {
1301 				if ((tmpprop = findprop(prop, canon_tagsA0, 9)))
1302 					tmpprop->lvl = ED_BAD;
1303 		}
1304 		break;
1305 
1306 	/* Number of actuations. */
1307 
1308 	case 0x0093:
1309 		/*
1310 		 * Alas, meanings of these fields seem to differ according
1311 		 * to camera model.  For the 1D, 1Ds, and 1D2, they are total
1312 		 * number of actuations.  For the 20D, they're the image
1313 		 * number.  For now, we'll make the former behavior default
1314 		 * and the latter an exception.
1315 		 */
1316 
1317 		if (!t->model) {
1318 			exifwarn("Canon model unset; please report to author");
1319 			break;
1320 		}
1321 
1322 		if (!canon_subval(prop, t, canon_tags93, NULL))
1323 			break;
1324 		v = 0;
1325 
1326 		if (strstr(t->model, "20D")) {
1327 
1328 			/* Image number is in two shorts... */
1329 
1330 			if ((tmpprop = findprop(t->props, canon_tags93, 1))) {
1331 				v = tmpprop->value >> 6;
1332 				w = (tmpprop->value & 0x3f) << 8;
1333 
1334 				if ((tmpprop = findprop(prop, canon_tags93, 2)))
1335 					w += tmpprop->value;
1336 				else {
1337 					v = 0;
1338 					w = 0;
1339 				}
1340 			}
1341 
1342 			if (v) {
1343 				tmpprop = childprop(prop);
1344 				tmpprop->name = "ImgNum";
1345 				tmpprop->descr = "Image Number";
1346 				tmpprop->lvl = ED_IMG;
1347 				exifstralloc(&tmpprop->str, 32);
1348 				snprintf(tmpprop->str, 31, "%03d-%04d", v, w);
1349 			}
1350 			break;
1351 		}
1352 
1353 		/* Number of acuations is in two shorts... */
1354 
1355 		if ((tmpprop = findprop(t->props, canon_tags93, 1))) {
1356 			v = tmpprop->value * 65536;
1357 
1358 			if ((tmpprop = findprop(prop, canon_tags93, 2)))
1359 				v += tmpprop->value;
1360 			else
1361 				v = 0;
1362 		}
1363 
1364 		if (v) {
1365 			tmpprop = childprop(prop);
1366 			tmpprop->name = "CanonActuations";
1367 			tmpprop->descr = "Camera Actuations";
1368 			tmpprop->lvl = ED_IMG;
1369 			tmpprop->value = v;
1370 		}
1371 		break;
1372 
1373 	/* Image number. */
1374 
1375 	case 0x0008:
1376 		if (!prop->value)
1377 			prop->lvl = ED_VRB;
1378 		exifstralloc(&prop->str, 32);
1379 		snprintf(prop->str, 31, "%03d-%04d", prop->value / 10000,
1380 		    prop->value % 10000);
1381 		break;
1382 
1383 	/* Serial number. */
1384 
1385 	case 0x000c:
1386 		exifstralloc(&prop->str, 11);
1387 		snprintf(prop->str, 11, "%010d", prop->value);
1388 		break;
1389 
1390 	/* Custom functions. */
1391 
1392 	case 0x000f:
1393 		/*
1394 		 * Canon annoyingly reuses this tag value for different sets
1395 		 * of custom functions (e.g., D30/60, 10D).  Therefore, we
1396 		 * won't try to interpret them unless we know for sure that
1397 		 * the camera model is supported.
1398 		 */
1399 
1400 		if (!t->model) {
1401 			exifwarn("Canon model unset; please report to author");
1402 			break;
1403 		}
1404 
1405 		if (strstr(t->model, "10D"))
1406 			canon_custom(prop, t->mkrmd.btiff + prop->value,
1407 			    t->mkrmd.order, canon_10dcustom);
1408 		else if (strstr(t->model, "D30") || strstr(t->model, "D60"))
1409 			canon_custom(prop, t->mkrmd.btiff + prop->value,
1410 			    t->mkrmd.order, canon_d30custom);
1411 		else if (strstr(t->model, "20D"))
1412 			canon_custom(prop, t->mkrmd.btiff + prop->value,
1413 			    t->mkrmd.order, canon_20dcustom);
1414 		else if (strstr(t->model, "5D"))
1415 			canon_custom(prop, t->mkrmd.btiff + prop->value,
1416 			    t->mkrmd.order, canon_5dcustom);
1417 		else
1418 			exifwarn2("Custom function unsupported; please "
1419 			    "report to author", t->model);
1420 		break;
1421 
1422 	case 0x0090:
1423 		canon_custom(prop, t->mkrmd.btiff + prop->value, t->mkrmd.order,
1424 		    canon_1dcustom);
1425 		break;
1426 
1427 	/* Dump debug for tags of type short w/count > 1. */
1428 
1429 	default:
1430 		if (prop->type == TIFF_SHORT && prop->count > 1 && debug)
1431 			canon_subval(prop, t, canon_tagsunk, NULL);
1432 		break;
1433 	}
1434 }
1435 
1436 
1437 /*
1438  * Try to read Canon maker note IFDs.
1439  */
1440 struct ifd *
canon_ifd(u_int32_t offset,struct tiffmeta * md)1441 canon_ifd(u_int32_t offset, struct tiffmeta *md)
1442 {
1443 
1444 	return (readifds(offset, canon_tags, md));
1445 }
1446