1 /* nikon_desc.c:
2  *
3  * Copyright 2002 Patrick Mansfield <patman@aracnet.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  */
20 #include <stdio.h>
21 #include <_stdint.h>
22 #include <sys/types.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <gphoto2/gphoto2-library.h>
26 #include "sierra.h"
27 #include "library.h"
28 #include "sierra-desc.h"
29 
30 /*
31  * Camera descriptor for Nikon Coolpix 880 (cp880).
32  */
33 
34 /*
35  * Notes:
36  *
37  * The variable "value" in a ValueNameType is the first element of
38  * the name/value union, and so it is the default value initialized.
39  *
40  * To init to a range, use:
41  *	{ .range = { 100.1, 2000.0, 10 } }, NULL
42  *
43  * Casts are used to avoid warnings about using a const.
44  *
45  * Only registers that are used by the camera configuration are listed
46  * here (for use in the get/set config functions); no settings, capture or
47  * other data is stored here.
48  */
49 
50 #ifdef ENABLE_NLS
51 #  include <libintl.h>
52 #  undef _
53 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
54 #  ifdef gettext_noop
55 #    define N_(String) gettext_noop (String)
56 #  else
57 #    define N_(String) (String)
58 #  endif
59 #else
60 #  define textdomain(String) (String)
61 #  define gettext(String) (String)
62 #  define dgettext(Domain,Message) (Message)
63 #  define dcgettext(Domain,Message,Type) (Message)
64 #  define bindtextdomain(Domain,Directory) (Domain)
65 #  define _(String) (String)
66 #  define N_(String) (String)
67 #endif
68 
69 /*
70  * Register 1: resolution/size.
71  */
72 static const ValueNameType cp880_reg_01_val_names[] = {
73 	/*
74 	 * These values suck. why didn't they make these maskable, or use
75 	 * a nibble for each part?  Just use a the combined resolution + size.
76 	 * It would be good to try and break these into two selections.
77 	 */
78 	{ { 0x01 }, "Basic-VGA" },	/* 640 x 480 */
79 	{ { 0x02 }, "Normal-VGA" },
80 	{ { 0x03 }, "Fine-VGA" },
81 	{ { 0x07 }, "Basic-XGA" },	/* 1024 x 768 */
82 	{ { 0x08 }, "Normal-XGA" },
83 	{ { 0x09 }, "Fine-XGA" },
84 	{ { 0x11 }, "Basic-Full" },
85 	{ { 0x12 }, "Normal-Full" },
86 	{ { 0x13 }, "Fine-Full" },
87 	{ { 0x23 }, "Hi-Full" },
88 };
89 static const RegisterDescriptorType cp880_reg_01[] = {
90 	{
91 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
92 		"resolution", N_("Resolution plus Size"),
93 		VAL_NAME_INIT (cp880_reg_01_val_names)
94 	}
95 };
96 
97 /*
98  * Register 1: resolution/size.
99  */
100 static const ValueNameType cp2500_reg_01_val_names[] = {
101 	/*
102 	 * These values suck. why didn't they make these maskable, or use
103 	 * a nibble for each part?  Just use a the combined resolution + size.
104 	 * It would be good to try and break these into two selections.
105 	 */
106 	{ { 0x01 }, "Basic-VGA" },	/* 640 x 480 */
107 	{ { 0x02 }, "Normal-VGA" },
108 	{ { 0x03 }, "Fine-VGA" },
109 
110 	{ { 0x04 }, "Basic-SXGA" },	/* 1280 x 1024 */
111 	{ { 0x05 }, "Normal-SXGA" },
112 	{ { 0x06 }, "Fine-SXGA" },
113 
114 	{ { 0x07 }, "Basic-XGA" },	/* 1024 x 768 */
115 	{ { 0x08 }, "Normal-XGA" },
116 	{ { 0x09 }, "Fine-XGA" },
117 
118 	{ { 0x0a }, "Basic-UXGA" },	/* 1600 x 1200 aka 2 Megapixel */
119 	{ { 0x0b }, "Normal-UXGA" },
120 	{ { 0x0c }, "Fine-UXGA" },
121 
122 };
123 static const RegisterDescriptorType cp2500_reg_01[] = {
124 	{
125 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
126 		"resolution", N_("Resolution plus Size"),
127 		VAL_NAME_INIT (cp2500_reg_01_val_names)
128 	}
129 };
130 
131 /*
132  * Register 2: Date and time.
133  */
134 static const ValueNameType cp880_reg_02_val_names[] = {
135 	/*
136 	 * Dummy value, since we need at least one of these to
137 	 * display anything.
138 	 */
139 	{ { 0x00 }, "Dummy" },
140 };
141 static const RegisterDescriptorType cp880_reg_02[] = {
142 	{
143 		GP_WIDGET_DATE, GP_REG_NO_MASK,
144 		"date-time", N_("Date and time (GMT)"),
145 		VAL_NAME_INIT (cp880_reg_02_val_names)
146 	}
147 };
148 
149 /*
150  * Register 3: shutter speed, cp880 must be in manual mode for this to
151  * work.
152  */
153 #ifdef RANGE_FOR_SHUTTER
154 static const ValueNameType cp880_reg_03_val_names[] = {
155 	{
156 		{ .range = { 0, 8000000 } }, NULL
157 	}
158 };
159 static const RegisterDescriptorType cp880_reg_03[] = {
160 	{
161 		GP_WIDGET_RANGE, GP_REG_NO_MASK,
162 		"shutter", N_("Shutter Speed microseconds (0 auto)"),
163 		VAL_NAME_INIT (cp880_reg_03_val_names)
164 	}
165 };
166 #endif
167 static const ValueNameType cp880_reg_03_val_names[] = {
168 	{ {       0 }, N_("Auto") },
169 	{ {    1000 }, "1/1000" },
170 	{ {    2000 }, "1/500" },
171 	{ {    4000 }, "1/250" },
172 	{ {    8000 }, "1/125" },
173 	{ {   16666 }, "1/60" },
174 	{ {   33333 }, "1/30" },
175 	{ {   66666 }, "1/15" },
176 	{ {  125000 }, "1/8" },
177 	{ {  250000 }, "1/4" },
178 	{ {  500000 }, "1/2" },
179 	{ { 1000000 }, "1" },
180 	{ { 2000000 }, "2" },
181 	{ { 3000000 }, "3" },
182 	{ { 4000000 }, "4" },
183 	{ { 5000000 }, "5" },
184 	{ { 6000000 }, "6" },
185 	{ { 7000000 }, "7" },
186 	{ { 8000000 }, "8" },
187 	/* { { -20 }, "bulb?" }, */
188 
189 };
190 static const RegisterDescriptorType cp880_reg_03[] = {
191 	{
192 		GP_WIDGET_MENU, GP_REG_NO_MASK,
193 		"shutter", N_("Shutter Speed (in seconds)"),
194 		VAL_NAME_INIT (cp880_reg_03_val_names)
195 	}
196 };
197 
198 /*
199  * Register 5: aperture settings (f-stop)
200  */
201 static const ValueNameType cp880_reg_05_val_names[] = {
202 	{ { 0 }, N_("Auto") },
203 	{ { 1 }, N_("Low") },
204 	{ { 2 }, N_("Medium") },
205 	/* { { 4 }, N_("High") }, not on a cp880 */
206 };
207 static const RegisterDescriptorType cp880_reg_05[] = {
208 	{
209 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
210 		"aperture", N_("Aperture Settings"),
211 		VAL_NAME_INIT (cp880_reg_05_val_names)
212 	}
213 };
214 
215 /*
216  * Register 6: color mode (not tested on cp880)
217  */
218 static const ValueNameType cp880_reg_06_val_names[] = {
219 	{ { 1 }, N_("Color") },
220 	{ { 2 }, N_("B/W") },
221 };
222 static const RegisterDescriptorType cp880_reg_06[] = {
223 	{
224 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
225 		"color", N_("Color Mode"),
226 		VAL_NAME_INIT (cp880_reg_06_val_names)
227 	}
228 };
229 
230 /*
231  * Register 7: flash settings
232  */
233 static const ValueNameType cp880_reg_07_val_names[] = {
234 	{ { 0 }, N_("Auto") },
235 	{ { 1 }, N_("Force") },
236 	{ { 2 }, N_("Off") },
237 	{ { 3 }, N_("Anti-redeye") },
238 	{ { 4 }, N_("Slow-sync") },
239 };
240 static const RegisterDescriptorType cp880_reg_07[] = {
241 	{
242 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
243 		"flash", N_("Flash Settings"),
244 		VAL_NAME_INIT (cp880_reg_07_val_names)
245 	}
246 };
247 
248 /*
249  * Register 19: Image adjustment.
250  */
251 static const ValueNameType cp880_reg_19_val_names[] = {
252 	{ { 5 }, N_("Auto") },
253 	{ { 0 }, N_("Normal") },		/* also 0 if chose b+w */
254 	{ { 1 }, N_("Contrast+") },		/* cp880 more contrast */
255 	{ { 2 }, N_("Contrast-") },		/* cp880 less contrast */
256 	{ { 3 }, N_("Brightness+") },	/* cp880 lighten image */
257 	{ { 4 }, N_("Brightness-") },	/* cp880 darken image */
258 };
259 static const RegisterDescriptorType cp880_reg_19[] = {
260 	{
261 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
262 		"image-adj", N_("Image Adjustment"), /* brightness/contrast */
263 		VAL_NAME_INIT (cp880_reg_19_val_names)
264 	}
265 };
266 
267 /*
268  * Register 20: white balance.
269  *
270  * Could not determine how the camera does the gradation in settings -
271  * such as fine +-1,2,3, and FL1 FL2 FL3. Dumping all registers (1 to 90)
272  * shows no changes when going (for example) from fine +3 to -3.
273  *
274  * Setting these via the camera to a +3/2/1 etc, and then changing them
275  * via gphoto2 to another value changes the "type" but the value +3/2/1 is
276  * the same, so there is some other register or setting that changes the
277  * range of these values.
278  *
279  * It appears this needs the sierra extended protocol to be complete.
280  */
281 static const ValueNameType cp880_reg_20_val_names[] = {
282 	{ { 0x00 }, N_("Auto") },
283 	{ { 0x01 }, N_("Fine") },	/* fine +3, +2, ... -3 */
284 	{ { 0x02 }, N_("Incandescent") }, /* incan +3 ... -3 */
285 	{ { 0x03 }, N_("Fluorescent") }, /* FL3, FL2, and FL1 */
286 	{ { 0x05 }, N_("Flash") },	/* speedlight/flash +3 ... -3 */
287 	{ { 0x06 }, N_("Preset") },	/* preset automatically by camera, prob range */
288 	{ { 0xff }, N_("Cloudy") }, /* cloudy +3 ... -3 */
289 };
290 static const RegisterDescriptorType cp880_reg_20[] = {
291 	{
292 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
293 		"whitebalance", N_("White Balance"),
294 		VAL_NAME_INIT (cp880_reg_20_val_names)
295 	}
296 };
297 
298 #ifdef REG_30_FAILS
299 /*
300  * Register 30: LED mode, write only. Writing 0 and 1 do nothing, 2
301  * retracts the lens and causes an error.
302  */
303 static const ValueNameType cp880_reg_30_val_names[] = {
304 	{ { 0x00 }, N_("Off") },
305 	{ { 0x01 }, N_("On") },
306 	{ { 0x02 }, N_("Blink") },
307 };
308 static const RegisterDescriptorType cp880_reg_30[] = {
309 	{
310 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
311 		"led", N_("LED Mode"),
312 		VAL_NAME_INIT (cp880_reg_30_val_names)
313 	}
314 };
315 #endif
316 
317 /*
318  * Register 33: focus mode. Can change these, but macro mode does not work
319  * correctly - it does not zoom in or focus (macro-mode focus) correctly.
320  * And, setting infinity using the cp880 also turns off the flash, here it
321  * does not turn off the flash.
322  */
323 static const ValueNameType cp880_reg_33_val_names[] = {
324 	{ { 0x01 }, N_("Macro") },
325 	{ { 0x02 }, N_("Normal") },
326 	{ { 0x03 }, N_("Infinity") },
327 };
328 static const RegisterDescriptorType cp880_reg_33[] = {
329 	{
330 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
331 		"focus-mode", N_("Focus Mode"),
332 		VAL_NAME_INIT (cp880_reg_33_val_names)
333 	}
334 };
335 
336 /*
337  * Register 34: operation mode. This is only readable, an action with
338  * subaction is required to change the mode.
339  *
340  * Note that on a cp880, sometimes the play mode ends up with a messed up
341  * display or an error message, powering the camera off and on seems to
342  * fix the problem.
343  *
344  * The use of next and previous should be part of a separate
345  * interface, such that a user can continuously press next or previous to
346  * cycle through the images (while the camera is in play mode).
347  *
348  * Use command 2 (via sierra_sub_action) with action
349  * SIERRA_ACTION_LCD_MODE (8), with a sub-action below to change the mode.
350  * So, read reg 34 to figure out the mode, then use sierra_action to
351  * change the mode - the sierra action needs another arg to set the
352  * secondary action for this. The register 34 values match those needed to
353  * change the mode.
354  *
355  * Using a register get/set method of CAM_DESC_SUBACTION enables the
356  * above kluge.
357  */
358 static const ValueNameType cp880_reg_34_val_names[] = {
359 	{ { 0x01 }, N_("Off") },	/* turn off lcd while waiting to capture */
360 	{ { 0x02 }, N_("Record") },	/* turn on lcd while waiting to capture */
361 	{ { 0x03 }, N_("Play") },	/* slide-show like mode */
362 	{ { 0x06 }, N_("Preview Thumbnail") },	/* slide-show thumbnail */
363 	{ { 0x07 }, N_("Next") },			/* go to the next image */
364 	{ { 0x08 }, N_("Previous") },		/* go to previous image */
365 	/*
366 	{ { 0x00 }, "unknown 0x00" },
367 	{ { 0x04 }, "unknown 0x04" },
368 	{ { 0x05 }, "unknown 0x05" },
369 	{ { 0x09 }, "unknown 0x09" },
370 	{ { 0x0a }, "unknown 0x0a" },
371 	{ { 0x0b }, "unknown 0x0b" },
372 	{ { 0x0c }, "unknown 0x0c" },
373 	*/
374 };
375 static const RegisterDescriptorType cp880_reg_34[] = {
376 	{
377 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
378 		"op-mode", N_("Operation Mode"),
379 		VAL_NAME_INIT (cp880_reg_34_val_names)
380 	}
381 };
382 
383 /*
384  * Register 35: lcd brightness.
385  */
386 static const ValueNameType cp880_reg_35_val_names[] = {
387 	{ { .range = { 0, 7 } }, NULL },
388 };
389 static const RegisterDescriptorType cp880_reg_35[] = {
390 	{
391 		GP_WIDGET_RANGE, GP_REG_NO_MASK,
392 		"lcd-brightness", N_("LCD Brightness"),
393 		VAL_NAME_INIT (cp880_reg_35_val_names)
394 	}
395 };
396 
397 /*
398  * Register 38: lcd auto shut off time, not verified for cp880, unknown
399  * what the maximum range should be.
400  */
401 static const ValueNameType cp880_reg_38_val_names[] = {
402 	{ { .range = { 0, 255 /* XXX? */ } }, NULL },
403 };
404 static const RegisterDescriptorType cp880_reg_38[] = {
405 	{
406 		GP_WIDGET_RANGE, GP_REG_NO_MASK,
407 		"lcd-auto-shutoff", N_("LCD Auto Shut Off (seconds)"),
408 		VAL_NAME_INIT (cp880_reg_38_val_names)
409 	}
410 };
411 
412 /*
413  * Register 53: language setting. On the cp880, can set to japanese, but
414  * cannot see any change in this register.
415  *
416  * It appears this needs the sierra extended protocol to be complete.
417  */
418 static const ValueNameType cp880_reg_53_val_names[] = {
419 	{ { 0x03 }, N_("English") },
420 	{ { 0x04 }, N_("French") },
421 	{ { 0x05 }, N_("German") },
422 	/* { { 0x06 }, "Italian" },	not on cp880 */
423 	/* { { 0x08 }, "Spanish" },	not on cp880 */
424 	/* { { 0x0a }, "Dutch" },	not on cp880 */
425 	/* { { 0xnn }, "Japanese" },
426 	 *
427 	 * weird, can set to japanese, but can't see any change in any
428 	 * registers; reg 53 is 3 wether it is english or japanese.
429 	 */
430 };
431 static const RegisterDescriptorType cp880_reg_53[] = {
432 	{
433 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
434 		"language", N_("Language"),
435 		VAL_NAME_INIT (cp880_reg_53_val_names)
436 	}
437 };
438 
439 /*
440  * Register 69: exposure compensation.
441  *
442  * The negative value is properly converted - the camera uses values
443  * compatible with little endian machine (or it is converted by gphoto2?).
444  *
445  * The cp880 sucks here, the register values goes from -20 to 20, but
446  * the only legal values are -20, -17, -13, ..., -7, -3, 0, 3, 7, ..., 20.
447  * It doesn't round, and it is too hard to round using a table, so just
448  * use a pull down menu rather than the more obvious range (slider).
449  */
450 #ifdef RANGE_FOR_EXPOSURE
451 static const ValueNameType cp880_reg_69_val_names[] = {
452 	{
453 		{ .range = { -2.0, 2.0, .1 } }, NULL,
454 	}
455 };
456 static const RegisterDescriptorType cp880_reg_69[] = {
457 	{
458 		GP_WIDGET_RANGE, GP_REG_NO_MASK,
459 		"exp", N_("Exposure Compensation"),
460 		VAL_NAME_INIT (cp880_reg_69_val_names)
461 	}
462 };
463 #endif
464 static const ValueNameType cp880_reg_69_val_names[] = {
465 	{ { -20 }, "-2.0" },
466 	{ { -17 }, "-1.7" },
467 	{ { -13 }, "-1.3" },
468 	{ { -10 }, "-1.0" },
469 	{ { -07 }, "-0.7" },
470 	{ { -03 }, "-0.3" },
471 	{ {  00 }, " 0" },
472 	{ { +03 }, "+0.3" },
473 	{ { +07 }, "+0.7" },
474 	{ { +10 }, "+1.0" },
475 	{ { +13 }, "+1.3" },
476 	{ { +17 }, "+1.7" },
477 	{ { +20 }, "+2.0" },
478 };
479 static const RegisterDescriptorType cp880_reg_69[] = {
480 	{
481 		GP_WIDGET_MENU, GP_REG_NO_MASK,
482 		"exp", N_("Exposure Compensation"),
483 		VAL_NAME_INIT (cp880_reg_69_val_names)
484 	}
485 };
486 
487 /*
488  * Register 70: exposure meter.
489  */
490 static const ValueNameType cp880_reg_70_val_names[] = {
491 	{ { 0x02 }, N_("Center-Weighted") },
492 	{ { 0x03 }, N_("Spot") },
493 	{ { 0x05 }, N_("Matrix") },
494 	{ { 0x06 }, N_("Spot-AF") },
495 };
496 static const RegisterDescriptorType cp880_reg_70[] = {
497 	{
498 		GP_WIDGET_RADIO, GP_REG_NO_MASK,
499 		"exp-meter", N_("Exposure Metering"),
500 		VAL_NAME_INIT (cp880_reg_70_val_names)
501 	}
502 };
503 
504 /*
505  * Register 71: optical zoom value. This does not work on the cp880.
506  *
507  * It appears this needs the sierra extended protocol to be complete.
508  */
509 static const ValueNameType cp880_reg_71_val_names[] = {
510 	{
511 		{ .range = { 8.0, 20.0, .1 } }, NULL
512 	}
513 };
514 static const RegisterDescriptorType cp880_reg_71[] = {
515 	{
516 		GP_WIDGET_RANGE, GP_REG_NO_MASK,
517 		"zoom", N_("Zoom (in millimeters)"),
518 		VAL_NAME_INIT (cp880_reg_71_val_names)
519 	}
520 };
521 
522 /*
523  * Register 72: digital zoom, not fully working for cp880. This is likely
524  * related to the optical zoom not working, as the digital zoom modifies
525  * register 71 (when done from the camera). I can only set it to 2.0.
526  *
527  * It appears this needs the sierra extended protocol to be complete.
528  *
529  * The hi portion (mask 0xff00) has digital zoom values. On the cp880, it
530  * looks like the regular zoom + the digital zoom value determine the
531  * actual digital zoom used (the optical zoom must be at max before the
532  * camera goes to a digital zoom).
533  *
534  * The low portion (mask 0x00ff) seems to have three values, none verified
535  * on the cp880 - mabye should probably be split further.
536  */
537 #ifdef OLD_WAY
538 static const ValueNameType cp880_reg_72_mask_hi_val_names[] = {
539 	{ { 0x0100 }, "1.25" },
540 	{ { 0x0200 }, "1.60" },
541 	{ { 0x0300 }, "2.00" },
542 	{ { 0x0400 }, "2.50" },
543 	{ { 0x0500 }, N_("none") },
544 };
545 static const ValueNameType cp880_reg_72_mask_lo_val_names[] = {
546 	{ { 0x0001 }, N_("AE-lock") },
547 	{ { 0x0002 }, N_("Fisheye") },
548 	{ { 0x0004 }, N_("Wide") },
549 };
550 static const RegisterDescriptorType cp880_reg_72[] = {
551 	{
552 		GP_WIDGET_RADIO, 0xff00,
553 		"dzoom", N_("Digital Zoom"),
554 		VAL_NAME_INIT (cp880_reg_72_mask_hi_val_names)
555 	},
556 	{
557 		GP_WIDGET_RADIO, 0x00ff,
558 		"misc-exp-lenses", N_("Misc exposure/lens settings"),
559 		VAL_NAME_INIT (cp880_reg_72_mask_lo_val_names)
560 	},
561 };
562 #endif
563 static const ValueNameType cp880_reg_72_mask_hi_val_names[] = {
564 	{ { 0x00 }, N_("off") },
565 	{ { 0x08 }, N_("on") },
566 
567 };
568 static const ValueNameType cp880_reg_72_mask_lo_val_names[] = {
569 	{ { 0x00 }, N_("off") },
570 	{ { 0x01 }, N_("on") },
571 };
572 
573 static const RegisterDescriptorType cp880_reg_72[] = {
574 	{
575 		GP_WIDGET_RADIO, 0x08,
576 		"dzoom", N_("Digital Zoom"),
577 		VAL_NAME_INIT (cp880_reg_72_mask_hi_val_names)
578 	},
579 	{
580 		GP_WIDGET_RADIO, 0x01,
581 		"ael", N_("Auto exposure lock"),
582 		VAL_NAME_INIT (cp880_reg_72_mask_lo_val_names)
583 	},
584 };
585 
586 /*
587  * All of the register used to modify picture settings. The register value
588  * received from the camera is stored into this data area, so it cannot be
589  * a const.
590  */
591 static CameraRegisterType cp880_pic_regs[] =  {
592 	/* camera prefix, register number, size of register */
593 	CAM_REG_TYPE_INIT (cp880, 01, 4, CAM_DESC_DEFAULT, 0), /* resolution/size */
594 	CAM_REG_TYPE_INIT (cp880, 03, 4, CAM_DESC_DEFAULT, 0), /* shutter */
595 	CAM_REG_TYPE_INIT (cp880, 05, 4, CAM_DESC_DEFAULT, 0), /* aperture (f-stop) */
596 	CAM_REG_TYPE_INIT (cp880, 06, 4, CAM_DESC_DEFAULT, 0), /* color mode */
597 	CAM_REG_TYPE_INIT (cp880, 07, 4, CAM_DESC_DEFAULT, 0), /* flash */
598 	CAM_REG_TYPE_INIT (cp880, 19, 4, CAM_DESC_DEFAULT, 0), /* brightness/contrast */
599 	CAM_REG_TYPE_INIT (cp880, 20, 4, CAM_DESC_DEFAULT, 0), /* white balance */
600 #ifdef REG_30_FAILS
601 	CAM_REG_TYPE_INIT (cp880, 30, 4, CAM_DESC_DEFAULT, 0), /* LED mode */
602 #endif
603 	CAM_REG_TYPE_INIT (cp880, 33, 4, CAM_DESC_DEFAULT, 0), /* focus mode */
604 	CAM_REG_TYPE_INIT (cp880, 69, 8, CAM_DESC_DEFAULT, 0), /* exposure compensation */
605 	CAM_REG_TYPE_INIT (cp880, 70, 4, CAM_DESC_DEFAULT, 0), /* exposure metering */
606 	CAM_REG_TYPE_INIT (cp880, 71, 8, CAM_DESC_DEFAULT, 0), /* optical zoom */
607 	CAM_REG_TYPE_INIT (cp880, 72, 4, CAM_DESC_DEFAULT, 0), /* digital zoom + lense +  AE lock */
608 };
609 
610 /*
611  * All of the register used to modify camera settings.
612  */
613 static CameraRegisterType cp880_cam_regs[] = {
614 	CAM_REG_TYPE_INIT (cp880, 02, 4, CAM_DESC_DEFAULT, 0), /* date-time */
615 	CAM_REG_TYPE_INIT (cp880, 34, 4, CAM_DESC_SUBACTION,
616 			  SIERRA_ACTION_LCD_MODE), /* lcd mode */
617 	CAM_REG_TYPE_INIT (cp880, 35, 4, CAM_DESC_DEFAULT, 0), /* LCD brightness */
618 	CAM_REG_TYPE_INIT (cp880, 38, 4, CAM_DESC_DEFAULT, 0), /* LCD auto shutoff */
619 	CAM_REG_TYPE_INIT (cp880, 53, 4, CAM_DESC_DEFAULT, 0), /* language */
620 };
621 
622 /*
623  * All of the register used to modify picture settings. The register value
624  * received from the camera is stored into this data area, so it cannot be
625  * a const.
626  */
627 static CameraRegisterType cp2500_pic_regs[] =  {
628 	/* camera prefix, register number, size of register */
629 	CAM_REG_TYPE_INIT (cp2500, 01, 4, CAM_DESC_DEFAULT, 0), /* resolution/size */
630 	CAM_REG_TYPE_INIT (cp880, 06, 4, CAM_DESC_DEFAULT, 0), /* color mode */
631 	CAM_REG_TYPE_INIT (cp880, 07, 4, CAM_DESC_DEFAULT, 0), /* flash */
632 	CAM_REG_TYPE_INIT (cp880, 19, 4, CAM_DESC_DEFAULT, 0), /* brightness/contrast */
633 	CAM_REG_TYPE_INIT (cp880, 20, 4, CAM_DESC_DEFAULT, 0), /* white balance */
634 #ifdef REG_30_FAILS
635 	CAM_REG_TYPE_INIT (cp880, 30, 4, CAM_DESC_DEFAULT, 0), /* LED mode */
636 #endif
637 	CAM_REG_TYPE_INIT (cp880, 33, 4, CAM_DESC_DEFAULT, 0), /* focus mode */
638 	CAM_REG_TYPE_INIT (cp880, 69, 8, CAM_DESC_DEFAULT, 0), /* exposure compensation */
639 	CAM_REG_TYPE_INIT (cp880, 70, 4, CAM_DESC_DEFAULT, 0), /* exposure metering */
640 	CAM_REG_TYPE_INIT (cp880, 71, 8, CAM_DESC_DEFAULT, 0), /* optical zoom */
641 	CAM_REG_TYPE_INIT (cp880, 72, 4, CAM_DESC_DEFAULT, 0), /* digital zoom + lense +  AE lock */
642 };
643 
644 /*
645  * All of the register used to modify camera settings.
646  */
647 static CameraRegisterType cp2500_cam_regs[] = {
648 	CAM_REG_TYPE_INIT (cp880, 02, 4, CAM_DESC_DEFAULT, 0), /* date-time */
649 	CAM_REG_TYPE_INIT (cp880, 34, 4, CAM_DESC_SUBACTION,
650 			  SIERRA_ACTION_LCD_MODE), /* lcd mode */
651 	CAM_REG_TYPE_INIT (cp880, 35, 4, CAM_DESC_DEFAULT, 0), /* LCD brightness */
652 	CAM_REG_TYPE_INIT (cp880, 53, 4, CAM_DESC_DEFAULT, 0), /* language */
653 };
654 
655 /*
656  * All of the register used to modify picture settings. The register value
657  * received from the camera is stored into this data area, so it cannot be
658  * a const.
659  */
660 static CameraRegisterType cp4300_pic_regs[] =  {
661 	/* camera prefix, register number, size of register */
662 	CAM_REG_TYPE_INIT (cp880, 01, 4, CAM_DESC_DEFAULT, 0), /* resolution/size */
663 	CAM_REG_TYPE_INIT (cp880, 06, 4, CAM_DESC_DEFAULT, 0), /* color mode */
664 	CAM_REG_TYPE_INIT (cp880, 07, 4, CAM_DESC_DEFAULT, 0), /* flash */
665 	CAM_REG_TYPE_INIT (cp880, 19, 4, CAM_DESC_DEFAULT, 0), /* brightness/contrast */
666 	CAM_REG_TYPE_INIT (cp880, 20, 4, CAM_DESC_DEFAULT, 0), /* white balance */
667 #ifdef REG_30_FAILS
668 	CAM_REG_TYPE_INIT (cp880, 30, 4, CAM_DESC_DEFAULT, 0), /* LED mode */
669 #endif
670 	CAM_REG_TYPE_INIT (cp880, 33, 4, CAM_DESC_DEFAULT, 0), /* focus mode */
671 	CAM_REG_TYPE_INIT (cp880, 69, 8, CAM_DESC_DEFAULT, 0), /* exposure compensation */
672 	CAM_REG_TYPE_INIT (cp880, 70, 4, CAM_DESC_DEFAULT, 0), /* exposure metering */
673 	CAM_REG_TYPE_INIT (cp880, 71, 8, CAM_DESC_DEFAULT, 0), /* optical zoom */
674 	CAM_REG_TYPE_INIT (cp880, 72, 4, CAM_DESC_DEFAULT, 0), /* digital zoom + lense +  AE lock */
675 };
676 
677 /*
678  * All of the register used to modify camera settings.
679  */
680 static CameraRegisterType cp4300_cam_regs[] = {
681 	CAM_REG_TYPE_INIT (cp880, 02, 4, CAM_DESC_DEFAULT, 0), /* date-time */
682 	CAM_REG_TYPE_INIT (cp880, 34, 4, CAM_DESC_SUBACTION,
683 			  SIERRA_ACTION_LCD_MODE), /* lcd mode */
684 	CAM_REG_TYPE_INIT (cp880, 35, 4, CAM_DESC_DEFAULT, 0), /* LCD brightness */
685 	CAM_REG_TYPE_INIT (cp880, 53, 4, CAM_DESC_DEFAULT, 0), /* language */
686 };
687 
688 
689 static const CameraRegisterSetType cp880_desc[] = {
690 	{
691 		N_("Picture Settings"),
692 		SIZE_ADDR (CameraRegisterType, cp880_pic_regs)
693 	},
694 	{
695 		N_("Camera Settings"),
696 		SIZE_ADDR (CameraRegisterType, cp880_cam_regs)
697 	},
698 };
699 
700 static const CameraRegisterSetType cp2500_desc[] = {
701 	{
702 		N_("Picture Settings"),
703 		SIZE_ADDR (CameraRegisterType, cp2500_pic_regs)
704 	},
705 	{
706 		N_("Camera Settings"),
707 		SIZE_ADDR (CameraRegisterType, cp2500_cam_regs)
708 	},
709 };
710 
711 static const CameraRegisterSetType cp4300_desc[] = {
712 	{
713 		N_("Picture Settings"),
714 		SIZE_ADDR (CameraRegisterType, cp4300_pic_regs)
715 	},
716 	{
717 		N_("Camera Settings"),
718 		SIZE_ADDR (CameraRegisterType, cp4300_cam_regs)
719 	},
720 };
721 
722 static const char cp880_manual[] =
723 N_(
724 "Nikon Coolpix 880:\n"
725 "    Camera configuration (or preferences):\n\n"
726 "        The optical zoom does not properly\n"
727 "        function.\n\n"
728 "        Not all configuration settings\n"
729 "        can be properly read or written, for\n"
730 "        example, the fine tuned setting of\n"
731 "        white balance, and the language settings.\n\n"
732 "        Put the camera in 'M' mode in order to\n"
733 "        to set the shutter speed.\n"
734 );
735 
736 /*
737  *  Note: use of the 995 has not been tested, it might not even be
738  *  possible to control the camera via the USB port since it reportedly
739  *  appears as a USB mass storage device.
740  */
741 static const char cp995_manual[] =
742 N_(
743 "Nikon Coolpix 995:\n"
744 "    Camera configuration (preferences) for this\n"
745 "    camera are incomplete, contact the gphoto\n"
746 "    developer mailing list\n"
747 "    if you would like to contribute to this\n"
748 "    driver.\n\n"
749 "    The download should function correctly.\n"
750 );
751 
752 const CameraDescType cp880_cam_desc = { cp880_desc, cp880_manual,
753 	SIERRA_EXT_PROTO, };
754 const CameraDescType cp995_cam_desc = { cp880_desc, cp995_manual,
755 	SIERRA_EXT_PROTO, };
756 const CameraDescType cp2500_cam_desc = { cp2500_desc, cp880_manual,
757 	SIERRA_EXT_PROTO, };
758 const CameraDescType cp4300_cam_desc = { cp4300_desc, cp880_manual,
759 	SIERRA_EXT_PROTO, };
760