Source code upload
[framework/connectivity/libgphoto2.git] / camlibs / sierra / sierra-desc.c
1 /* sierra-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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <_stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #include <math.h>
28
29 #include <gphoto2/gphoto2-library.h>
30 #include <gphoto2/gphoto2-port-log.h>
31
32 #include "sierra.h"
33 #include "sierra-desc.h"
34 #include "library.h"
35
36 #ifdef ENABLE_NLS
37 #  include <libintl.h>
38 #  undef _
39 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
40 #  ifdef gettext_noop
41 #    define N_(String) gettext_noop (String)
42 #  else
43 #    define N_(String) (String)
44 #  endif
45 #else
46 #  define textdomain(String) (String)
47 #  define gettext(String) (String)
48 #  define dgettext(Domain,Message) (Message)
49 #  define dcgettext(Domain,Message,Type) (Message)
50 #  define bindtextdomain(Domain,Directory) (Domain)
51 #  define _(String) (String)
52 #  define N_(String) (String)
53 #endif
54
55 #define GP_MODULE "sierra"
56
57 /*
58  * For some reason, round() does not get a prototype from math.h.
59  */
60 extern double round(double x);
61
62 static int 
63 camera_cam_desc_get_value (ValueNameType *val_name_p, CameraWidgetType widge, 
64                            uint32_t reg_len, void *buff, int mask, 
65                            CameraWidget *child)
66 {
67         if ((widge == GP_WIDGET_RADIO) || (widge == GP_WIDGET_MENU)) {
68                 gp_widget_add_choice (child, _(val_name_p->name));
69                 GP_DEBUG ("get value %15s:\t%lld (0x%04llx)", 
70                        val_name_p->name, val_name_p->u.value,
71                        val_name_p->u.value);
72                 /* XXX where is endian handled? */
73                 if ((mask & *(int*) buff) == val_name_p->u.value) {
74                         gp_widget_set_value (child, _(val_name_p->name));
75                 }
76         } else if (widge == GP_WIDGET_DATE) {
77                 GP_DEBUG ("get value date/time %s", ctime((time_t *) buff));
78                 gp_widget_set_value (child, (int*) buff);
79         } else if (widge == GP_WIDGET_RANGE) {
80                 float float_val, increment;
81
82                 increment = val_name_p->u.range[2];
83                 if (increment == 0.0) {
84                         /* 
85                          * Use a default value.
86                          */
87                         increment = 1.0;
88                 }
89                 GP_DEBUG ("get value range:\t%08g:%08g increment %g (via %g)", 
90                        val_name_p->u.range[0], val_name_p->u.range[1],
91                        increment, val_name_p->u.range[2]);
92                 gp_widget_set_range (child, val_name_p->u.range[0], 
93                                      val_name_p->u.range[1], increment);
94                 /*
95                  * Kluge: store the value in buff as a 4 byte int, even
96                  * though we might have read 8 bytes or more.
97                  */
98                 float_val = (*(int*) buff) * increment;
99                 gp_widget_set_value (child, &float_val);
100         } else if (widge == GP_WIDGET_BUTTON) {
101                 GP_DEBUG ("get button");
102                 gp_widget_set_value (child, val_name_p->u.callback);
103         } else {
104                 GP_DEBUG ("get value bad widget type %d", widge);
105                 return (GP_ERROR);
106         }
107
108         return (GP_OK);
109 }
110
111 static int
112 camera_cam_desc_get_widget (Camera *camera, CameraRegisterType *reg_p, 
113                             CameraWidget *section, GPContext *context)
114 {
115         int ind, vind, ret, value;
116         int mask;
117         char buff[1024];
118         CameraWidget *child;
119         RegisterDescriptorType *reg_desc_p;
120
121         GP_DEBUG ("register %d", reg_p->reg_number);
122         if (reg_p->reg_len == 0) {
123                 /*
124                  * This is 0 for GP_WIDGET_BUTTON (callbacks), since is no
125                  * register for call backs. Frontends "get" the value, and
126                  * call the function directly.
127                  */
128                 ret = GP_OK;
129         } else if (reg_p->reg_len == 4) {
130                 int rval;
131                 ret = sierra_get_int_register (camera, reg_p->reg_number,
132                                                &rval,
133                                                context);
134                 reg_p->reg_value = rval;
135         } else if (reg_p->reg_len == 8) {
136                 /*
137                  * reg_value is 8 bytes maximum. If you need a bigger
138                  * value, change the reg_value size, or allocate space on
139                  * the fly and make a union with reg_value and a void*.
140                  */
141                 ret = sierra_get_string_register (camera, reg_p->reg_number, 
142                                           -1, NULL, buff, &value, context);
143                 if ((ret == GP_OK) && value != reg_p->reg_len) {
144                         GP_DEBUG ("Bad length result %d", value);
145                         return (GP_ERROR);
146                 }
147                 memcpy (&reg_p->reg_value, buff, reg_p->reg_len);
148         } else {
149                 GP_DEBUG ("Bad register length %d", reg_p->reg_number);
150                 return (GP_ERROR);
151         }
152         GP_DEBUG ("... '%s'.", gp_result_as_string (ret));
153         if (ret < 0) {
154                 return (ret);
155         }
156
157         for (ind = 0; ind < reg_p->reg_desc_cnt; ind++) {
158                 reg_desc_p = &reg_p->reg_desc[ind];
159                 mask = reg_desc_p->regs_mask;
160                 GP_DEBUG ("window name is %s", reg_desc_p->regs_long_name);
161                 gp_widget_new (reg_desc_p->reg_widget_type, 
162                                _(reg_desc_p->regs_long_name), &child);
163                 gp_widget_set_name (child, reg_desc_p->regs_short_name);
164                 /*
165                  * Setting the info for the preference settings does not
166                  * make sense like it does for an icon button. This is
167                  * used as the tool-tip field (mouse over hint that pops
168                  * up after a second in gtkam).  We don't want this used
169                  * at all; setting it to space doesn't work well, so just
170                  * set it to the same as regs_long_name.
171                  */
172                 gp_widget_set_info (child,  _(reg_desc_p->regs_long_name));
173                 GP_DEBUG ("reg_value 0x%016llx", reg_p->reg_value);
174                 for (vind = 0; vind < reg_desc_p->reg_val_name_cnt; vind++) {
175                         camera_cam_desc_get_value (&reg_desc_p->regs_value_names[vind],
176                                 reg_desc_p->reg_widget_type, reg_p->reg_len,
177                                 (char*) &reg_p->reg_value, mask, child);
178                 }
179                 /*
180                  * For radio and menu values: if there has been no change, it
181                  * means the value was not set, and so it is unknown.
182                  */
183                 if (((reg_desc_p->reg_widget_type == GP_WIDGET_RADIO) || 
184                      (reg_desc_p->reg_widget_type == GP_WIDGET_MENU)) && 
185                       !gp_widget_changed (child)) {
186                         sprintf (buff, _("%lld (unknown)"), reg_p->reg_value);
187                         gp_widget_add_choice (child, buff);
188                         gp_widget_set_value (child, buff);
189                 }
190                 gp_widget_append (section, child);
191         }
192         return (GP_OK);
193 }
194
195 int
196 camera_get_config_cam_desc (Camera *camera, CameraWidget **window,
197                             GPContext *context)
198 {
199         CameraWidget *section;
200         int indw, indr;
201         const CameraDescType *cam_desc = NULL;
202
203         GP_DEBUG ("*** camera_get_config_cam_desc");
204         CHECK (camera_start (camera, context));
205         gp_widget_new (GP_WIDGET_WINDOW, _("Camera Configuration"), window);
206
207         cam_desc = camera->pl->cam_desc;
208         for (indw = 0; indw < 2 /* XXX sizeof () */; indw++) {
209                 GP_DEBUG ("%s registers", cam_desc->regset[indw].window_name);
210                 gp_widget_new (GP_WIDGET_SECTION,
211                                _(cam_desc->regset[indw].window_name), &section);
212                 gp_widget_append (*window, section);
213                 for (indr = 0; indr < cam_desc->regset[indw].reg_cnt;  indr++) {
214                         camera_cam_desc_get_widget (camera,
215                               &cam_desc->regset[indw].regs[indr], section,
216                               context);
217                 }
218         }
219         return (GP_OK);
220 }
221
222 static int
223 cam_desc_set_register (Camera *camera, CameraRegisterType *reg_p,
224                        void *value, GPContext *context)
225 {
226         if (reg_p->reg_get_set.method == CAM_DESC_DEFAULT) {
227                 if (reg_p->reg_len == 4) {
228                         /* XXX endian problem or not? */
229                         CHECK_STOP (camera, sierra_set_int_register
230                                 (camera, reg_p->reg_number,
231                                 *(int*)value, context));
232                 } else if (reg_p->reg_len <= 8) {
233                         CHECK_STOP (camera, sierra_set_string_register (camera,
234                                         reg_p->reg_number, (char*) value,
235                                         reg_p->reg_len, context));
236                 } else {
237                         /*
238                          * Note that sizeof u.value is 8, so if you have a
239                          * larger value to store, somehow change u.value
240                          * size, or add a union.
241                          */
242                         GP_DEBUG ("set value BAD LENGTH %d", reg_p->reg_len);
243                         return (GP_ERROR);
244                 }
245         } else if (reg_p->reg_get_set.method == CAM_DESC_SUBACTION) {
246                 /*
247                  * Right now, the only supported sub-action is for
248                  * changing the LCD mode, the only other possible
249                  * sub-actions are for testing, calibration, and
250                  * protection mode. Just make sure the LCD mode setting
251                  * works.
252                  */
253                 CHECK_STOP (camera, sierra_sub_action (camera, 
254                         reg_p->reg_get_set.action, *(int*) value,
255                         context));
256         } else {
257                 GP_DEBUG ("Unsupported register setting action %d",
258                         reg_p->reg_get_set.method);
259                 return (GP_ERROR);
260         }
261         return (GP_OK);
262 }
263
264 static int 
265 camera_cam_desc_set_value (Camera *camera, CameraRegisterType *reg_p,
266                            RegisterDescriptorType *reg_desc_p,
267                            ValueNameType *val_name_p, void *data,
268                            GPContext *context)
269 {
270         /*
271          * Return GP_OK if match and OK, 1 if no match, or < 0 on error.
272          */
273         if ((reg_desc_p->reg_widget_type == GP_WIDGET_RADIO) || 
274             (reg_desc_p->reg_widget_type == GP_WIDGET_MENU)) {
275                 uint32_t new_value;
276
277                 GP_DEBUG ("set value comparing data '%s' with name '%s'", *(char**)data,
278                           val_name_p->name);
279                 if (strcmp (*(char**)data, val_name_p->name) != 0) {
280                         return (1);
281                 }
282                 /*
283                  * For masking, we might actually set the same register
284                  * twice - once for each change in the mask, so we have to
285                  * reset reg_value to the new value.
286                  * 
287                  * If we must to mask u.value, that is really a bug - the
288                  * u.value should already be masked.
289                  *
290                  * For registers longer than 4 bytes, we are masking
291                  * in whatever values were already in the upper 4 bytes -
292                  * none of the current settings (new values) are longer
293                  * than 4 bytes.
294                  */
295                 new_value = (reg_p->reg_value & ~reg_desc_p->regs_mask) |
296                         (val_name_p->u.value & reg_desc_p->regs_mask);
297                 reg_p->reg_value = new_value;
298                 GP_DEBUG ("set new val 0x%x; reg val 0x%x; msk 0x%x; val 0x%x ",
299                           new_value, (int)reg_p->reg_value,
300                           reg_desc_p->regs_mask, (int)val_name_p->u.value);
301                 CHECK_STOP (camera, cam_desc_set_register (camera, reg_p,
302                                 &new_value, context));
303         } else if (reg_desc_p->reg_widget_type == GP_WIDGET_DATE) {
304                 GP_DEBUG ("set new date/time %s", ctime((time_t*)data));
305                 CHECK_STOP (camera, cam_desc_set_register (camera, reg_p,
306                                 (int*)data, context));
307         } else if (reg_desc_p->reg_widget_type == GP_WIDGET_RANGE) {
308                 int val[2];
309                 float increment;
310
311                 if (reg_p->reg_get_set.method != CAM_DESC_DEFAULT) {
312                         GP_DEBUG ("Setting range values using the non-default"
313                                   " register functions is not supported");
314                         return (GP_ERROR);
315                 }
316                 /*
317                  * The value in *data is a float, convert it to an int.
318                  *
319                  * Currently no need to support any subaction here.
320                  *
321                  * Similiar to the masking above, if we have a register
322                  * larger than 4 bytes, put the four bytes in the int to
323                  * into the low four bytes of the value we want to set;
324                  * fill the rest with whatever was read from the camera.
325                  */
326                 increment = val_name_p->u.range[2];
327                 if (increment == 0.0) {
328                         increment = 1.0; /* default value */
329                 }
330                 GP_DEBUG ("set value range from %g inc %g", *(float*)data,
331                           increment);
332                 val[0] = round ((*(float*) data) / increment);
333                 if (reg_p->reg_len == 4) {
334                         /* 
335                          * not used but set it anyway 
336                          */
337                         val[1] = 0;
338                 } else if (reg_p->reg_len == 8) {
339                         memcpy(&val[1], ((char*)&reg_p->reg_value)+sizeof(val[0]), sizeof(val[0]));
340                         /* val[1] = ((int *) &reg_p->reg_value)[1]; */
341                 } else if (reg_p->reg_len != 4 ) {
342                         GP_DEBUG ("Unsupported range with register length %d",
343                                   reg_p->reg_len);
344                         return (GP_ERROR);
345                 }
346                 GP_DEBUG ("set value range to %d (0x%x and 0x%x)", val[0],
347                           val[0], val[1]);
348                 CHECK_STOP (camera, cam_desc_set_register (camera, reg_p, 
349                                                            &val, context));
350         } else {
351                 GP_DEBUG ("bad reg_widget_type type %d", 
352                         reg_desc_p->reg_widget_type);
353                 return (GP_ERROR);
354         }
355         return (GP_OK);
356 }
357
358 static int
359 camera_cam_desc_set_widget (Camera *camera, CameraRegisterType *reg_p,
360                             CameraWidget *window, GPContext *context)
361 {
362         int ind, vind, ret;
363         int mask;
364         union value_in {
365                 char *charp;
366                 int val;
367                 float flt;
368         } value_in;
369         CameraWidget *child;
370         RegisterDescriptorType *reg_desc_p;
371
372         GP_DEBUG ("register %d", reg_p->reg_number);
373
374         for (ind = 0; ind < reg_p->reg_desc_cnt; ind++) {
375                 reg_desc_p = &reg_p->reg_desc[ind];
376                 mask = reg_desc_p->regs_mask;
377                 GP_DEBUG ("window name is %s", reg_desc_p->regs_long_name);
378
379                 if ((gp_widget_get_child_by_label (window,
380                      _(reg_desc_p->regs_long_name), &child) >= 0) &&
381                      gp_widget_changed (child)) {
382                         gp_widget_get_value (child, &value_in);
383                         for (vind = 0; vind < reg_desc_p->reg_val_name_cnt;
384                              vind++) {
385                                 ret = camera_cam_desc_set_value (camera, reg_p,
386                                         reg_desc_p,
387                                         &reg_desc_p->regs_value_names[vind],
388                                         &value_in, context);
389                                 if (ret == GP_OK) {
390                                         /*
391                                          * Something got set, mark the
392                                          * widget as changed, so the user
393                                          * can repeat any actions  - like
394                                          * going to the "next" picture by
395                                          * repeatedly hitting apply while
396                                          * in operation play mode.
397                                          *
398                                          * This has the side affect of
399                                          * changing whatever was just set
400                                          * twice when using the apply in
401                                          * gtkam - once when applied and
402                                          * once when OK.
403                                          */
404                                         gp_widget_set_changed (child, 1);
405
406                                 }
407                                 if (ret <= 0) {
408                                         /*
409                                          * Value was set (GP_OK is 0), or
410                                          * some an error occurred (< 0),
411                                          * don't bother checking any other
412                                          * value/name pairs.
413                                          */
414                                         break;
415                                 }
416                         }
417                 }
418         }
419         return (GP_OK);
420 }
421
422 int 
423 camera_set_config_cam_desc (Camera *camera, CameraWidget *window,
424                             GPContext *context)
425 {
426         int wind, rind;
427         const CameraDescType *cam_desc = NULL;
428
429         GP_DEBUG ("*** camera_set_config_cam_desc");
430         CHECK (camera_start (camera, context));
431
432         cam_desc = camera->pl->cam_desc;
433         for (wind = 0; wind < 2 /* XXX sizeof () */; wind++) {
434                 GP_DEBUG ("%s registers", cam_desc->regset[wind].window_name);
435                 for (rind = 0; rind < cam_desc->regset[wind].reg_cnt;  rind++) {
436                         camera_cam_desc_set_widget (camera,
437                               &cam_desc->regset[wind].regs[rind], window,
438                               context);
439                 }
440         }
441         return (GP_OK);
442 }