"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/camlibs/ptp2/config.c" (21 Feb 2021, 394482 Bytes) of package /linux/privat/libgphoto2-2.5.27.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "config.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.5.26_vs_2.5.27.

    1 /* config.c
    2  *
    3  * Copyright (C) 2003-2021 Marcus Meissner <marcus@jet.franken.de>
    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 #define _DEFAULT_SOURCE
   21 #include "config.h"
   22 
   23 #include <math.h>
   24 #include <stdlib.h>
   25 #include <string.h>
   26 #include <stdio.h>
   27 #include <time.h>
   28 #ifdef WIN32
   29 # include <winsock.h>
   30 #else
   31 # include <sys/socket.h>
   32 # include <netinet/in.h>
   33 # include <arpa/inet.h>
   34 #endif
   35 #include <sys/types.h>
   36 
   37 #include <gphoto2/gphoto2-library.h>
   38 #include <gphoto2/gphoto2-port-log.h>
   39 #include <gphoto2/gphoto2-setting.h>
   40 
   41 #ifdef ENABLE_NLS
   42 #  include <libintl.h>
   43 #  undef _
   44 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
   45 #  ifdef gettext_noop
   46 #    define N_(String) gettext_noop (String)
   47 #  else
   48 #    define N_(String) (String)
   49 #  endif
   50 #else
   51 #  define textdomain(String) (String)
   52 #  define gettext(String) (String)
   53 #  define dgettext(Domain,Message) (Message)
   54 #  define dcgettext(Domain,Message,Type) (Message)
   55 #  define bindtextdomain(Domain,Directory) (Domain)
   56 #  define _(String) (String)
   57 #  define N_(String) (String)
   58 #endif
   59 
   60 #include "ptp.h"
   61 #include "ptp-bugs.h"
   62 #include "ptp-private.h"
   63 #include "ptp-pack.c"
   64 
   65 #ifdef __GNUC__
   66 # define __unused__ __attribute__((unused))
   67 #else
   68 # define __unused__
   69 #endif
   70 
   71 #define SET_CONTEXT(camera, ctx) ((PTPData *) camera->pl->params.data)->context = ctx
   72 
   73 int
   74 have_prop(Camera *camera, uint16_t vendor, uint16_t prop) {
   75     unsigned int i;
   76 
   77     /* prop 0 matches */
   78     if (!prop && (camera->pl->params.deviceinfo.VendorExtensionID==vendor))
   79         return 1;
   80 
   81     if (    ((prop & 0x7000) == 0x5000) ||
   82         (NIKON_1(&camera->pl->params) && ((prop & 0xf000) == 0xf000))
   83     ) { /* properties */
   84         for (i=0; i<camera->pl->params.deviceinfo.DevicePropertiesSupported_len; i++) {
   85             if (prop != camera->pl->params.deviceinfo.DevicePropertiesSupported[i])
   86                 continue;
   87             if ((prop & 0xf000) == 0x5000) { /* generic property */
   88                 if (!vendor || (camera->pl->params.deviceinfo.VendorExtensionID==vendor))
   89                     return 1;
   90             }
   91             if (camera->pl->params.deviceinfo.VendorExtensionID==vendor)
   92                 return 1;
   93         }
   94     }
   95     if ((prop & 0x7000) == 0x1000) { /* commands */
   96         for (i=0; i<camera->pl->params.deviceinfo.OperationsSupported_len; i++) {
   97 
   98             if (prop != camera->pl->params.deviceinfo.OperationsSupported[i])
   99                 continue;
  100             if ((prop & 0xf000) == 0x1000) /* generic property */
  101                 return 1;
  102             if (camera->pl->params.deviceinfo.VendorExtensionID==vendor)
  103                 return 1;
  104         }
  105     }
  106     return 0;
  107 }
  108 
  109 static int
  110 camera_prepare_chdk_capture(Camera *camera, GPContext *context) {
  111     PTPParams       *params = &camera->pl->params;
  112     int             scriptid = 0, major = 0,minor = 0;
  113     unsigned int        status;
  114     int         luastatus;
  115     ptp_chdk_script_msg *msg = NULL;
  116     char *lua       =
  117 PTP_CHDK_LUA_SERIALIZE
  118 "if not get_mode() then\n\
  119         switch_mode_usb(1)\n\
  120         local i=0\n\
  121         while not get_mode() and i < 300 do\n\
  122                 sleep(10)\n\
  123                 i=i+1\n\
  124         end\n\
  125         if not get_mode() then\n\
  126                 return false, 'switch failed'\n\
  127         end\n\
  128         return true\n\
  129 end\n\
  130 return false,'already in rec'\n\
  131 ";
  132     C_PTP (ptp_chdk_get_version (params, &major, &minor));
  133     GP_LOG_D ("CHDK %d.%d", major, minor);
  134 
  135     GP_LOG_D ("calling lua script %s", lua);
  136     C_PTP (ptp_chdk_exec_lua(params, lua, 0, &scriptid, &luastatus));
  137     GP_LOG_D ("called script. script id %d, status %d", scriptid, luastatus);
  138 
  139     while (1) {
  140         C_PTP (ptp_chdk_get_script_status(params, &status));
  141         GP_LOG_D ("script status %x", status);
  142 
  143         if (status & PTP_CHDK_SCRIPT_STATUS_MSG) {
  144             C_PTP (ptp_chdk_read_script_msg(params, &msg));
  145             GP_LOG_D ("message script id %d, type %d, subtype %d", msg->script_id, msg->type, msg->subtype);
  146             GP_LOG_D ("message script %s", msg->data);
  147             free (msg);
  148         }
  149 
  150         if (!(status & PTP_CHDK_SCRIPT_STATUS_RUN))
  151             break;
  152         usleep(100000);
  153     }
  154     return GP_OK;
  155 }
  156 
  157 static int
  158 camera_unprepare_chdk_capture(Camera *camera, GPContext *context) {
  159     PTPParams       *params = &camera->pl->params;
  160     int             scriptid = 0, status = 0;
  161     ptp_chdk_script_msg *msg = NULL;
  162     char *lua       =
  163 PTP_CHDK_LUA_SERIALIZE
  164 "if get_mode() then\n\
  165         switch_mode_usb(0)\n\
  166         local i=0\n\
  167         while get_mode() and i < 300 do\n\
  168                 sleep(10)\n\
  169                 i=i+1\n\
  170         end\n\
  171         if get_mode() then\n\
  172                 return false, 'switch failed'\n\
  173         end\n\
  174         return true\n\
  175 end\n\
  176 return false,'already in play'\n\
  177 ";
  178     GP_LOG_D ("calling lua script %s", lua);
  179     C_PTP (ptp_chdk_exec_lua(params, lua, 0, &scriptid, &status));
  180     C_PTP (ptp_chdk_read_script_msg(params, &msg));
  181 
  182     GP_LOG_D ("called script. script id %d, status %d", scriptid, status);
  183     GP_LOG_D ("message script id %d, type %d, subtype %d", msg->script_id, msg->type, msg->subtype);
  184     GP_LOG_D ("message script %s", msg->data);
  185     free (msg);
  186     if (!status) {
  187         gp_context_error(context,_("CHDK did not leave recording mode."));
  188         return GP_ERROR;
  189     }
  190     return GP_OK;
  191 }
  192 
  193 static int
  194 camera_prepare_canon_powershot_capture(Camera *camera, GPContext *context) {
  195     uint16_t        ret;
  196     PTPContainer        event;
  197     PTPPropertyValue    propval;
  198     PTPParams       *params = &camera->pl->params;
  199     int             found, oldtimeout;
  200 
  201         if (ptp_property_issupported(params, PTP_DPC_CANON_FlashMode)) {
  202         GP_LOG_D ("Canon capture mode is already set up.");
  203         C_PTP (ptp_getdevicepropvalue(params, PTP_DPC_CANON_EventEmulateMode, &propval, PTP_DTC_UINT16));
  204         GP_LOG_D ("Event emulate mode 0x%04x", propval.u16);
  205         params->canon_event_mode = propval.u16;
  206         return GP_OK;
  207     }
  208 
  209     propval.u16 = 0;
  210     C_PTP (ptp_getdevicepropvalue(params, PTP_DPC_CANON_EventEmulateMode, &propval, PTP_DTC_UINT16));
  211     GP_LOG_D ("prop 0xd045 value is 0x%04x",propval.u16);
  212 
  213     propval.u16=1;
  214     C_PTP (ptp_setdevicepropvalue(params, PTP_DPC_CANON_EventEmulateMode, &propval, PTP_DTC_UINT16));
  215     params->canon_event_mode = propval.u16;
  216     C_PTP (ptp_getdevicepropvalue(params, PTP_DPC_CANON_SizeOfOutputDataFromCamera, &propval, PTP_DTC_UINT32));
  217     GP_LOG_D ("prop PTP_DPC_CANON_SizeOfOutputDataFromCamera value is %d",propval.u32);
  218     C_PTP (ptp_getdevicepropvalue(params, PTP_DPC_CANON_SizeOfInputDataToCamera, &propval, PTP_DTC_UINT32));
  219     GP_LOG_D ("prop PTP_DPC_CANON_SizeOfInputDataToCamera value is %d",propval.u32);
  220 
  221     C_PTP (ptp_getdeviceinfo (params, &params->deviceinfo));
  222     C_PTP (ptp_getdeviceinfo (params, &params->deviceinfo));
  223     CR (fixup_cached_deviceinfo (camera, &params->deviceinfo));
  224 
  225     C_PTP (ptp_getdevicepropvalue(params, PTP_DPC_CANON_SizeOfOutputDataFromCamera, &propval, PTP_DTC_UINT32));
  226     GP_LOG_D ("prop PTP_DPC_CANON_SizeOfOutputDataFromCamera value is %d",propval.u32);
  227     C_PTP (ptp_getdevicepropvalue(params, PTP_DPC_CANON_SizeOfInputDataToCamera, &propval, PTP_DTC_UINT32));
  228     GP_LOG_D ("prop PTP_DPC_CANON_SizeOfInputDataToCamera value is %d",propval.u32);
  229     C_PTP (ptp_getdeviceinfo (params, &params->deviceinfo));
  230     CR (fixup_cached_deviceinfo (camera, &params->deviceinfo));
  231     C_PTP (ptp_getdevicepropvalue(params, PTP_DPC_CANON_EventEmulateMode, &propval, PTP_DTC_UINT16));
  232     params->canon_event_mode = propval.u16;
  233     GP_LOG_D ("prop 0xd045 value is 0x%04x",propval.u16);
  234 
  235     GP_LOG_D ("Magic code ends.");
  236 
  237     GP_LOG_D ("Setting prop. EventEmulateMode to 7.");
  238 /* interrupt  9013 get event
  239  1     Yes      No
  240  2     Yes      No
  241  3     Yes      Yes
  242  4     Yes      Yes
  243  5     Yes      Yes
  244  6     No       No
  245  7     No       Yes
  246  */
  247     propval.u16 = 7;
  248     C_PTP (ptp_setdevicepropvalue(params, PTP_DPC_CANON_EventEmulateMode, &propval, PTP_DTC_UINT16));
  249     params->canon_event_mode = propval.u16;
  250 
  251     ret = ptp_canon_startshootingmode (params);
  252     if (ret == PTP_RC_CANON_A009) {
  253         /* I think this means ... already in capture mode */
  254         return GP_OK;
  255     }
  256     if (ret != PTP_RC_OK) {
  257         GP_LOG_E ("'ptp_canon_startshootingmode (params)' failed: 0x%04x", ret);
  258         C_PTP_REP (ret);
  259     }
  260     gp_port_get_timeout (camera->port, &oldtimeout);
  261     gp_port_set_timeout (camera->port, 1000);
  262 
  263     /* Catch the event telling us the mode was switched ... */
  264     /* If we were prepared already, it will be 5*50*1000 wait, so 1/4 second ... hmm */
  265     found = 0;
  266     while (found++<10) {
  267         ret = ptp_check_event (params);
  268         if (ret != PTP_RC_OK)
  269             break;
  270 
  271         while (ptp_get_one_event (params, &event)) {
  272             GP_LOG_D ("Event: 0x%x", event.Code);
  273             if ((event.Code==0xc00c) ||
  274                 (event.Code==PTP_EC_StorageInfoChanged)) {
  275                 GP_LOG_D ("Event: Entered shooting mode.");
  276                 found = 1;
  277                 break;
  278             }
  279         }
  280         usleep(50*1000);
  281     }
  282 
  283 #if 0
  284     gp_port_set_timeout (camera->port, oldtimeout);
  285     if (ptp_operation_issupported(params, PTP_OC_CANON_ViewfinderOn)) {
  286         ret = ptp_canon_viewfinderon (params);
  287         if (ret != PTP_RC_OK)
  288             GP_LOG_E ("Canon enable viewfinder failed: %d", ret);
  289         /* ignore errors here */
  290     }
  291     gp_port_set_timeout (camera->port, 1000);
  292 #endif
  293 
  294     /* Reget device info, they change on the Canons. */
  295     C_PTP (ptp_getdeviceinfo(&camera->pl->params, &camera->pl->params.deviceinfo));
  296     CR (fixup_cached_deviceinfo (camera, &camera->pl->params.deviceinfo));
  297     gp_port_set_timeout (camera->port, oldtimeout);
  298     return GP_OK;
  299 }
  300 
  301 int
  302 camera_canon_eos_update_capture_target(Camera *camera, GPContext *context, int value) {
  303     PTPParams       *params = &camera->pl->params;
  304     char            buf[200];
  305     PTPPropertyValue    ct_val;
  306     PTPDevicePropDesc   dpd;
  307     int         cardval = -1;
  308 
  309     memset(&dpd,0,sizeof(dpd));
  310     if (!have_eos_prop(params, PTP_VENDOR_CANON, PTP_DPC_CANON_EOS_CaptureDestination) ) {
  311         GP_LOG_D ("No CaptureDestination property?");
  312         return GP_OK;
  313     }
  314     C_PTP (ptp_canon_eos_getdevicepropdesc (params,PTP_DPC_CANON_EOS_CaptureDestination, &dpd));
  315 
  316     /* Look for the correct value of the card mode */
  317     if (value != PTP_CANON_EOS_CAPTUREDEST_HD) {
  318         if (dpd.FormFlag == PTP_DPFF_Enumeration) {
  319             unsigned int    i;
  320             for (i=0;i<dpd.FORM.Enum.NumberOfValues;i++) {
  321                 if (dpd.FORM.Enum.SupportedValue[i].u32 != PTP_CANON_EOS_CAPTUREDEST_HD) {
  322                     cardval = dpd.FORM.Enum.SupportedValue[i].u32;
  323                     break;
  324                 }
  325             }
  326             GP_LOG_D ("Card value is %d",cardval);
  327         }
  328         if (cardval == -1) {
  329             /* https://github.com/gphoto/gphoto2/issues/383 ... we dont get an enum, but the value is 2 ... */
  330             if (dpd.CurrentValue.u32 != PTP_CANON_EOS_CAPTUREDEST_HD) {
  331                 cardval = dpd.CurrentValue.u32;
  332             } else {
  333                 GP_LOG_D ("NO Card found - falling back to SDRAM!");
  334                 cardval = PTP_CANON_EOS_CAPTUREDEST_HD;
  335             }
  336         }
  337     }
  338 
  339     if (value == 1)
  340         value = cardval;
  341 
  342     /* -1 == use setting from config-file, 1 == card, 4 == ram*/
  343     ct_val.u32 = (value == -1)
  344              ? (GP_OK == gp_setting_get("ptp2","capturetarget",buf)) && strcmp(buf,"sdram") ? cardval : PTP_CANON_EOS_CAPTUREDEST_HD
  345              : value;
  346 
  347     /* otherwise we get DeviceBusy for some reason */
  348     if (ct_val.u32 != dpd.CurrentValue.u32) {
  349         C_PTP_MSG (ptp_canon_eos_setdevicepropvalue (params, PTP_DPC_CANON_EOS_CaptureDestination, &ct_val, PTP_DTC_UINT32),
  350                "setdevicepropvalue of capturetarget to 0x%x failed", ct_val.u32);
  351         if (ct_val.u32 == PTP_CANON_EOS_CAPTUREDEST_HD) {
  352             uint16_t    ret;
  353 
  354             /* if we want to download the image from the device, we need to tell the camera
  355              * that we have enough space left. */
  356             /* this might be a trigger value for "no space" -Marcus
  357             ret = ptp_canon_eos_pchddcapacity(params, 0x7fffffff, 0x00001000, 0x00000001);
  358              */
  359 
  360             LOG_ON_PTP_E (ptp_canon_eos_setuilock (params));
  361             ret = ptp_canon_eos_pchddcapacity(params, 0x0fffffff, 0x00001000, 0x00000001);
  362             LOG_ON_PTP_E (ptp_canon_eos_resetuilock (params));
  363             /* not so bad if its just busy, would also fail later. */
  364             if (ret == PTP_RC_DeviceBusy) ret = PTP_RC_OK;
  365             C_PTP (ret);
  366             /* Tricky ... eos1200d seems to take a while to register this change and the first capture
  367              * when it is still switching might be going down the drain. */
  368             while (1) {
  369                 C_PTP (ptp_check_eos_events (params));
  370                 C_PTP (ptp_canon_eos_getdevicepropdesc (params,PTP_DPC_CANON_EOS_AvailableShots, &dpd));
  371                 if (dpd.CurrentValue.u32 > 0)
  372                     break;
  373             }
  374         }
  375     } else {
  376         GP_LOG_D ("optimized ... setdevicepropvalue of capturetarget to 0x%x not done as it was set already.", ct_val.u32 );
  377     }
  378     ptp_free_devicepropdesc (&dpd);
  379     return GP_OK;
  380 }
  381 
  382 static int
  383 camera_prepare_canon_eos_capture(Camera *camera, GPContext *context) {
  384     PTPParams   *params = &camera->pl->params;
  385     PTPStorageIDs   sids;
  386     int     tries;
  387 
  388     GP_LOG_D ("preparing EOS capture...");
  389 
  390     if (is_canon_eos_m(params)) {
  391         int mode = 0x15;    /* default for EOS M and newer Powershot SX */
  392 
  393         if (!strcmp(params->deviceinfo.Model,"Canon PowerShot SX540 HS")) mode = 0x11;  /* testing for https://github.com/gphoto/libgphoto2/issues/360 */
  394         if (!strcmp(params->deviceinfo.Model,"Canon PowerShot SX600 HS")) goto skip;
  395 
  396         if (!strcmp(params->deviceinfo.Model,"Canon PowerShot G5 X")) mode = 0x11;
  397         if (!strcmp(params->deviceinfo.Model,"Canon EOS M6 Mark II")) mode = 0x1;
  398         C_PTP (ptp_canon_eos_setremotemode(params, mode));
  399     } else {
  400         C_PTP (ptp_canon_eos_setremotemode(params, 1));
  401     }
  402 skip:
  403     C_PTP (ptp_canon_eos_seteventmode(params, 1));
  404     params->eos_camerastatus = -1;  /* aka unknown */
  405 
  406     if (ptp_operation_issupported(params, PTP_OC_CANON_EOS_SetRequestOLCInfoGroup))
  407         C_PTP (ptp_canon_eos_setrequestolcinfogroup(params, 0x00001fff));
  408 
  409     /* Get the initial bulk set of event data */
  410     C_PTP (ptp_check_eos_events (params));
  411 
  412     if (ptp_operation_issupported(params, PTP_OC_CANON_EOS_RequestDevicePropValue)) {
  413         /* request additional properties */
  414         /* if one of this is not present GeneralError will be returned, so only check
  415          * and log, but do not error return */
  416         LOG_ON_PTP_E (ptp_canon_eos_requestdevicepropvalue (params, PTP_DPC_CANON_EOS_Owner));
  417         LOG_ON_PTP_E (ptp_canon_eos_requestdevicepropvalue (params, PTP_DPC_CANON_EOS_Artist));
  418         LOG_ON_PTP_E (ptp_canon_eos_requestdevicepropvalue (params, PTP_DPC_CANON_EOS_Copyright));
  419         LOG_ON_PTP_E (ptp_canon_eos_requestdevicepropvalue (params, PTP_DPC_CANON_EOS_SerialNumber));
  420 
  421 /*      LOG_ON_PTP_E (ptp_canon_eos_requestdevicepropvalue (params, PTP_DPC_CANON_EOS_DPOFVersion)); */
  422 /*      LOG_ON_PTP_E (ptp_canon_eos_requestdevicepropvalue (params, PTP_DPC_CANON_EOS_MyMenuList)); */
  423 /*      LOG_ON_PTP_E (ptp_canon_eos_requestdevicepropvalue (params, PTP_DPC_CANON_EOS_LensAdjustParams)); */
  424     }
  425     if (ptp_operation_issupported(params, PTP_OC_CANON_EOS_GetDeviceInfoEx)) {
  426         PTPCanonEOSDeviceInfo x;
  427         unsigned int i;
  428 
  429         C_PTP (ptp_canon_eos_getdeviceinfo (params, &x));
  430         for (i=0;i<x.EventsSupported_len;i++)
  431             GP_LOG_D ("event: %04x", x.EventsSupported[i]);
  432         for (i=0;i<x.DevicePropertiesSupported_len;i++)
  433             GP_LOG_D ("deviceprop: %04x", x.DevicePropertiesSupported[i]);
  434         for (i=0;i<x.unk_len;i++)
  435             GP_LOG_D ("unk: %04x", x.unk[i]);
  436         ptp_free_EOS_DI (&x);
  437     }
  438 
  439     /* The new EOS occasionally returned an empty event set ... likely because we are too fast. try again some times. */
  440     C_PTP (ptp_check_eos_events (params));
  441     tries = 10;
  442     while (--tries && !have_eos_prop(params,PTP_VENDOR_CANON,PTP_DPC_CANON_EOS_EVFOutputDevice)) {
  443         GP_LOG_D("evfoutput device not found, retrying");
  444         usleep(50*1000);
  445         C_PTP (ptp_check_eos_events (params));
  446     }
  447 
  448     CR (camera_canon_eos_update_capture_target( camera, context, -1 ));
  449 
  450     ptp_free_DI (&params->deviceinfo);
  451     C_PTP (ptp_getdeviceinfo(params, &params->deviceinfo));
  452     CR (fixup_cached_deviceinfo (camera, &params->deviceinfo));
  453     C_PTP (ptp_canon_eos_getstorageids(params, &sids));
  454     if (sids.n >= 1) {
  455         unsigned char *sdata;
  456         unsigned int slen;
  457         C_PTP (ptp_canon_eos_getstorageinfo(params, sids.Storage[0], &sdata, &slen ));
  458         free (sdata);
  459     }
  460     free (sids.Storage);
  461 
  462     /* FIXME: 9114 call missing here! */
  463 
  464     /* Get the second bulk set of 0x9116 property data */
  465     C_PTP (ptp_check_eos_events (params));
  466     params->eos_captureenabled = 1;
  467 
  468     /* run this only on EOS M, not on PowerShot SX */
  469     /* I lost track where it is needed.
  470      * Need it:
  471      * + EOS M10
  472      * + PowerShot SX 720HS
  473      * + PowerShot G9x mark II
  474      *
  475      * NOT NEEDED for EOS M6 Mark II ... this behaves like a regular EOS no-M and will disable tethering if we set output=8.
  476      */
  477     if (    is_canon_eos_m (params) &&
  478         (strcmp(params->deviceinfo.Model,"Canon EOS M6 Mark II") != 0)
  479     ) {
  480         /* This code is needed on EOS m3 at least. might not be needed on others ... mess :/ */
  481         PTPPropertyValue    ct_val;
  482 
  483         GP_LOG_D ("EOS M detected");
  484 
  485         C_PTP (ptp_canon_eos_seteventmode(params, 2));
  486         ct_val.u16 = 0x0008;
  487         C_PTP (ptp_canon_eos_setdevicepropvalue (params, PTP_DPC_CANON_EOS_EVFOutputDevice, &ct_val, PTP_DTC_UINT16));
  488 
  489 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  490         usleep(1000*1000); /* 1 second */
  491 #endif
  492 
  493         C_PTP (ptp_check_eos_events (params));
  494     }
  495     return GP_OK;
  496 }
  497 
  498 int
  499 camera_prepare_capture (Camera *camera, GPContext *context)
  500 {
  501     PTPParams       *params = &camera->pl->params;
  502 
  503     GP_LOG_D ("prepare_capture");
  504     switch (params->deviceinfo.VendorExtensionID) {
  505     case PTP_VENDOR_FUJI:
  506         {
  507             PTPPropertyValue propval;
  508 
  509             /* without the firmware update ... not an error... */
  510             if (!have_prop (camera, PTP_VENDOR_FUJI, 0xd207))
  511                 return GP_OK;
  512 
  513             /* timelapse does:
  514              * d38c -> 1    (PC Mode)
  515              * d207 -> 2    (USB control)
  516              */
  517 
  518             propval.u16 = 0x0001;
  519             LOG_ON_PTP_E (ptp_setdevicepropvalue (params, 0xd38c, &propval, PTP_DTC_UINT16));
  520             propval.u16 = 0x0002;
  521             LOG_ON_PTP_E (ptp_setdevicepropvalue (params, 0xd207, &propval, PTP_DTC_UINT16));
  522             return GP_OK;
  523         }
  524         break;
  525     case PTP_VENDOR_CANON:
  526         if (ptp_operation_issupported(params, PTP_OC_CANON_InitiateReleaseControl))
  527             return camera_prepare_canon_powershot_capture(camera,context);
  528 
  529         if (ptp_operation_issupported(params, PTP_OC_CHDK))
  530             return camera_prepare_chdk_capture(camera,context);
  531 
  532         if (ptp_operation_issupported(params, PTP_OC_CANON_EOS_RemoteRelease) ||
  533             ptp_operation_issupported(params, PTP_OC_CANON_EOS_RemoteReleaseOn)
  534         )
  535             return camera_prepare_canon_eos_capture(camera,context);
  536         gp_context_error(context, _("Sorry, your Canon camera does not support Canon capture"));
  537         return GP_ERROR_NOT_SUPPORTED;
  538     case PTP_VENDOR_PANASONIC: {
  539         char buf[1024];
  540         if ((GP_OK != gp_setting_get("ptp2","capturetarget",buf)) || !strcmp(buf,"sdram"))
  541             C_PTP (ptp_panasonic_setcapturetarget(params, 1));
  542         else
  543             C_PTP (ptp_panasonic_setcapturetarget(params, 0));
  544         break;
  545     }
  546     default:
  547         /* generic capture does not need preparation */
  548         return GP_OK;
  549     }
  550     return GP_OK;
  551 }
  552 
  553 static int
  554 camera_unprepare_canon_powershot_capture(Camera *camera, GPContext *context) {
  555     PTPParams       *params = &camera->pl->params;
  556 
  557     C_PTP (ptp_canon_endshootingmode (params));
  558 
  559     if (ptp_operation_issupported(params, PTP_OC_CANON_ViewfinderOff)) {
  560         if (params->canon_viewfinder_on) {
  561             params->canon_viewfinder_on = 0;
  562             LOG_ON_PTP_E (ptp_canon_viewfinderoff (params));
  563             /* ignore errors here */
  564         }
  565     }
  566     /* Reget device info, they change on the Canons. */
  567     C_PTP (ptp_getdeviceinfo(params, &params->deviceinfo));
  568     CR (fixup_cached_deviceinfo (camera, &params->deviceinfo));
  569     return GP_OK;
  570 }
  571 
  572 static int
  573 camera_unprepare_canon_eos_capture(Camera *camera, GPContext *context) {
  574     PTPParams       *params = &camera->pl->params;
  575 
  576     /* just in case we had autofocus running */
  577     if (ptp_operation_issupported(params, PTP_OC_CANON_EOS_AfCancel))
  578         CR (ptp_canon_eos_afcancel(params));
  579 
  580     if (is_canon_eos_m (params)) {
  581         PTPPropertyValue    ct_val;
  582 
  583         ct_val.u16 = 0x0000;
  584         C_PTP (ptp_canon_eos_setdevicepropvalue (params, PTP_DPC_CANON_EOS_EVFOutputDevice, &ct_val, PTP_DTC_UINT16));
  585     }
  586 
  587     /* then emits 911b and 911c ... not done yet ... */
  588     CR (camera_canon_eos_update_capture_target(camera, context, 1));
  589 
  590     if (ptp_operation_issupported(&camera->pl->params, PTP_OC_CANON_EOS_ResetUILock))
  591         LOG_ON_PTP_E (ptp_canon_eos_resetuilock (params));
  592 
  593     /* Drain the rest set of the event data */
  594     C_PTP (ptp_check_eos_events (params));
  595     C_PTP (ptp_canon_eos_setremotemode(params, 0));
  596     C_PTP (ptp_canon_eos_seteventmode(params, 0));
  597     params->eos_captureenabled = 0;
  598     return GP_OK;
  599 }
  600 
  601 int
  602 camera_unprepare_capture (Camera *camera, GPContext *context)
  603 {
  604     GP_LOG_D ("Unprepare_capture");
  605     switch (camera->pl->params.deviceinfo.VendorExtensionID) {
  606     case PTP_VENDOR_CANON:
  607         if (ptp_operation_issupported(&camera->pl->params, PTP_OC_CANON_TerminateReleaseControl))
  608             return camera_unprepare_canon_powershot_capture (camera, context);
  609 
  610         if (ptp_operation_issupported(&camera->pl->params, PTP_OC_CHDK))
  611             return camera_unprepare_chdk_capture(camera,context);
  612 
  613         if (ptp_operation_issupported(&camera->pl->params, PTP_OC_CANON_EOS_RemoteRelease) ||
  614             ptp_operation_issupported(&camera->pl->params, PTP_OC_CANON_EOS_RemoteReleaseOn)
  615         )
  616             return camera_unprepare_canon_eos_capture (camera, context);
  617 
  618         gp_context_error(context,
  619         _("Sorry, your Canon camera does not support Canon capture"));
  620         return GP_ERROR_NOT_SUPPORTED;
  621     case PTP_VENDOR_FUJI:
  622         {
  623             PTPPropertyValue propval;
  624             PTPParams *params = &camera->pl->params;
  625 
  626             if (params->inliveview) {
  627                 C_PTP_REP (ptp_terminateopencapture (params, params->opencapture_transid));
  628                 params->inliveview = 0;
  629             }
  630 
  631             propval.u16 = 0x0001;
  632             C_PTP (ptp_setdevicepropvalue (params, 0xd207, &propval, PTP_DTC_UINT16));
  633             return GP_OK;
  634         }
  635         break;
  636     default:
  637         /* generic capture does not need unpreparation */
  638         return GP_OK;
  639     }
  640     return GP_OK;
  641 }
  642 
  643 static uint16_t
  644 nikon_wait_busy(PTPParams *params, int waitms, int timeout) {
  645     uint16_t    res;
  646     int     tries;
  647 
  648     /* wait either 1 second, or 50 tries */
  649     if (waitms)
  650         tries=timeout/waitms;
  651     else
  652         tries=50;
  653     do {
  654         res = ptp_nikon_device_ready(params);
  655         if (    (res != PTP_RC_DeviceBusy) &&
  656             (res != PTP_RC_NIKON_Bulb_Release_Busy)
  657         )
  658             return res;
  659         if (waitms) usleep(waitms*1000)/*wait a bit*/;
  660     } while (tries--);
  661     return res;
  662 }
  663 
  664 struct submenu;
  665 #define CONFIG_GET_ARGS Camera *camera, CameraWidget **widget, struct submenu* menu, PTPDevicePropDesc *dpd
  666 #define CONFIG_GET_NAMES camera, widget, menu, dpd
  667 typedef int (*get_func)(CONFIG_GET_ARGS);
  668 #define CONFIG_PUT_ARGS Camera *camera, CameraWidget *widget, PTPPropertyValue *propval, PTPDevicePropDesc *dpd
  669 #define CONFIG_PUT_NAMES camera, widget, propval, dpd
  670 typedef int (*put_func)(CONFIG_PUT_ARGS);
  671 
  672 struct menu;
  673 #define CONFIG_MENU_GET_ARGS Camera *camera, CameraWidget **widget, struct menu* menu
  674 typedef int (*get_menu_func)(CONFIG_MENU_GET_ARGS);
  675 #define CONFIG_MENU_PUT_ARGS Camera *camera, CameraWidget *widget
  676 typedef int (*put_menu_func)(CONFIG_MENU_PUT_ARGS);
  677 
  678 struct submenu {
  679     char        *label;
  680     char        *name;
  681     uint16_t    propid;
  682     uint16_t    vendorid;
  683     uint32_t    type;   /* for 32bit alignment */
  684     get_func    getfunc;
  685     put_func    putfunc;
  686 };
  687 
  688 struct menu {
  689     char        *label;
  690     char        *name;
  691 
  692     uint16_t    usb_vendorid;
  693     uint16_t    usb_productid;
  694 
  695     /* Either: Standard menu */
  696     struct  submenu *submenus;
  697     /* Or: Non-standard menu with custom behaviour */
  698     get_menu_func   getfunc;
  699     put_menu_func   putfunc;
  700 };
  701 
  702 /* Generic helper function for:
  703  *
  704  * ENUM xINTxx propertiess, with potential vendor specific variables. \
  705  */
  706 #define GENERIC_TABLE(bits,type,dpc) \
  707 struct deviceproptable##bits {      \
  708     char        *label;     \
  709     type        value;      \
  710     uint16_t    vendor_id;  \
  711 };\
  712 \
  713 static int \
  714 _get_Generic##bits##Table(CONFIG_GET_ARGS, struct deviceproptable##bits * tbl, int tblsize) { \
  715     int i, j; \
  716     int isset = FALSE, isset2 = FALSE; \
  717  \
  718     if (!(dpd->FormFlag & (PTP_DPFF_Enumeration|PTP_DPFF_Range))) { \
  719         GP_LOG_D ("no enumeration/range in %sbit table code... going on", #bits); \
  720     } \
  721     if (dpd->DataType != dpc) { \
  722         GP_LOG_D ("no %s prop in %sbit table code", #bits, #bits); \
  723         return GP_ERROR; \
  724     } \
  725  \
  726     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget); \
  727     gp_widget_set_name (*widget, menu->name); \
  728     if (dpd->FormFlag & PTP_DPFF_Enumeration) { \
  729         if (!dpd->FORM.Enum.NumberOfValues) { \
  730             /* fill in with all values we have in the table. */ \
  731             for (j=0;j<tblsize;j++) { \
  732                 if ((tbl[j].vendor_id == 0) || \
  733                     (tbl[j].vendor_id == camera->pl->params.deviceinfo.VendorExtensionID) \
  734                 ) { \
  735                     gp_widget_add_choice (*widget, _(tbl[j].label)); \
  736                     if (tbl[j].value == dpd->CurrentValue.bits) { \
  737                         gp_widget_set_value (*widget, _(tbl[j].label)); \
  738                         isset2 = TRUE; \
  739                     } \
  740                 } \
  741             } \
  742             /* fallthrough in case we do not have currentvalue in the table. isset2 = FALSE */ \
  743         } \
  744         for (i = 0; i<dpd->FORM.Enum.NumberOfValues; i++) { \
  745             isset = FALSE; \
  746             for (j=0;j<tblsize;j++) { \
  747                 if ((tbl[j].value == dpd->FORM.Enum.SupportedValue[i].bits) && \
  748                     ((tbl[j].vendor_id == 0) || \
  749                      (tbl[j].vendor_id == camera->pl->params.deviceinfo.VendorExtensionID)) \
  750                 ) { \
  751                     gp_widget_add_choice (*widget, _(tbl[j].label)); \
  752                     if (tbl[j].value == dpd->CurrentValue.bits) { \
  753                         isset2 = TRUE; \
  754                         gp_widget_set_value (*widget, _(tbl[j].label)); \
  755                     } \
  756                     isset = TRUE; \
  757                     break; \
  758                 } \
  759             } \
  760             if (!isset) { \
  761                 char buf[200]; \
  762                 sprintf(buf, _("Unknown value %04x"), dpd->FORM.Enum.SupportedValue[i].bits); \
  763                 gp_widget_add_choice (*widget, buf); \
  764                 if (dpd->FORM.Enum.SupportedValue[i].bits == dpd->CurrentValue.bits) { \
  765                     isset2 = TRUE; \
  766                     gp_widget_set_value (*widget, buf); \
  767                 } \
  768             } \
  769         } \
  770     } \
  771     if (dpd->FormFlag & PTP_DPFF_Range) { \
  772         type r; \
  773         for (   r = dpd->FORM.Range.MinimumValue.bits; \
  774             r<=dpd->FORM.Range.MaximumValue.bits; \
  775             r+= dpd->FORM.Range.StepSize.bits \
  776         ) { \
  777             isset = FALSE; \
  778             for (j=0;j<tblsize;j++) { \
  779                 if ((tbl[j].value == r) && \
  780                     ((tbl[j].vendor_id == 0) || \
  781                      (tbl[j].vendor_id == camera->pl->params.deviceinfo.VendorExtensionID)) \
  782                 ) { \
  783                     gp_widget_add_choice (*widget, _(tbl[j].label)); \
  784                     if (r == dpd->CurrentValue.bits) { \
  785                         isset2 = TRUE; \
  786                         gp_widget_set_value (*widget, _(tbl[j].label)); \
  787                     } \
  788                     isset = TRUE; \
  789                     break; \
  790                 } \
  791             } \
  792             if (!isset) { \
  793                 char buf[200]; \
  794                 sprintf(buf, _("Unknown value %04x"), r); \
  795                 gp_widget_add_choice (*widget, buf); \
  796                 if (r == dpd->CurrentValue.bits) { \
  797                     isset2 = TRUE; \
  798                     gp_widget_set_value (*widget, buf); \
  799                 } \
  800             } \
  801  \
  802             /* device might report stepsize 0. but we do at least 1 round */ \
  803             if (dpd->FORM.Range.StepSize.bits == 0) \
  804                 break; \
  805         } \
  806     } \
  807     if (!isset2) { \
  808         for (j=0;j<tblsize;j++) { \
  809             if (((tbl[j].vendor_id == 0) || \
  810                  (tbl[j].vendor_id == camera->pl->params.deviceinfo.VendorExtensionID)) && \
  811                  (tbl[j].value == dpd->CurrentValue.bits) \
  812             ) { \
  813                 gp_widget_add_choice (*widget, _(tbl[j].label)); \
  814                 isset2 = TRUE; \
  815                 gp_widget_set_value (*widget, _(tbl[j].label)); \
  816             } \
  817         } \
  818         if (!isset2) { \
  819             char buf[200]; \
  820             sprintf(buf, _("Unknown value %04x"), dpd->CurrentValue.bits); \
  821             gp_widget_add_choice (*widget, buf); \
  822             gp_widget_set_value (*widget, buf); \
  823         } \
  824     } \
  825     return (GP_OK); \
  826 } \
  827 \
  828 \
  829 static int \
  830 _put_Generic##bits##Table(CONFIG_PUT_ARGS, struct deviceproptable##bits * tbl, int tblsize) { \
  831     char *value; \
  832     int i, intval, j; \
  833     int foundvalue = 0; \
  834     type bits##val = 0; \
  835  \
  836     CR (gp_widget_get_value (widget, &value)); \
  837     for (i=0;i<tblsize;i++) { \
  838         if ((!strcmp(_(tbl[i].label),value) || !strcmp(tbl[i].label,value)) && \
  839             ((tbl[i].vendor_id == 0) || (tbl[i].vendor_id == camera->pl->params.deviceinfo.VendorExtensionID)) \
  840         ) { \
  841             bits##val = tbl[i].value; \
  842             foundvalue = 1; \
  843          \
  844             if (dpd->FormFlag & PTP_DPFF_Enumeration) { \
  845                 for (j = 0; j<dpd->FORM.Enum.NumberOfValues; j++) { \
  846                     if (bits##val == dpd->FORM.Enum.SupportedValue[j].bits) { \
  847                         GP_LOG_D ("FOUND right value for %s in the enumeration at val %d", value, bits##val); \
  848                         propval->bits = bits##val; \
  849                         return GP_OK; \
  850                     } \
  851                 } \
  852                 GP_LOG_D ("did not find the right value for %s in the enumeration at val %d... continuing", value, bits##val); \
  853                 /* continue looking, but with this value as fallback */ \
  854             } else { \
  855                 GP_LOG_D ("not an enumeration ... return %s as %d", value, bits##val); \
  856                 propval->bits = bits##val; \
  857                 return GP_OK; \
  858             } \
  859         } \
  860     } \
  861     if (foundvalue) { \
  862         GP_LOG_D ("Using fallback, not found in enum... return %s as %d", value, bits##val); \
  863         propval->bits = bits##val; \
  864         return GP_OK; \
  865     } \
  866     if (!sscanf(value, _("Unknown value %04x"), &intval)) { \
  867         GP_LOG_E ("failed to find value %s in list", value); \
  868         return GP_ERROR; \
  869     } \
  870     GP_LOG_D ("Using fallback, not found in enum... return %s as %d", value, bits##val); \
  871     propval->bits = intval; \
  872     return GP_OK; \
  873 }
  874 
  875 GENERIC_TABLE(u32,uint32_t,PTP_DTC_UINT32)
  876 GENERIC_TABLE(u16,uint16_t,PTP_DTC_UINT16)
  877 GENERIC_TABLE(i16,int16_t, PTP_DTC_INT16)
  878 GENERIC_TABLE(u8, uint8_t, PTP_DTC_UINT8)
  879 GENERIC_TABLE(i8, int8_t,  PTP_DTC_INT8)
  880 
  881 #define GENERIC16TABLE(name,tbl)            \
  882 static int                      \
  883 _get_##name(CONFIG_GET_ARGS) {              \
  884     return _get_Genericu16Table(CONFIG_GET_NAMES,   \
  885         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  886     );                      \
  887 }                           \
  888                             \
  889 static int __unused__                   \
  890 _put_##name(CONFIG_PUT_ARGS) {              \
  891     return _put_Genericu16Table(CONFIG_PUT_NAMES,   \
  892         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  893     );                      \
  894 }
  895 
  896 #define GENERIC32TABLE(name,tbl)            \
  897 static int                      \
  898 _get_##name(CONFIG_GET_ARGS) {              \
  899     return _get_Genericu32Table(CONFIG_GET_NAMES,   \
  900         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  901     );                      \
  902 }                           \
  903                             \
  904 static int __unused__                   \
  905 _put_##name(CONFIG_PUT_ARGS) {              \
  906     return _put_Genericu32Table(CONFIG_PUT_NAMES,   \
  907         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  908     );                      \
  909 }
  910 
  911 #define GENERICI16TABLE(name,tbl)           \
  912 static int                      \
  913 _get_##name(CONFIG_GET_ARGS) {              \
  914     return _get_Generici16Table(CONFIG_GET_NAMES,   \
  915         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  916     );                      \
  917 }                           \
  918                             \
  919 static int __unused__                   \
  920 _put_##name(CONFIG_PUT_ARGS) {              \
  921     return _put_Generici16Table(CONFIG_PUT_NAMES,   \
  922         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  923     );                      \
  924 }
  925 
  926 #define GENERIC8TABLE(name,tbl)             \
  927 static int                      \
  928 _get_##name(CONFIG_GET_ARGS) {              \
  929     return _get_Genericu8Table(CONFIG_GET_NAMES,    \
  930         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  931     );                      \
  932 }                           \
  933                             \
  934 static int __unused__                   \
  935 _put_##name(CONFIG_PUT_ARGS) {              \
  936     return _put_Genericu8Table(CONFIG_PUT_NAMES,    \
  937         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  938     );                      \
  939 }
  940 
  941 #define GENERICI8TABLE(name,tbl)            \
  942 static int                      \
  943 _get_##name(CONFIG_GET_ARGS) {              \
  944     return _get_Generici8Table(CONFIG_GET_NAMES,    \
  945         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  946     );                      \
  947 }                           \
  948                             \
  949 static int __unused__                   \
  950 _put_##name(CONFIG_PUT_ARGS) {              \
  951     return _put_Generici8Table(CONFIG_PUT_NAMES,    \
  952         tbl,sizeof(tbl)/sizeof(tbl[0])      \
  953     );                      \
  954 }
  955 
  956 static int
  957 _get_AUINT8_as_CHAR_ARRAY(CONFIG_GET_ARGS) {
  958     unsigned int    j;
  959     char        value[128];
  960 
  961     gp_widget_new (GP_WIDGET_TEXT, _(menu->label), widget);
  962     gp_widget_set_name (*widget, menu->name);
  963     if (dpd->DataType != PTP_DTC_AUINT8) {
  964         sprintf (value,_("unexpected datatype %i"),dpd->DataType);
  965     } else {
  966         memset(value,0,sizeof(value));
  967         for (j=0;j<dpd->CurrentValue.a.count;j++)
  968             value[j] = dpd->CurrentValue.a.v[j].u8;
  969     }
  970     gp_widget_set_value (*widget,value);
  971     return (GP_OK);
  972 }
  973 
  974 static int
  975 _get_STR(CONFIG_GET_ARGS) {
  976     char value[64];
  977 
  978     gp_widget_new (GP_WIDGET_TEXT, _(menu->label), widget);
  979     gp_widget_set_name (*widget, menu->name);
  980     if (dpd->DataType != PTP_DTC_STR) {
  981         sprintf (value,_("unexpected datatype %i"),dpd->DataType);
  982         gp_widget_set_value (*widget,value);
  983     } else {
  984         gp_widget_set_value (*widget,dpd->CurrentValue.str);
  985     }
  986     return (GP_OK);
  987 }
  988 
  989 static int
  990 _get_STR_ENUMList (CONFIG_GET_ARGS) {
  991     int j;
  992 
  993     if (!(dpd->FormFlag & PTP_DPFF_Enumeration))
  994         return GP_ERROR;
  995     if (dpd->DataType != PTP_DTC_STR)
  996         return GP_ERROR;
  997     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
  998     gp_widget_set_name (*widget, menu->name);
  999     for (j=0;j<dpd->FORM.Enum.NumberOfValues; j++)
 1000         gp_widget_add_choice (*widget,dpd->FORM.Enum.SupportedValue[j].str);
 1001     gp_widget_set_value (*widget,dpd->CurrentValue.str);
 1002     return GP_OK;
 1003 }
 1004 
 1005 static int
 1006 _put_STR(CONFIG_PUT_ARGS) {
 1007     const char *string;
 1008 
 1009     CR (gp_widget_get_value(widget, &string));
 1010     C_MEM (propval->str = strdup (string));
 1011     return (GP_OK);
 1012 }
 1013 
 1014 static int
 1015 _put_AUINT8_as_CHAR_ARRAY(CONFIG_PUT_ARGS) {
 1016     char    *value;
 1017     unsigned int i;
 1018 
 1019     CR (gp_widget_get_value(widget, &value));
 1020     memset(propval,0,sizeof(PTPPropertyValue));
 1021     /* add \0 ? */
 1022     C_MEM (propval->a.v = calloc((strlen(value)+1),sizeof(PTPPropertyValue)));
 1023     propval->a.count = strlen(value)+1;
 1024     for (i=0;i<strlen(value)+1;i++)
 1025         propval->a.v[i].u8 = value[i];
 1026     return (GP_OK);
 1027 }
 1028 
 1029 static int
 1030 _get_Range_INT8(CONFIG_GET_ARGS) {
 1031     float CurrentValue;
 1032 
 1033     if (dpd->FormFlag != PTP_DPFF_Range)
 1034         return (GP_ERROR_NOT_SUPPORTED);
 1035     if (dpd->DataType != PTP_DTC_INT8)
 1036         return (GP_ERROR_NOT_SUPPORTED);
 1037     gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 1038     gp_widget_set_name ( *widget, menu->name);
 1039     CurrentValue = (float) dpd->CurrentValue.i8;
 1040     gp_widget_set_range ( *widget, (float) dpd->FORM.Range.MinimumValue.i8, (float) dpd->FORM.Range.MaximumValue.i8, (float) dpd->FORM.Range.StepSize.i8);
 1041     gp_widget_set_value ( *widget, &CurrentValue);
 1042     return (GP_OK);
 1043 }
 1044 
 1045 
 1046 static int
 1047 _put_Range_INT8(CONFIG_PUT_ARGS) {
 1048     float f;
 1049 
 1050     CR (gp_widget_get_value(widget, &f));
 1051     propval->i8 = (int) f;
 1052     return (GP_OK);
 1053 }
 1054 
 1055 static int
 1056 _get_Range_UINT8(CONFIG_GET_ARGS) {
 1057     float CurrentValue;
 1058 
 1059     if (dpd->FormFlag != PTP_DPFF_Range)
 1060         return (GP_ERROR_NOT_SUPPORTED);
 1061     if (dpd->DataType != PTP_DTC_UINT8)
 1062         return (GP_ERROR_NOT_SUPPORTED);
 1063     gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 1064     gp_widget_set_name ( *widget, menu->name);
 1065     CurrentValue = (float) dpd->CurrentValue.u8;
 1066     gp_widget_set_range ( *widget, (float) dpd->FORM.Range.MinimumValue.u8, (float) dpd->FORM.Range.MaximumValue.u8, (float) dpd->FORM.Range.StepSize.u8);
 1067     gp_widget_set_value ( *widget, &CurrentValue);
 1068     return (GP_OK);
 1069 }
 1070 
 1071 
 1072 static int
 1073 _put_Range_UINT8(CONFIG_PUT_ARGS) {
 1074     float f;
 1075 
 1076     CR (gp_widget_get_value(widget, &f));
 1077     propval->u8 = (int) f;
 1078     return (GP_OK);
 1079 }
 1080 
 1081 static int
 1082 _get_Fuji_Totalcount(CONFIG_GET_ARGS) {
 1083     char buf[20];
 1084 
 1085     sprintf(buf,"%d",dpd->CurrentValue.u32 >> 16);
 1086     gp_widget_new (GP_WIDGET_TEXT, _(menu->label), widget);
 1087     gp_widget_set_name (*widget, menu->name);
 1088     gp_widget_set_value (*widget, buf);
 1089     return  GP_OK;
 1090 }
 1091 
 1092 /* generic int getter */
 1093 static int
 1094 _get_INT(CONFIG_GET_ARGS) {
 1095     char value[64];
 1096     float   rvalue = 0;
 1097 
 1098     switch (dpd->DataType) {
 1099     case PTP_DTC_UINT32:
 1100         sprintf (value, "%u", dpd->CurrentValue.u32 ); rvalue = dpd->CurrentValue.u32;
 1101         break;
 1102     case PTP_DTC_INT32:
 1103         sprintf (value, "%d", dpd->CurrentValue.i32 ); rvalue = dpd->CurrentValue.i32;
 1104         break;
 1105     case PTP_DTC_UINT16:
 1106         sprintf (value, "%u", dpd->CurrentValue.u16 ); rvalue = dpd->CurrentValue.u16;
 1107         break;
 1108     case PTP_DTC_INT16:
 1109         sprintf (value, "%d", dpd->CurrentValue.i16 ); rvalue = dpd->CurrentValue.i16;
 1110         break;
 1111     case PTP_DTC_UINT8:
 1112         sprintf (value, "%u", dpd->CurrentValue.u8 ); rvalue = dpd->CurrentValue.u8;
 1113         break;
 1114     case PTP_DTC_INT8:
 1115         sprintf (value, "%d", dpd->CurrentValue.i8 ); rvalue = dpd->CurrentValue.i8;
 1116         break;
 1117     default:
 1118         sprintf (value,_("unexpected datatype %i"),dpd->DataType);
 1119         return GP_ERROR;
 1120     }
 1121     if (dpd->FormFlag == PTP_DPFF_Enumeration) {
 1122         gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 1123         gp_widget_set_name (*widget, menu->name);
 1124         gp_widget_set_value (*widget, value); /* text */
 1125     } else {
 1126         if (dpd->FormFlag == PTP_DPFF_Range) {
 1127             gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 1128             gp_widget_set_name (*widget, menu->name);
 1129             gp_widget_set_value (*widget, &rvalue); /* float */
 1130         } else {
 1131             gp_widget_new (GP_WIDGET_TEXT, _(menu->label), widget);
 1132             gp_widget_set_name (*widget, menu->name);
 1133             gp_widget_set_value (*widget, value); /* text */
 1134         }
 1135     }
 1136 
 1137     if (dpd->FormFlag == PTP_DPFF_Enumeration) {
 1138         int i;
 1139 
 1140         for (i=0;i<dpd->FORM.Enum.NumberOfValues;i++) {
 1141             switch (dpd->DataType) {
 1142             case PTP_DTC_UINT32:    sprintf (value, "%u", dpd->FORM.Enum.SupportedValue[i].u32 ); break;
 1143             case PTP_DTC_INT32: sprintf (value, "%d", dpd->FORM.Enum.SupportedValue[i].i32 ); break;
 1144             case PTP_DTC_UINT16:    sprintf (value, "%u", dpd->FORM.Enum.SupportedValue[i].u16 ); break;
 1145             case PTP_DTC_INT16: sprintf (value, "%d", dpd->FORM.Enum.SupportedValue[i].i16 ); break;
 1146             case PTP_DTC_UINT8: sprintf (value, "%u", dpd->FORM.Enum.SupportedValue[i].u8  ); break;
 1147             case PTP_DTC_INT8:  sprintf (value, "%d", dpd->FORM.Enum.SupportedValue[i].i8  ); break;
 1148             default: sprintf (value,_("unexpected datatype %i"),dpd->DataType); return GP_ERROR;
 1149             }
 1150             gp_widget_add_choice (*widget,value);
 1151         }
 1152     }
 1153     if (dpd->FormFlag == PTP_DPFF_Range) {
 1154         float b = 0, t = 0, s = 0;
 1155 
 1156 #define X(type,u) case type: b = (float)dpd->FORM.Range.MinimumValue.u; t = (float)dpd->FORM.Range.MaximumValue.u; s = (float)dpd->FORM.Range.StepSize.u; break;
 1157         switch (dpd->DataType) {
 1158         X(PTP_DTC_UINT32,u32)
 1159         X(PTP_DTC_INT32,i32)
 1160         X(PTP_DTC_UINT16,u16)
 1161         X(PTP_DTC_INT16,i16)
 1162         X(PTP_DTC_UINT8,u8)
 1163         X(PTP_DTC_INT8,i8)
 1164         }
 1165 #undef X
 1166         gp_widget_set_range (*widget, b, t, s);
 1167     }
 1168     return GP_OK;
 1169 }
 1170 
 1171 static int
 1172 _put_INT(CONFIG_PUT_ARGS) {
 1173     if (dpd->FormFlag == PTP_DPFF_Range) {
 1174         float f;
 1175 
 1176         CR (gp_widget_get_value(widget, &f));
 1177         switch (dpd->DataType) {
 1178         case PTP_DTC_UINT32:    propval->u32 = f; break;
 1179         case PTP_DTC_INT32: propval->i32 = f; break;
 1180         case PTP_DTC_UINT16:    propval->u16 = f; break;
 1181         case PTP_DTC_INT16: propval->i16 = f; break;
 1182         case PTP_DTC_UINT8: propval->u8 = f; break;
 1183         case PTP_DTC_INT8:  propval->i8 = f; break;
 1184         }
 1185         return GP_OK;
 1186     } else {
 1187         char *value;
 1188         unsigned int u;
 1189         int i;
 1190 
 1191         CR (gp_widget_get_value(widget, &value));
 1192 
 1193         switch (dpd->DataType) {
 1194         case PTP_DTC_UINT32:
 1195         case PTP_DTC_UINT16:
 1196         case PTP_DTC_UINT8:
 1197             C_PARAMS (1 == sscanf (value, "%u", &u ));
 1198             break;
 1199         case PTP_DTC_INT32:
 1200         case PTP_DTC_INT16:
 1201         case PTP_DTC_INT8:
 1202             C_PARAMS (1 == sscanf (value, "%d", &i ));
 1203             break;
 1204         default:
 1205             return GP_ERROR;
 1206         }
 1207         switch (dpd->DataType) {
 1208         case PTP_DTC_UINT32:
 1209             propval->u32 = u;
 1210             break;
 1211         case PTP_DTC_INT32:
 1212             propval->i32 = i;
 1213             break;
 1214         case PTP_DTC_UINT16:
 1215             propval->u16 = u;
 1216             break;
 1217         case PTP_DTC_INT16:
 1218             propval->i16 = i;
 1219             break;
 1220         case PTP_DTC_UINT8:
 1221             propval->u8 = u;
 1222             break;
 1223         case PTP_DTC_INT8:
 1224             propval->i8 = i;
 1225             break;
 1226         }
 1227     }
 1228     return GP_OK;
 1229 }
 1230 
 1231 
 1232 static int
 1233 _get_Nikon_OnOff_UINT8(CONFIG_GET_ARGS) {
 1234     if (dpd->FormFlag != PTP_DPFF_Range)
 1235         return (GP_ERROR_NOT_SUPPORTED);
 1236     if (dpd->DataType != PTP_DTC_UINT8)
 1237         return (GP_ERROR_NOT_SUPPORTED);
 1238     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 1239     gp_widget_set_name ( *widget, menu->name);
 1240     gp_widget_add_choice (*widget,_("On"));
 1241     gp_widget_add_choice (*widget,_("Off"));
 1242     gp_widget_set_value ( *widget, (dpd->CurrentValue.u8?_("On"):_("Off")));
 1243     return (GP_OK);
 1244 }
 1245 
 1246 static int
 1247 _put_Nikon_OnOff_UINT8(CONFIG_PUT_ARGS) {
 1248     char *value;
 1249 
 1250     CR (gp_widget_get_value(widget, &value));
 1251     if(!strcmp(value,_("On"))) {
 1252         propval->u8 = 1;
 1253         return (GP_OK);
 1254     }
 1255     if(!strcmp(value,_("Off"))) {
 1256         propval->u8 = 0;
 1257         return (GP_OK);
 1258     }
 1259     return (GP_ERROR);
 1260 }
 1261 
 1262 static int
 1263 _get_Nikon_OffOn_UINT8(CONFIG_GET_ARGS) {
 1264     if (dpd->FormFlag != PTP_DPFF_Range)
 1265         return (GP_ERROR_NOT_SUPPORTED);
 1266     if (dpd->DataType != PTP_DTC_UINT8)
 1267         return (GP_ERROR_NOT_SUPPORTED);
 1268     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 1269     gp_widget_set_name ( *widget, menu->name);
 1270     gp_widget_add_choice (*widget,_("On"));
 1271     gp_widget_add_choice (*widget,_("Off"));
 1272     gp_widget_set_value ( *widget, (!dpd->CurrentValue.u8?_("On"):_("Off")));
 1273     return (GP_OK);
 1274 }
 1275 
 1276 static int
 1277 _put_Nikon_OffOn_UINT8(CONFIG_PUT_ARGS) {
 1278     char *value;
 1279 
 1280     CR (gp_widget_get_value(widget, &value));
 1281     if(!strcmp(value,_("On"))) {
 1282         propval->u8 = 0;
 1283         return (GP_OK);
 1284     }
 1285     if(!strcmp(value,_("Off"))) {
 1286         propval->u8 = 1;
 1287         return (GP_OK);
 1288     }
 1289     return (GP_ERROR);
 1290 }
 1291 
 1292 #define PUT_SONY_VALUE_(bits,inttype)                               \
 1293 static int                                      \
 1294 _put_sony_value_##bits (PTPParams*params, uint16_t prop, inttype value,int useenumorder) {  \
 1295     GPContext       *context = ((PTPData *) params->data)->context;     \
 1296     PTPDevicePropDesc   dpd;                            \
 1297     PTPPropertyValue    propval;                        \
 1298     inttype         origval;                        \
 1299     time_t          start,end;                      \
 1300     int         tries = 100;    /* 100 steps allowed towards the new value */   \
 1301                                             \
 1302     GP_LOG_D("setting 0x%04x to 0x%08x", prop, value);              \
 1303                                             \
 1304     C_PTP_REP (ptp_sony_getalldevicepropdesc (params));             \
 1305     C_PTP_REP (ptp_generic_getdevicepropdesc (params, prop, &dpd));         \
 1306     if (value == dpd.CurrentValue.bits) {                       \
 1307         GP_LOG_D("value is already 0x%08x", value);             \
 1308         return GP_OK;                               \
 1309     }                                       \
 1310 fallback:                                       \
 1311     do {                                        \
 1312         origval = dpd.CurrentValue.bits;                    \
 1313         /* if it is a ENUM, the camera will walk through the ENUM */        \
 1314         if (useenumorder && (dpd.FormFlag & PTP_DPFF_Enumeration) && dpd.FORM.Enum.NumberOfValues) {        \
 1315             int i, posorig = -1, posnew = -1;               \
 1316                                             \
 1317             for (i=0;i<dpd.FORM.Enum.NumberOfValues;i++) {          \
 1318                 if (origval == dpd.FORM.Enum.SupportedValue[i].bits)    \
 1319                     posorig = i;                    \
 1320                 if (value == dpd.FORM.Enum.SupportedValue[i].bits)  \
 1321                     posnew = i;                 \
 1322                 if ((posnew != -1) && (posorig != -1))          \
 1323                     break;                      \
 1324             }                               \
 1325             if (posnew == -1) {                     \
 1326                 gp_context_error (context, _("Target value is not in enumeration."));\
 1327                 return GP_ERROR_BAD_PARAMETERS;             \
 1328             }                               \
 1329             GP_LOG_D("posnew %d, posorig %d, value %d", posnew, posorig, value);    \
 1330             if (posnew == posorig)                      \
 1331                 break;                          \
 1332             if (posnew > posorig)                       \
 1333                 propval.u8 = posnew-posorig;                \
 1334             else                                \
 1335                 propval.u8 = 0x100-(posorig-posnew);            \
 1336         } else {                                \
 1337             if (value == origval)                       \
 1338                 break;                          \
 1339             if (value > origval)                        \
 1340                 propval.u8 = 0x01;                  \
 1341             else                                \
 1342                 propval.u8 = 0xff;                  \
 1343         }                                   \
 1344         C_PTP_REP (ptp_sony_setdevicecontrolvalueb (params, prop, &propval, PTP_DTC_UINT8 ));\
 1345                                             \
 1346         GP_LOG_D ("value is (0x%x vs target 0x%x)", origval, value);        \
 1347                                             \
 1348         /* we tell the camera to do it, but it takes around 0.7 seconds for the SLT-A58 */  \
 1349         time(&start);                               \
 1350         do {                                    \
 1351             C_PTP_REP (ptp_sony_getalldevicepropdesc (params));     \
 1352             C_PTP_REP (ptp_generic_getdevicepropdesc (params, prop, &dpd)); \
 1353                                             \
 1354             if (dpd.CurrentValue.bits == value) {               \
 1355                 GP_LOG_D ("Value matched!");                \
 1356                 break;                          \
 1357             }                               \
 1358             if (dpd.CurrentValue.bits != origval) {             \
 1359                 GP_LOG_D ("value changed (0x%x vs 0x%x vs target 0x%x), next step....", dpd.CurrentValue.bits, origval, value);\
 1360                 break;                          \
 1361             }                               \
 1362                                             \
 1363             usleep(200*1000);                       \
 1364                                             \
 1365             time(&end);                         \
 1366         } while (end-start <= 3);                       \
 1367                                             \
 1368         if (propval.u8 == 0x01 && dpd.CurrentValue.bits > value) {      \
 1369             GP_LOG_D ("We overshooted value, maybe not exact match possible. Break!");  \
 1370             break;                              \
 1371         }                                   \
 1372         if (propval.u8 == 0xff && dpd.CurrentValue.bits < value) {      \
 1373             GP_LOG_D ("We overshooted value, maybe not exact match possible. Break!");  \
 1374             break;                              \
 1375         }                                   \
 1376                                             \
 1377         if (dpd.CurrentValue.bits == value) {                   \
 1378             GP_LOG_D ("Value matched!");                    \
 1379             break;                              \
 1380         }                                   \
 1381         if (dpd.CurrentValue.bits == origval) {                 \
 1382             GP_LOG_D ("value did not change (0x%x vs 0x%x vs target 0x%x), not good ...", dpd.CurrentValue.bits, origval, value);\
 1383             break;                              \
 1384         }                                   \
 1385         /* We did not get there. Did we hit 0? */               \
 1386         if (useenumorder && (dpd.FormFlag & PTP_DPFF_Enumeration)) {        \
 1387             int i, posnow = -1;                     \
 1388                                             \
 1389             for (i=0;i<dpd.FORM.Enum.NumberOfValues;i++) {          \
 1390                 if (dpd.CurrentValue.bits == dpd.FORM.Enum.SupportedValue[i].bits) {    \
 1391                     posnow = i;                 \
 1392                     break;                      \
 1393                 }                           \
 1394             }                               \
 1395             if (posnow == -1) {                     \
 1396                 GP_LOG_D ("Now value is not in enumeration, falling back to ordered tries.");\
 1397                 useenumorder = 0;                   \
 1398                 goto fallback;                      \
 1399             }                               \
 1400             GP_LOG_D("posnow %d, value %d", posnow, dpd.CurrentValue.bits); \
 1401             if ((posnow == 0) && (propval.u8 == 0xff)) {            \
 1402                 gp_context_error (context, _("Sony was not able to set the new value, is it valid?"));  \
 1403                 GP_LOG_D ("hit bottom of enumeration, not good.");  \
 1404                 return GP_ERROR;                    \
 1405             }                               \
 1406             if ((posnow == dpd.FORM.Enum.NumberOfValues-1) && (propval.u8 == 0x01)) {           \
 1407                 GP_LOG_D ("hit top of enumeration, not good.");     \
 1408                 gp_context_error (context, _("Sony was not able to set the new value, is it valid?"));  \
 1409                 return GP_ERROR;                    \
 1410             }                               \
 1411         }                                   \
 1412     } while (tries--);/* occasionally we fail, make an escape path */       \
 1413     return GP_OK;                                   \
 1414 }
 1415 
 1416 PUT_SONY_VALUE_(u16,uint16_t) /* _put_sony_value_u16 */
 1417 PUT_SONY_VALUE_(i16,int16_t) /* _put_sony_value_i16 */
 1418 PUT_SONY_VALUE_(u32,uint32_t) /* _put_sony_value_u32 */
 1419 
 1420 static int
 1421 _get_CANON_FirmwareVersion(CONFIG_GET_ARGS) {
 1422     char value[64];
 1423 
 1424     gp_widget_new (GP_WIDGET_TEXT, _(menu->label), widget);
 1425     gp_widget_set_name (*widget, menu->name);
 1426     if (dpd->DataType != PTP_DTC_UINT32) {
 1427         sprintf (value,_("unexpected datatype %i"),dpd->DataType);
 1428     } else {
 1429         uint32_t x = dpd->CurrentValue.u32;
 1430         sprintf (value,"%d.%d.%d.%d",((x&0xff000000)>>24),((x&0xff0000)>>16),((x&0xff00)>>8),x&0xff);
 1431     }
 1432     gp_widget_set_value (*widget,value);
 1433     return (GP_OK);
 1434 }
 1435 
 1436 static struct deviceproptableu16 whitebalance[] = {
 1437     { N_("Manual"),         0x0001, 0 },
 1438     { N_("Automatic"),      0x0002, 0 },
 1439     { N_("One-push Automatic"), 0x0003, 0 },
 1440     { N_("Daylight"),       0x0004, 0 },
 1441     { N_("Fluorescent"),        0x0005, 0 },
 1442     { N_("Tungsten"),       0x0006, 0 },
 1443     { N_("Flash"),          0x0007, 0 },
 1444     { N_("Cloudy"),         0x8010, PTP_VENDOR_NIKON },
 1445     { N_("Shade"),          0x8011, PTP_VENDOR_NIKON },
 1446     { N_("Color Temperature"),  0x8012, PTP_VENDOR_NIKON },
 1447     { N_("Preset"),         0x8013, PTP_VENDOR_NIKON },
 1448     { N_("Off"),            0x8014, PTP_VENDOR_NIKON },
 1449     { N_("Natural light auto"), 0x8016, PTP_VENDOR_NIKON },
 1450 
 1451     { N_("Fluorescent Lamp 1"), 0x8001, PTP_VENDOR_FUJI },
 1452     { N_("Fluorescent Lamp 2"), 0x8002, PTP_VENDOR_FUJI },
 1453     { N_("Fluorescent Lamp 3"), 0x8003, PTP_VENDOR_FUJI },
 1454     { N_("Fluorescent Lamp 4"), 0x8004, PTP_VENDOR_FUJI },
 1455     { N_("Fluorescent Lamp 5"), 0x8005, PTP_VENDOR_FUJI },
 1456     { N_("Shade"),          0x8006, PTP_VENDOR_FUJI },
 1457     { N_("Choose Color Temperature"),0x8007, PTP_VENDOR_FUJI },
 1458     { N_("Preset Custom 1"),    0x8008, PTP_VENDOR_FUJI },
 1459     { N_("Preset Custom 2"),    0x8009, PTP_VENDOR_FUJI },
 1460     { N_("Preset Custom 3"),    0x800a, PTP_VENDOR_FUJI },
 1461     { N_("Preset Custom 4"),    0x800b, PTP_VENDOR_FUJI },
 1462     { N_("Preset Custom 5"),    0x800c, PTP_VENDOR_FUJI },
 1463 
 1464     { N_("Shade"),          0x8011, PTP_VENDOR_SONY },
 1465     { N_("Cloudy"),         0x8010, PTP_VENDOR_SONY },
 1466     { N_("Fluorescent: Warm White"),0x8001, PTP_VENDOR_SONY },
 1467     { N_("Fluorescent: Cold White"),0x8002, PTP_VENDOR_SONY },
 1468     { N_("Fluorescent: Day White"), 0x8003, PTP_VENDOR_SONY },
 1469     { N_("Fluorescent: Daylight"),  0x8004, PTP_VENDOR_SONY },
 1470     { N_("Choose Color Temperature"),0x8012, PTP_VENDOR_SONY },
 1471     { N_("Preset 1"),       0x8020, PTP_VENDOR_SONY },
 1472     { N_("Preset 2"),       0x8021, PTP_VENDOR_SONY },
 1473     { N_("Preset 3"),       0x8022, PTP_VENDOR_SONY },
 1474     { N_("Preset"),         0x8023, PTP_VENDOR_SONY },
 1475     { N_("Underwater: Auto"),   0x8030, PTP_VENDOR_SONY },
 1476 
 1477     { N_("Shade"),          0x8001, PTP_VENDOR_PENTAX },
 1478     { N_("Cloudy"),         0x8002, PTP_VENDOR_PENTAX },
 1479     { N_("Tungsten 2"),     0x8020, PTP_VENDOR_PENTAX },
 1480     { N_("Fluorescent: Daylight"),  0x8003, PTP_VENDOR_PENTAX },
 1481     { N_("Fluorescent: Day White"), 0x8004, PTP_VENDOR_PENTAX },
 1482     { N_("Fluorescent: White"), 0x8005, PTP_VENDOR_PENTAX },
 1483     { N_("Fluorescent: Tungsten"),  0x8006, PTP_VENDOR_PENTAX },
 1484 };
 1485 GENERIC16TABLE(WhiteBalance,whitebalance)
 1486 
 1487 static struct deviceproptableu16 olympus_whitebalance[] = {
 1488     { N_("Automatic"),      0x0001, 0 },
 1489     { N_("Daylight"),       0x0002, 0 },
 1490     { N_("Shade"),          0x0003, 0 },
 1491     { N_("Cloudy"),         0x0004, 0 },
 1492     { N_("Tungsten"),       0x0005, 0 },
 1493     { N_("Fluorescent"),        0x0006, 0 },
 1494     { N_("Underwater"),     0x0007, 0 },
 1495     { N_("Flash"),          0x0008, 0 },
 1496     { N_("Preset 1"),       0x0009, 0 },
 1497     { N_("Preset 2"),       0x000a, 0 },
 1498     { N_("Preset 3"),       0x000b, 0 },
 1499     { N_("Preset 4"),       0x000c, 0 },
 1500     { N_("Custom"),         0x000d, 0 },
 1501 };
 1502 GENERIC16TABLE(Olympus_WhiteBalance,olympus_whitebalance)
 1503 
 1504 static struct deviceproptableu16 fuji_imageformat[] = {
 1505     { N_("RAW"),            1,  PTP_VENDOR_FUJI },
 1506     { N_("JPEG Fine"),      2,  PTP_VENDOR_FUJI },
 1507     { N_("JPEG Normal"),        3,  PTP_VENDOR_FUJI },
 1508     { N_("RAW + JPEG Fine"),    4,  PTP_VENDOR_FUJI },
 1509     { N_("RAW + JPEG Normal"),  5,  PTP_VENDOR_FUJI },
 1510 };
 1511 GENERIC16TABLE(Fuji_ImageFormat,fuji_imageformat)
 1512 
 1513 static struct deviceproptableu16 olympus_imageformat[] = {
 1514     { N_("RAW"),            0x020,  PTP_VENDOR_GP_OLYMPUS_OMD },
 1515     { N_("Large Fine JPEG"),    0x101,  PTP_VENDOR_GP_OLYMPUS_OMD },
 1516     { N_("Large Normal JPEG"),  0x102,  PTP_VENDOR_GP_OLYMPUS_OMD },
 1517     { N_("Medium Normal JPEG"), 0x103,  PTP_VENDOR_GP_OLYMPUS_OMD },
 1518     { N_("Small Normal JPEG"),  0x104,  PTP_VENDOR_GP_OLYMPUS_OMD },
 1519     { N_("Large Fine JPEG+RAW"),    0x121,  PTP_VENDOR_GP_OLYMPUS_OMD },
 1520     { N_("Large Normal JPEG+RAW"),  0x122,  PTP_VENDOR_GP_OLYMPUS_OMD },
 1521     { N_("Medium Normal JPEG+RAW"), 0x123,  PTP_VENDOR_GP_OLYMPUS_OMD },
 1522     { N_("Small Normal JPEG+RAW"),  0x124,  PTP_VENDOR_GP_OLYMPUS_OMD },
 1523 };
 1524 GENERIC16TABLE(Olympus_Imageformat,olympus_imageformat)
 1525 
 1526 static struct deviceproptableu16 fuji_releasemode[] = {
 1527     { N_("Single frame"),       1,  PTP_VENDOR_FUJI },
 1528     { N_("Continuous low speed"),   2,  PTP_VENDOR_FUJI },
 1529     { N_("Continuous high speed"),  3,  PTP_VENDOR_FUJI },
 1530     { N_("Self-timer"),     4,  PTP_VENDOR_FUJI },
 1531     { N_("Mup Mirror up"),      5,  PTP_VENDOR_FUJI },
 1532 };
 1533 GENERIC16TABLE(Fuji_ReleaseMode,fuji_releasemode)
 1534 
 1535 static struct deviceproptableu16 fuji_filmsimulation[] = {
 1536     { N_("PROVIA/Standard"),            1,  PTP_VENDOR_FUJI },
 1537     { N_("Velvia/Vivid"),               2,  PTP_VENDOR_FUJI },
 1538     { N_("ASTIA/Soft"),                 3,  PTP_VENDOR_FUJI },
 1539     { N_("PRO Neg.Hi"),                 4,  PTP_VENDOR_FUJI },
 1540     { N_("PRO Neg.Std"),                5,  PTP_VENDOR_FUJI },
 1541     { N_("Black & White"),              6,  PTP_VENDOR_FUJI },
 1542     { N_("Black & White+Ye Filter"),    7,  PTP_VENDOR_FUJI },
 1543     { N_("Black & White+R Filter"),     8,  PTP_VENDOR_FUJI },
 1544     { N_("Black & White+G Filter"),     9,  PTP_VENDOR_FUJI },
 1545     { N_("Sepia"),                      10, PTP_VENDOR_FUJI },
 1546     { N_("Classic Chrome"),             11, PTP_VENDOR_FUJI },
 1547     { N_("ACROS"),                      12, PTP_VENDOR_FUJI },
 1548     { N_("ACROS+Ye Filter"),            13, PTP_VENDOR_FUJI },
 1549     { N_("ACROS+R Filter,"),            14, PTP_VENDOR_FUJI },
 1550     { N_("ACROS+G Filter"),             15, PTP_VENDOR_FUJI },
 1551     { N_("ETERNA/Cinema"),              16, PTP_VENDOR_FUJI },
 1552     { N_("Classic Neg"),                17, PTP_VENDOR_FUJI },
 1553     { N_("ETERNA BLEACH BYPASS"),       18, PTP_VENDOR_FUJI },
 1554 };
 1555 GENERIC16TABLE(Fuji_FilmSimulation,fuji_filmsimulation)
 1556 
 1557 static int
 1558 _get_ExpCompensation(CONFIG_GET_ARGS) {
 1559     int j;
 1560     char buf[13];
 1561 
 1562     if (!(dpd->FormFlag & PTP_DPFF_Enumeration))
 1563         return GP_ERROR;
 1564     if (dpd->DataType != PTP_DTC_INT16)
 1565         return GP_ERROR;
 1566     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 1567     gp_widget_set_name (*widget, menu->name);
 1568     for (j=0;j<dpd->FORM.Enum.NumberOfValues; j++) {
 1569         sprintf(buf, "%g", dpd->FORM.Enum.SupportedValue[j].i16/1000.0);
 1570         gp_widget_add_choice (*widget,buf);
 1571     }
 1572     sprintf(buf, "%g", dpd->CurrentValue.i16/1000.0);
 1573     gp_widget_set_value (*widget,buf);
 1574     return GP_OK;
 1575 }
 1576 
 1577 static int
 1578 _put_ExpCompensation(CONFIG_PUT_ARGS) {
 1579     char    *value;
 1580     float   x;
 1581     int16_t val, targetval = 0;
 1582     int mindist = 65535, j;
 1583 
 1584     CR (gp_widget_get_value(widget, &value));
 1585     if (1 != sscanf(value,"%g", &x))
 1586         return GP_ERROR;
 1587 
 1588     /* float processing is not always hitting the right values, but close */
 1589     val = x*1000.0;
 1590     for (j=0;j<dpd->FORM.Enum.NumberOfValues; j++) {
 1591         if (abs(dpd->FORM.Enum.SupportedValue[j].i16 - val) < mindist) {
 1592             mindist = abs(dpd->FORM.Enum.SupportedValue[j].i16 - val);
 1593             targetval = dpd->FORM.Enum.SupportedValue[j].i16;
 1594         }
 1595     }
 1596     propval->i16 = targetval;
 1597     return GP_OK ;
 1598 }
 1599 
 1600 /* old method, uses stepping */
 1601 static int
 1602 _put_Sony_ExpCompensation(CONFIG_PUT_ARGS) {
 1603     int ret;
 1604 
 1605     ret = _put_ExpCompensation(CONFIG_PUT_NAMES);
 1606     if (ret != GP_OK) return ret;
 1607     return _put_sony_value_i16 (&camera->pl->params, dpd->DevicePropertyCode, propval->i16, 0);
 1608 }
 1609 
 1610 /* new method, can set directly */
 1611 static int
 1612 _put_Sony_ExpCompensation2(CONFIG_PUT_ARGS) {
 1613     int ret;
 1614 
 1615     ret = _put_ExpCompensation(CONFIG_PUT_NAMES);
 1616     if (ret != GP_OK) return ret;
 1617     return translate_ptp_result (ptp_sony_setdevicecontrolvaluea (&camera->pl->params, dpd->DevicePropertyCode, propval, PTP_DTC_INT16));
 1618 }
 1619 
 1620 static int
 1621 _get_Olympus_ExpCompensation(CONFIG_GET_ARGS) {
 1622     int j;
 1623     char buf[13];
 1624 
 1625     if (!(dpd->FormFlag & PTP_DPFF_Enumeration))
 1626         return GP_ERROR;
 1627     if (dpd->DataType != PTP_DTC_UINT16)
 1628         return GP_ERROR;
 1629     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 1630     gp_widget_set_name (*widget, menu->name);
 1631     for (j=0;j<dpd->FORM.Enum.NumberOfValues; j++) {
 1632         sprintf(buf, "%g", dpd->FORM.Enum.SupportedValue[j].i16/1000.0);
 1633         gp_widget_add_choice (*widget,buf);
 1634     }
 1635     sprintf(buf, "%g", dpd->CurrentValue.i16/1000.0);
 1636     gp_widget_set_value (*widget,buf);
 1637     return GP_OK;
 1638 }
 1639 
 1640 static int
 1641 _put_Olympus_ExpCompensation(CONFIG_PUT_ARGS) {
 1642     char    *value;
 1643     float   x;
 1644     int16_t val, targetval = 0;
 1645     int mindist = 65535, j;
 1646 
 1647     CR (gp_widget_get_value(widget, &value));
 1648     if (1 != sscanf(value,"%g", &x))
 1649         return GP_ERROR;
 1650 
 1651     /* float processing is not always hitting the right values, but close */
 1652     val = x*1000.0;
 1653     for (j=0;j<dpd->FORM.Enum.NumberOfValues; j++) {
 1654         if (abs(dpd->FORM.Enum.SupportedValue[j].i16 - val) < mindist) {
 1655             mindist = abs(dpd->FORM.Enum.SupportedValue[j].i16 - val);
 1656             targetval = dpd->FORM.Enum.SupportedValue[j].i16;
 1657         }
 1658     }
 1659     propval->i16 = targetval;
 1660     return GP_OK ;
 1661 }
 1662 
 1663 
 1664 static struct deviceproptableu16 canon_assistlight[] = {
 1665     { N_("On"), 0x0000, PTP_VENDOR_CANON },
 1666     { N_("Off"),    0x0001, PTP_VENDOR_CANON },
 1667 };
 1668 GENERIC16TABLE(Canon_AssistLight,canon_assistlight)
 1669 
 1670 static struct deviceproptableu16 canon_autorotation[] = {
 1671     { N_("On"), 0x0000, PTP_VENDOR_CANON },
 1672     { N_("Off"),    0x0001, PTP_VENDOR_CANON },
 1673 };
 1674 GENERIC16TABLE(Canon_AutoRotation,canon_autorotation)
 1675 
 1676 static struct deviceproptableu16 canon_beepmode[] = {
 1677     { N_("Off"),    0x00, PTP_VENDOR_CANON },
 1678     { N_("On"), 0x01, PTP_VENDOR_CANON },
 1679 };
 1680 GENERIC16TABLE(Canon_BeepMode,canon_beepmode)
 1681 
 1682 static int
 1683 _get_Canon_ZoomRange(CONFIG_GET_ARGS) {
 1684     float   f, t, b, s;
 1685 
 1686     if (!(dpd->FormFlag & PTP_DPFF_Range))
 1687         return GP_ERROR;
 1688     gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 1689     gp_widget_set_name (*widget,menu->name);
 1690     f = (float)dpd->CurrentValue.u16;
 1691     b = (float)dpd->FORM.Range.MinimumValue.u16;
 1692     t = (float)dpd->FORM.Range.MaximumValue.u16;
 1693     s = (float)dpd->FORM.Range.StepSize.u16;
 1694     gp_widget_set_range (*widget, b, t, s);
 1695     gp_widget_set_value (*widget, &f);
 1696     return GP_OK;
 1697 }
 1698 
 1699 static int
 1700 _put_Canon_ZoomRange(CONFIG_PUT_ARGS)
 1701 {
 1702     float   f;
 1703 
 1704     CR (gp_widget_get_value(widget, &f));
 1705     propval->u16 = (unsigned short)f;
 1706     return (GP_OK);
 1707 }
 1708 
 1709 /* This seems perhaps focal length * 1.000.000 */
 1710 static int
 1711 _get_Sony_Zoom(CONFIG_GET_ARGS) {
 1712     float   f, t, b, s;
 1713 
 1714     if (dpd->DataType != PTP_DTC_UINT32)
 1715         return GP_ERROR;
 1716     if (!(dpd->FormFlag & PTP_DPFF_Range))
 1717         return GP_ERROR;
 1718     gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 1719     gp_widget_set_name (*widget,menu->name);
 1720     f = (float)dpd->CurrentValue.u32 / 1000000;
 1721     b = (float)dpd->FORM.Range.MinimumValue.u32 / 1000000;
 1722     t = (float)dpd->FORM.Range.MaximumValue.u32 / 1000000;
 1723     s = 1;
 1724     gp_widget_set_range (*widget, b, t, s);
 1725     gp_widget_set_value (*widget, &f);
 1726     return GP_OK;
 1727 }
 1728 
 1729 static int
 1730 _put_Sony_Zoom(CONFIG_PUT_ARGS)
 1731 {
 1732     float   f;
 1733     PTPParams *params = &camera->pl->params;
 1734 
 1735     CR (gp_widget_get_value(widget, &f));
 1736     propval->u32 = (uint32_t)f*1000000;
 1737     return _put_sony_value_u32(params, PTP_DPC_SONY_Zoom, propval->u32, 0);
 1738 }
 1739 
 1740 static int
 1741 _get_Nikon_WBBias(CONFIG_GET_ARGS) {
 1742     float   f, t, b, s;
 1743 
 1744     if (dpd->DataType != PTP_DTC_INT8)
 1745         return GP_ERROR;
 1746     if (!(dpd->FormFlag & PTP_DPFF_Range))
 1747         return GP_ERROR;
 1748     gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 1749     gp_widget_set_name (*widget,menu->name);
 1750     f = (float)dpd->CurrentValue.i8;
 1751     b = (float)dpd->FORM.Range.MinimumValue.i8;
 1752     t = (float)dpd->FORM.Range.MaximumValue.i8;
 1753     s = (float)dpd->FORM.Range.StepSize.i8;
 1754     gp_widget_set_range (*widget, b, t, s);
 1755     gp_widget_set_value (*widget, &f);
 1756     return (GP_OK);
 1757 }
 1758 
 1759 static int
 1760 _put_Nikon_WBBias(CONFIG_PUT_ARGS)
 1761 {
 1762     float   f;
 1763 
 1764     CR (gp_widget_get_value(widget, &f));
 1765     propval->i8 = (signed char)f;
 1766     return (GP_OK);
 1767 }
 1768 
 1769 /* This can get type 1 (INT8) , 2 (UINT8) and 4 (UINT16) */
 1770 static int
 1771 _get_Nikon_UWBBias(CONFIG_GET_ARGS) {
 1772     float   f, t, b, s;
 1773 
 1774     if (!(dpd->FormFlag & PTP_DPFF_Range))
 1775         return GP_ERROR;
 1776     gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 1777     gp_widget_set_name (*widget,menu->name);
 1778     switch (dpd->DataType) {
 1779     case PTP_DTC_UINT16:
 1780         f = (float)dpd->CurrentValue.u16;
 1781         b = (float)dpd->FORM.Range.MinimumValue.u16;
 1782         t = (float)dpd->FORM.Range.MaximumValue.u16;
 1783         s = (float)dpd->FORM.Range.StepSize.u16;
 1784         break;
 1785     case PTP_DTC_UINT8:
 1786         f = (float)dpd->CurrentValue.u8;
 1787         b = (float)dpd->FORM.Range.MinimumValue.u8;
 1788         t = (float)dpd->FORM.Range.MaximumValue.u8;
 1789         s = (float)dpd->FORM.Range.StepSize.u8;
 1790         break;
 1791     case PTP_DTC_INT8:
 1792         f = (float)dpd->CurrentValue.i8;
 1793         b = (float)dpd->FORM.Range.MinimumValue.i8;
 1794         t = (float)dpd->FORM.Range.MaximumValue.i8;
 1795         s = (float)dpd->FORM.Range.StepSize.i8;
 1796         break;
 1797     default:
 1798         return GP_ERROR;
 1799     }
 1800     gp_widget_set_range (*widget, b, t, s);
 1801     gp_widget_set_value (*widget, &f);
 1802     return GP_OK;
 1803 }
 1804 
 1805 static int
 1806 _put_Nikon_UWBBias(CONFIG_PUT_ARGS)
 1807 {
 1808     float   f;
 1809 
 1810     CR (gp_widget_get_value(widget, &f));
 1811     switch (dpd->DataType) {
 1812     case PTP_DTC_UINT16:
 1813         propval->u16 = (unsigned short)f;
 1814         break;
 1815     case PTP_DTC_UINT8:
 1816         propval->u8 = (unsigned char)f;
 1817         break;
 1818     case PTP_DTC_INT8:
 1819         propval->i8 = (char)f;
 1820         break;
 1821     default:
 1822         return GP_ERROR;
 1823     }
 1824     return GP_OK;
 1825 }
 1826 
 1827 static int
 1828 _get_Nikon_WBBiasPresetVal(CONFIG_GET_ARGS) {
 1829     char buf[20];
 1830 
 1831     if (dpd->DataType != PTP_DTC_UINT32)
 1832         return (GP_ERROR);
 1833     gp_widget_new (GP_WIDGET_TEXT, _(menu->label), widget);
 1834     gp_widget_set_name (*widget,menu->name);
 1835     sprintf (buf, "%d", dpd->CurrentValue.u32);
 1836     gp_widget_set_value (*widget, buf);
 1837     return (GP_OK);
 1838 }
 1839 static int
 1840 _get_Nikon_WBBiasPreset(CONFIG_GET_ARGS) {
 1841     char buf[20];
 1842     int i;
 1843 
 1844     if (dpd->DataType != PTP_DTC_UINT8)
 1845         return (GP_ERROR);
 1846     if (!(dpd->FormFlag & PTP_DPFF_Range))
 1847         return (GP_ERROR);
 1848     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 1849     gp_widget_set_name (*widget,menu->name);
 1850     for (i = dpd->FORM.Range.MinimumValue.u8; i < dpd->FORM.Range.MaximumValue.u8; i++) {
 1851         sprintf (buf, "%d", i);
 1852         gp_widget_add_choice (*widget, buf);
 1853         if (i == dpd->CurrentValue.u8)
 1854             gp_widget_set_value (*widget, buf);
 1855     }
 1856     return (GP_OK);
 1857 }
 1858 
 1859 static int
 1860 _put_Nikon_WBBiasPreset(CONFIG_PUT_ARGS) {
 1861     int ret;
 1862     char    *val;
 1863 
 1864     CR (gp_widget_get_value(widget, &val));
 1865     sscanf (val, "%u", &ret);
 1866     propval->u8 = ret;
 1867     return (GP_OK);
 1868 }
 1869 
 1870 static int
 1871 _get_Nikon_HueAdjustment(CONFIG_GET_ARGS) {
 1872     float   f, t, b, s;
 1873 
 1874     if (dpd->DataType != PTP_DTC_INT8)
 1875         return (GP_ERROR);
 1876     if (dpd->FormFlag & PTP_DPFF_Range) {
 1877         gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 1878         gp_widget_set_name (*widget,menu->name);
 1879         f = (float)dpd->CurrentValue.i8;
 1880         b = (float)dpd->FORM.Range.MinimumValue.i8;
 1881         t = (float)dpd->FORM.Range.MaximumValue.i8;
 1882         s = (float)dpd->FORM.Range.StepSize.i8;
 1883         gp_widget_set_range (*widget, b, t, s);
 1884         gp_widget_set_value (*widget, &f);
 1885         return (GP_OK);
 1886     }
 1887     if (dpd->FormFlag & PTP_DPFF_Enumeration) {
 1888         char buf[20];
 1889         int i, isset = FALSE;
 1890 
 1891         gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 1892         gp_widget_set_name (*widget,menu->name);
 1893         for (i = 0; i<dpd->FORM.Enum.NumberOfValues; i++) {
 1894 
 1895             sprintf (buf, "%d", dpd->FORM.Enum.SupportedValue[i].i8);
 1896             gp_widget_add_choice (*widget, buf);
 1897             if (dpd->FORM.Enum.SupportedValue[i].i8 == dpd->CurrentValue.i8) {
 1898                 gp_widget_set_value (*widget, buf);
 1899                 isset = TRUE;
 1900             }
 1901         }
 1902         if (!isset && (dpd->FORM.Enum.NumberOfValues > 0)) {
 1903             sprintf (buf, "%d", dpd->FORM.Enum.SupportedValue[0].i8);
 1904             gp_widget_set_value (*widget, buf);
 1905         }
 1906         return (GP_OK);
 1907     }
 1908     return (GP_ERROR);
 1909 }
 1910 
 1911 static int
 1912 _put_Nikon_HueAdjustment(CONFIG_PUT_ARGS)
 1913 {
 1914     if (dpd->FormFlag & PTP_DPFF_Range) {
 1915         float   f = 0.0;
 1916         CR (gp_widget_get_value(widget, &f));
 1917         propval->i8 = (signed char)f;
 1918         return (GP_OK);
 1919     }
 1920     if (dpd->FormFlag & PTP_DPFF_Enumeration) {
 1921         char *val;
 1922         int ival;
 1923 
 1924         CR (gp_widget_get_value(widget, &val));
 1925         sscanf (val, "%d", &ival);
 1926         propval->i8 = ival;
 1927         return (GP_OK);
 1928     }
 1929     return (GP_ERROR);
 1930 }
 1931 
 1932 static int
 1933 _get_Nikon_MovieLoopLength(CONFIG_GET_ARGS) {
 1934 
 1935     if (dpd->DataType != PTP_DTC_UINT32)
 1936         return GP_ERROR;
 1937 
 1938     if (dpd->FormFlag & PTP_DPFF_Enumeration) {
 1939         char buf[20];
 1940         int i, isset = FALSE;
 1941 
 1942         gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 1943         gp_widget_set_name (*widget,menu->name);
 1944         for (i = 0; i<dpd->FORM.Enum.NumberOfValues; i++) {
 1945 
 1946             sprintf (buf, "%d", dpd->FORM.Enum.SupportedValue[i].u32/10);
 1947             gp_widget_add_choice (*widget, buf);
 1948             if (dpd->FORM.Enum.SupportedValue[i].u32 == dpd->CurrentValue.u32) {
 1949                 gp_widget_set_value (*widget, buf);
 1950                 isset = TRUE;
 1951             }
 1952         }
 1953         if (!isset && (dpd->FORM.Enum.NumberOfValues > 0)) {
 1954             sprintf (buf, "%d", dpd->FORM.Enum.SupportedValue[0].u32/10);
 1955             gp_widget_set_value (*widget, buf);
 1956         }
 1957         return GP_OK;
 1958     }
 1959     return GP_ERROR;
 1960 }
 1961 
 1962 static int
 1963 _put_Nikon_MovieLoopLength(CONFIG_PUT_ARGS)
 1964 {
 1965     char *val;
 1966     int ival;
 1967 
 1968     CR (gp_widget_get_value(widget, &val));
 1969     sscanf (val, "%d", &ival);
 1970     propval->u32 = ival*10;
 1971     return GP_OK;
 1972 }
 1973 
 1974 
 1975 static struct deviceproptableu8 canon_quality[] = {
 1976     { N_("undefined"),  0x00, 0 },
 1977     { N_("economy"),    0x01, 0 },
 1978     { N_("normal"),     0x02, 0 },
 1979     { N_("fine"),       0x03, 0 },
 1980     { N_("lossless"),   0x04, 0 },
 1981     { N_("superfine"),  0x05, 0 },
 1982 };
 1983 GENERIC8TABLE(Canon_Quality,canon_quality)
 1984 
 1985 static struct deviceproptableu8 canon_fullview_fileformat[] = {
 1986     { N_("Undefined"),  0x00, 0 },
 1987     { N_("JPEG"),       0x01, 0 },
 1988     { N_("CRW"),        0x02, 0 },
 1989 };
 1990 GENERIC8TABLE(Canon_Capture_Format,canon_fullview_fileformat)
 1991 
 1992 static struct deviceproptableu8 canon_shootmode[] = {
 1993     { N_("Auto"),       0x01, 0 },
 1994     { N_("TV"),     0x02, 0 },
 1995     { N_("AV"),     0x03, 0 },
 1996     { N_("Manual"),     0x04, 0 },
 1997     { N_("A_DEP"),      0x05, 0 },
 1998     { N_("M_DEP"),      0x06, 0 },
 1999     { N_("Bulb"),       0x07, 0 },
 2000     /* Marcus: The SDK has more listed, but I have never seen them
 2001      * enumerated by the cameras. Lets leave them out for now. */
 2002 };
 2003 GENERIC8TABLE(Canon_ShootMode,canon_shootmode)
 2004 
 2005 static struct deviceproptableu16 canon_eos_autoexposuremode[] = {
 2006     { N_("P"),      0x0000, 0 },
 2007     { N_("TV"),     0x0001, 0 },
 2008     { N_("AV"),     0x0002, 0 },
 2009     { N_("Manual"),     0x0003, 0 },
 2010     { N_("Bulb"),       0x0004, 0 },
 2011     { N_("A_DEP"),      0x0005, 0 },
 2012     { N_("DEP"),        0x0006, 0 },
 2013     { N_("Custom"),     0x0007, 0 },
 2014     { N_("Lock"),       0x0008, 0 },
 2015     { N_("Green"),      0x0009, 0 },
 2016     { N_("Night Portrait"), 0x000a, 0 },
 2017     { N_("Sports"),     0x000b, 0 },
 2018     { N_("Portrait"),   0x000c, 0 },
 2019     { N_("Landscape"),  0x000d, 0 },
 2020     { N_("Closeup"),    0x000e, 0 },
 2021     { N_("Flash Off"),  0x000f, 0 },
 2022 
 2023     { N_("Auto"),           0x0016, 0 },    /* EOS M6 Mark 2 */
 2024     { N_("Handheld Night Scene"),   0x0017, 0 },    /* EOS M6 Mark 2 */
 2025     { N_("HDR Backlight Control"),  0x0018, 0 },    /* EOS M6 Mark 2 */
 2026     { N_("Food"),           0x001b, 0 },    /* EOS M6 Mark 2 */
 2027     { N_("Grainy B/W"),     0x001e, 0 },    /* EOS M6 Mark 2 */
 2028     { N_("Soft focus"),     0x001f, 0 },    /* EOS M6 Mark 2 */
 2029     { N_("Toy camera effect"),  0x0020, 0 },    /* EOS M6 Mark 2 */
 2030     { N_("Fish-eye effect"),    0x0021, 0 },    /* EOS M6 Mark 2 */
 2031     { N_("Water painting effect"),  0x0022, 0 },    /* EOS M6 Mark 2 */
 2032     { N_("Miniature effect"),   0x0023, 0 },    /* EOS M6 Mark 2 */
 2033     { N_("HDR art standard"),   0x0024, 0 },    /* EOS M6 Mark 2 */
 2034     { N_("HDR art vivid"),      0x0025, 0 },    /* EOS M6 Mark 2 */
 2035     { N_("HDR art bold"),       0x0026, 0 },    /* EOS M6 Mark 2 */
 2036     { N_("HDR art embossed"),   0x0027, 0 },    /* EOS M6 Mark 2 */
 2037     { N_("Panning"),        0x002d, 0 },    /* EOS M6 Mark 2 */
 2038     { N_("Self Portrait"),      0x0032, 0 },    /* EOS M6 Mark 2 */
 2039     { N_("Hybrid Auto"),        0x0033, 0 },    /* EOS M6 Mark 2 */
 2040     { N_("Smooth skin"),        0x0034, 0 },    /* EOS M6 Mark 2 */
 2041     { N_("Fv"),         0x0037, 0 },    /* EOS M6 Mark 2 */
 2042 };
 2043 GENERIC16TABLE(Canon_EOS_AutoExposureMode,canon_eos_autoexposuremode)
 2044 
 2045 static struct deviceproptableu32 canon_eos_alomode[] = {
 2046     { N_("Standard"),               0x10000, 0 },
 2047     { N_("Standard (disabled in manual exposure)"), 0x00000, 0 },
 2048     { N_("Low"),                    0x10101, 0 },
 2049     { N_("Low (disabled in manual exposure)"),  0x00101, 0 },
 2050     { N_("Off"),                    0x10303, 0 },
 2051     { N_("Off (disabled in manual exposure)"),  0x00303, 0 },
 2052     { N_("High"),                   0x10202, 0 },
 2053     { N_("High (disabled in manual exposure)"), 0x00202, 0 },
 2054     { N_("x1"), 0x1, 0 },
 2055     { N_("x2"), 0x2, 0 },
 2056     { N_("x3"), 0x3, 0 },
 2057 };
 2058 GENERIC32TABLE(Canon_EOS_AloMode,canon_eos_alomode)
 2059 
 2060 static struct deviceproptableu8 canon_flash[] = {
 2061     { N_("off"),                0, 0 },
 2062     { N_("auto"),               1, 0 },
 2063     { N_("on"),             2, 0 },
 2064     { N_("red eye suppression"),        3, 0 },
 2065     { N_("fill in"),            4, 0 },
 2066     { N_("auto + red eye suppression"), 5, 0 },
 2067     { N_("on + red eye suppression"),   6, 0 },
 2068 };
 2069 GENERIC8TABLE(Canon_FlashMode,canon_flash)
 2070 
 2071 static struct deviceproptableu8 nikon_internalflashmode[] = {
 2072     { N_("iTTL"),       0, 0 },
 2073     { N_("Manual"),     1, 0 },
 2074     { N_("Commander"),  2, 0 },
 2075     { N_("Repeating"),  3, 0 }, /* stroboskop */
 2076 };
 2077 GENERIC8TABLE(Nikon_InternalFlashMode,nikon_internalflashmode)
 2078 
 2079 static struct deviceproptableu8 nikon_flashcommandermode[] = {
 2080     { N_("TTL"),        0, 0 },
 2081     { N_("Auto Aperture"),  1, 0 },
 2082     { N_("Full Manual"),    2, 0 },
 2083 };
 2084 GENERIC8TABLE(Nikon_FlashCommanderMode,nikon_flashcommandermode)
 2085 
 2086 static struct deviceproptableu8 nikon_liveviewsize[] = {
 2087     { N_("QVGA"),       1, 0 },
 2088     { N_("VGA"),        2, 0 },
 2089     { N_("XGA"),        3, 0 },
 2090 };
 2091 GENERIC8TABLE(Nikon_LiveViewSize,nikon_liveviewsize)
 2092 
 2093 static struct deviceproptableu16 fuji_liveviewsize[] = {
 2094     { N_("XGA"),        1, 0 },
 2095     { N_("VGA"),        2, 0 },
 2096     { N_("QVGA"),       3, 0 },
 2097 };
 2098 GENERIC16TABLE(Fuji_LiveViewSize,fuji_liveviewsize)
 2099 
 2100 static struct deviceproptableu8 sony_qx_liveviewsize[] = {
 2101     { "640x480",        1, 0 },
 2102     { "1024x768",       2, 0 },
 2103     { "1920x1280",      3, 0 },
 2104 };
 2105 GENERIC8TABLE(Sony_QX_LiveViewSize,sony_qx_liveviewsize)
 2106 
 2107 static int
 2108 _get_Canon_LiveViewSize(CONFIG_GET_ARGS) {
 2109     unsigned int i;
 2110     unsigned int have = 0;
 2111     char buf[20];
 2112 
 2113     if (!(dpd->FormFlag & PTP_DPFF_Enumeration))
 2114         return GP_ERROR;
 2115     if (dpd->DataType != PTP_DTC_UINT16)
 2116         return GP_ERROR;
 2117 /* actually it is a flag value, 1 = TFT, 2 = PC, 4 = MOBILE, 8 = MOBILE2 */
 2118 
 2119     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 2120     gp_widget_set_name (*widget, menu->name);
 2121 
 2122     for (i=0;i<dpd->FORM.Enum.NumberOfValues;i++) {
 2123         if ((dpd->FORM.Enum.SupportedValue[i].u16 & 0xe) == 0x2) {
 2124             if (!(have & 0x2))
 2125                 gp_widget_add_choice (*widget, _("Large"));
 2126             have |= 0x2;
 2127             continue;
 2128         }
 2129         if ((dpd->FORM.Enum.SupportedValue[i].u16 & 0xe) == 0x4) {
 2130             if (!(have & 0x4))
 2131                 gp_widget_add_choice (*widget, _("Medium"));
 2132             have |= 0x4;
 2133             continue;
 2134         }
 2135         if ((dpd->FORM.Enum.SupportedValue[i].u16 & 0xe) == 0x8) {
 2136             if (!(have & 0x8))
 2137                 gp_widget_add_choice (*widget, _("Small"));
 2138             have |= 0x8;
 2139             continue;
 2140         }
 2141     }
 2142     if ((dpd->CurrentValue.u16 & 0xe) == 0x8) { gp_widget_set_value (*widget, _("Small")); return GP_OK; }
 2143     if ((dpd->CurrentValue.u16 & 0xe) == 0x4) { gp_widget_set_value (*widget, _("Medium")); return GP_OK; }
 2144     if ((dpd->CurrentValue.u16 & 0xe) == 0x2) { gp_widget_set_value (*widget, _("Large")); return GP_OK; }
 2145     sprintf(buf,"val %x", dpd->CurrentValue.u16);
 2146     gp_widget_set_value (*widget, buf);
 2147     return GP_OK;
 2148 }
 2149 
 2150 static int
 2151 _put_Canon_LiveViewSize(CONFIG_PUT_ARGS) {
 2152     char        *val;
 2153     unsigned int    outputval = 0;
 2154 
 2155     CR (gp_widget_get_value (widget, &val));
 2156     if (!strcmp(val,_("Large"))) { outputval = 0x2; }
 2157     if (!strcmp(val,_("Medium"))) { outputval = 0x4; }
 2158     if (!strcmp(val,_("Small"))) { outputval = 0x8; }
 2159 
 2160     if (outputval == 0)
 2161         return GP_ERROR_BAD_PARAMETERS;
 2162     /* replace the current outputsize, but keep the TFT flag */
 2163     propval->u16 = (dpd->CurrentValue.u16 & ~0xe) | outputval;
 2164     return GP_OK;
 2165 }
 2166 
 2167 static struct deviceproptableu8 nikon_flashcommanderpower[] = {
 2168     { N_("Full"),       0, 0 },
 2169     { "1/2",        1, 0 },
 2170     { "1/4",        2, 0 },
 2171     { "1/8",        3, 0 },
 2172     { "1/16",       4, 0 },
 2173     { "1/32",       5, 0 },
 2174     { "1/64",       6, 0 },
 2175     { "1/128",      7, 0 },
 2176 };
 2177 GENERIC8TABLE(Nikon_FlashCommanderPower,nikon_flashcommanderpower)
 2178 
 2179 /* 0xd1d3 */
 2180 static struct deviceproptableu8 nikon_flashcommandchannel[] = {
 2181     { "1",      0, 0 },
 2182     { "2",      1, 0 },
 2183     { "3",      2, 0 },
 2184     { "4",      3, 0 },
 2185 };
 2186 GENERIC8TABLE(Nikon_FlashCommandChannel,nikon_flashcommandchannel)
 2187 
 2188 /* 0xd1d4 */
 2189 static struct deviceproptableu8 nikon_flashcommandselfmode[] = {
 2190     { N_("TTL"),        0, 0 },
 2191     { N_("Manual"),     1, 0 },
 2192     { N_("Off"),        2, 0 },
 2193 };
 2194 GENERIC8TABLE(Nikon_FlashCommandSelfMode,nikon_flashcommandselfmode)
 2195 
 2196 /* 0xd1d5, 0xd1d8, 0xd1da */
 2197 static struct deviceproptableu8 nikon_flashcommandXcompensation[] = {
 2198     { "-3.0",       0, 0 },
 2199     { "-2.7",       1, 0 },
 2200     { "-2.3",       2, 0 },
 2201     { "-2.0",       3, 0 },
 2202     { "-1.7",       4, 0 },
 2203     { "-1.3",       5, 0 },
 2204     { "-1.0",       6, 0 },
 2205     { "-0.7",       7, 0 },
 2206     { "-0.3",       8, 0 },
 2207     { "0.0",        9, 0 },
 2208     { "0.3",        10, 0 },
 2209     { "0.7",        11, 0 },
 2210     { "1.0",        12, 0 },
 2211     { "1.3",        13, 0 },
 2212     { "1.7",        14, 0 },
 2213     { "2.0",        15, 0 },
 2214     { "2.3",        16, 0 },
 2215     { "2.7",        17, 0 },
 2216     { "3.0",        18, 0 },
 2217 };
 2218 GENERIC8TABLE(Nikon_FlashCommandXCompensation,nikon_flashcommandXcompensation)
 2219 
 2220 /* 0xd1d5, 0xd1d9, 0xd1dc */
 2221 static struct deviceproptableu8 nikon_flashcommandXvalue[] = {
 2222     { N_("Full"),       0, 0 },
 2223     { "1/1.3",      1, 0 },
 2224     { "1/1.7",      2, 0 },
 2225     { "1/2",        3, 0 },
 2226     { "1/2.5",      4, 0 },
 2227     { "1/3.2",      5, 0 },
 2228     { "1/4",        6, 0 },
 2229     { "1/5",        7, 0 },
 2230     { "1/6.4",      8, 0 },
 2231     { "1/8",        9, 0 },
 2232     { "1/10",       10, 0 },
 2233     { "1/13",       11, 0 },
 2234     { "1/16",       12, 0 },
 2235     { "1/20",       13, 0 },
 2236     { "1/25",       14, 0 },
 2237     { "1/32",       15, 0 },
 2238     { "1/40",       16, 0 },
 2239     { "1/50",       17, 0 },
 2240     { "1/64",       18, 0 },
 2241     { "1/80",       19, 0 },
 2242     { "1/100",      20, 0 },
 2243     { "1/128",      21, 0 },
 2244 };
 2245 GENERIC8TABLE(Nikon_FlashCommandXValue,nikon_flashcommandXvalue)
 2246 
 2247 
 2248 /* 0xd1d7, 0xd1da */
 2249 static struct deviceproptableu8 nikon_flashcommandXmode[] = {
 2250     { N_("TTL"),        0, 0 },
 2251     { N_("Auto Aperture"),  1, 0 },
 2252     { N_("Manual"),     2, 0 },
 2253     { N_("Off"),        3, 0 },
 2254 };
 2255 GENERIC8TABLE(Nikon_FlashCommandXMode,nikon_flashcommandXmode)
 2256 
 2257 
 2258 static struct deviceproptableu8 nikon_afmode[] = {
 2259     { N_("AF-S"),       0, 0 },
 2260     { N_("AF-C"),       1, 0 },
 2261     { N_("AF-A"),       2, 0 },
 2262     { N_("MF (fixed)"), 3, 0 },
 2263     { N_("MF (selection)"), 4, 0 },
 2264     /* more for newer */
 2265 };
 2266 GENERIC8TABLE(Nikon_AFMode,nikon_afmode)
 2267 
 2268 static struct deviceproptableu8 nikon_videomode[] = {
 2269     { N_("NTSC"),       0, 0 },
 2270     { N_("PAL"),        1, 0 },
 2271 };
 2272 GENERIC8TABLE(Nikon_VideoMode,nikon_videomode)
 2273 
 2274 static struct deviceproptableu8 flash_modemanualpower[] = {
 2275     { N_("Full"),   0x00, 0 },
 2276     { "1/2",    0x01, 0 },
 2277     { "1/4",    0x02, 0 },
 2278     { "1/8",    0x03, 0 },
 2279     { "1/16",   0x04, 0 },
 2280     { "1/32",   0x05, 0 },
 2281 };
 2282 GENERIC8TABLE(Nikon_FlashModeManualPower,flash_modemanualpower)
 2283 
 2284 static struct deviceproptableu8 canon_meteringmode[] = {
 2285     { N_("Center-weighted"),        0, 0 },
 2286     { N_("Spot"),               1, 0 },
 2287     { N_("Average"),            2, 0 },
 2288     { N_("Evaluative"),         3, 0 },
 2289     { N_("Partial"),            4, 0 },
 2290     { N_("Center-weighted average"),    5, 0 },
 2291     { N_("Spot metering interlocked with AF frame"),    6, 0 },
 2292     { N_("Multi spot"),         7, 0 },
 2293 };
 2294 GENERIC8TABLE(Canon_MeteringMode,canon_meteringmode)
 2295 
 2296 static struct deviceproptableu8 canon_eos_picturestyle[] = {
 2297     { N_("Standard"),   0x81, 0 },
 2298     { N_("Portrait"),   0x82, 0 },
 2299     { N_("Landscape"),  0x83, 0 },
 2300     { N_("Neutral"),    0x84, 0 },
 2301     { N_("Faithful"),   0x85, 0 },
 2302     { N_("Monochrome"), 0x86, 0 },
 2303     { N_("Auto"),       0x87, 0 }, /*Canon EOS 5D Mark III*/
 2304     { N_("Fine detail"),    0x88, 0 },
 2305     { N_("User defined 1"), 0x21, 0 },
 2306     { N_("User defined 2"), 0x22, 0 },
 2307     { N_("User defined 3"), 0x23, 0 },
 2308 };
 2309 GENERIC8TABLE(Canon_EOS_PictureStyle,canon_eos_picturestyle)
 2310 
 2311 static struct deviceproptableu16 canon_shutterspeed[] = {
 2312     { "auto",   0x0000,0 },
 2313     { "bulb",   0x0004,0 },
 2314     { "bulb",   0x000c,0 },
 2315     { "30",     0x0010,0 },
 2316     { "25",     0x0013,0 },
 2317     { "20.3",   0x0014,0 }, /* + 1/3 */
 2318     { "20",     0x0015,0 },
 2319     { "15",     0x0018,0 },
 2320     { "13",     0x001b,0 },
 2321     { "10",     0x001c,0 },
 2322     { "10.3",   0x001d,0 }, /* 10.4 */
 2323     { "8",      0x0020,0 },
 2324     { "6.3",    0x0023,0 }, /* + 1/3 */
 2325     { "6",      0x0024,0 },
 2326     { "5",      0x0025,0 },
 2327     { "4",      0x0028,0 },
 2328     { "3.2",    0x002b,0 },
 2329     { "3",      0x002c,0 },
 2330     { "2.5",    0x002d,0 },
 2331     { "2",      0x0030,0 },
 2332     { "1.6",    0x0033,0 },
 2333     { "1.5",    0x0034,0 },
 2334     { "1.3",    0x0035,0 },
 2335     { "1",      0x0038,0 },
 2336     { "0.8",    0x003b,0 },
 2337     { "0.7",    0x003c,0 },
 2338     { "0.6",    0x003d,0 },
 2339     { "0.5",    0x0040,0 },
 2340     { "0.4",    0x0043,0 },
 2341     { "0.3",    0x0044,0 },
 2342     { "0.3",    0x0045,0 }, /* 1/3 */
 2343     { "1/4",    0x0048,0 },
 2344     { "1/5",    0x004b,0 },
 2345     { "1/6",    0x004c,0 },
 2346     { "1/6",    0x004d,0 }, /* 1/3? */
 2347     { "1/8",    0x0050,0 },
 2348     { "1/10",   0x0053,0 }, /* 1/3? */
 2349     { "1/10",   0x0054,0 },
 2350     { "1/13",   0x0055,0 },
 2351     { "1/15",   0x0058,0 },
 2352     { "1/20",   0x005b,0 }, /* 1/3? */
 2353     { "1/20",   0x005c,0 },
 2354     { "1/25",   0x005d,0 },
 2355     { "1/30",   0x0060,0 },
 2356     { "1/40",   0x0063,0 },
 2357     { "1/45",   0x0064,0 },
 2358     { "1/50",   0x0065,0 },
 2359     { "1/60",   0x0068,0 },
 2360     { "1/80",   0x006b,0 },
 2361     { "1/90",   0x006c,0 },
 2362     { "1/100",  0x006d,0 },
 2363     { "1/125",  0x0070,0 },
 2364     { "1/160",  0x0073,0 },
 2365     { "1/180",  0x0074,0 },
 2366     { "1/200",  0x0075,0 },
 2367     { "1/250",  0x0078,0 },
 2368     { "1/320",  0x007b,0 },
 2369     { "1/350",  0x007c,0 },
 2370     { "1/400",  0x007d,0 },
 2371     { "1/500",  0x0080,0 },
 2372     { "1/640",  0x0083,0 },
 2373     { "1/750",  0x0084,0 },
 2374     { "1/800",  0x0085,0 },
 2375     { "1/1000", 0x0088,0 },
 2376     { "1/1250", 0x008b,0 },
 2377     { "1/1500", 0x008c,0 },
 2378     { "1/1600", 0x008d,0 },
 2379     { "1/2000", 0x0090,0 },
 2380     { "1/2500", 0x0093,0 },
 2381     { "1/3000", 0x0094,0 },
 2382     { "1/3200", 0x0095,0 },
 2383     { "1/4000", 0x0098,0 },
 2384     { "1/5000", 0x009b,0 },
 2385     { "1/6000", 0x009c,0 },
 2386     { "1/6400", 0x009d,0 },
 2387     { "1/8000", 0x00a0,0 },
 2388 };
 2389 GENERIC16TABLE(Canon_ShutterSpeed,canon_shutterspeed)
 2390 
 2391 
 2392 static struct deviceproptableu16 canon_focuspoints[] = {
 2393     { N_("Focusing Point on Center Only, Manual"),  0x1000, 0 },
 2394     { N_("Focusing Point on Center Only, Auto"),    0x1001, 0 },
 2395     { N_("Multiple Focusing Points (No Specification), Manual"),    0x3000, 0 },
 2396     { N_("Multiple Focusing Points, Auto"),     0x3001, 0 },
 2397     { N_("Multiple Focusing Points (Right)"),   0x3002, 0 },
 2398     { N_("Multiple Focusing Points (Center)"),  0x3003, 0 },
 2399     { N_("Multiple Focusing Points (Left)"),    0x3004, 0 },
 2400 };
 2401 GENERIC16TABLE(Canon_FocusingPoint,canon_focuspoints)
 2402 
 2403 static struct deviceproptableu8 canon_size[] = {
 2404     { N_("Large"),      0x00, 0 },
 2405     { N_("Medium 1"),   0x01, 0 },
 2406     { N_("Medium 2"),   0x03, 0 },
 2407     { N_("Medium 3"),   0x07, 0 },
 2408     { N_("Small"),      0x02, 0 },
 2409 };
 2410 GENERIC8TABLE(Canon_Size,canon_size)
 2411 
 2412 static struct deviceproptableu8 sony_size[] = {
 2413     { N_("Large"),      0x01, 0 },
 2414     { N_("Medium"),     0x02, 0 },
 2415     { N_("Small"),      0x03, 0 },
 2416 };
 2417 GENERIC8TABLE(Sony_ImageSize,sony_size)
 2418 
 2419 static struct deviceproptableu8 nikon1_size[] = {
 2420     { N_("Small"),      0x00, 0 },
 2421     { N_("Medium"),     0x01, 0 },
 2422     { N_("Large"),      0x02, 0 },
 2423 };
 2424 GENERIC8TABLE(Nikon1_ImageSize,nikon1_size)
 2425 
 2426 static struct deviceproptableu8 sony_aspectratio[] = {
 2427     { N_("3:2"),        0x01, 0 },
 2428     { N_("16:9"),       0x02, 0 },
 2429 };
 2430 GENERIC8TABLE(Sony_AspectRatio,sony_aspectratio)
 2431 
 2432 /* values are from 6D */
 2433 static struct deviceproptableu16 canon_eos_aspectratio[] = {
 2434     { "3:2",    0x0000, 0},
 2435     { "1:1",    0x0001, 0},
 2436     { "4:3",    0x0002, 0},
 2437     { "16:9",   0x0007, 0},
 2438     { "1.6x",   0x000d, 0}, /* guess , EOS R */
 2439 };
 2440 GENERIC16TABLE(Canon_EOS_AspectRatio,canon_eos_aspectratio)
 2441 
 2442 /* actually in 1/10s of a second, but only 3 values in use */
 2443 static struct deviceproptableu16 canon_selftimer[] = {
 2444     { N_("Not used"),   0,  0 },
 2445     { N_("10 seconds"), 100,    0 },
 2446     { N_("2 seconds"),  20, 0 },
 2447 };
 2448 GENERIC16TABLE(Canon_SelfTimer,canon_selftimer)
 2449 
 2450 /* actually it is a flag value, 1 = TFT, 2 = PC, 4 = MOBILE, 8 = MOBILE2 */
 2451 static struct deviceproptableu16 canon_eos_cameraoutput[] = {
 2452     { N_("Off"),        0, 0 }, /*On 5DM3, LCD/TFT is off, mirror down and optical view finder enabled */
 2453     { N_("TFT"),        1, 0 },
 2454     { N_("PC"),         2, 0 },
 2455     { N_("TFT + PC"),   3, 0 },
 2456     { N_("MOBILE"),     4, 0 },
 2457     { N_("TFT + MOBILE"),   5, 0 },
 2458     { N_("PC + MOBILE"),    6, 0 },
 2459     { N_("TFT + PC + MOBILE"), 7, 0 },
 2460     { N_("MOBILE2"),    8, 0 },
 2461     { N_("TFT + MOBILE2"),  9, 0 },
 2462     { N_("PC + MOBILE2"),   10, 0 },
 2463     { N_("TFT + PC + MOBILE2"), 11, 0 },
 2464 };
 2465 GENERIC16TABLE(Canon_EOS_CameraOutput,canon_eos_cameraoutput)
 2466 
 2467 static struct deviceproptableu16 canon_eos_evfrecordtarget[] = {
 2468     { N_("None"),       0, 0 },
 2469     { N_("SDRAM"),      3, 0 },
 2470     { N_("Card"),       4, 0 },
 2471 };
 2472 GENERIC16TABLE(Canon_EOS_EVFRecordTarget,canon_eos_evfrecordtarget)
 2473 
 2474 /* values currently unknown */
 2475 static struct deviceproptableu16 canon_eos_evfmode[] = {
 2476     { "0",  0, 0 },
 2477     { "1",  1, 0 },
 2478 };
 2479 GENERIC16TABLE(Canon_EOS_EVFMode,canon_eos_evfmode)
 2480 
 2481 #if 0 /* reimplement with viewfinder on/off below */
 2482 static struct deviceproptableu8 canon_cameraoutput[] = {
 2483     { N_("Undefined"),  0, 0 },
 2484     { N_("LCD"),        1, 0 },
 2485     { N_("Video OUT"),  2, 0 },
 2486     { N_("Off"),        3, 0 },
 2487 };
 2488 GENERIC8TABLE(Canon_CameraOutput,canon_cameraoutput)
 2489 #endif
 2490 
 2491 static int
 2492 _get_Canon_CameraOutput(CONFIG_GET_ARGS) {
 2493     int i,isset=0;
 2494     char buf[30];
 2495 
 2496     if (!(dpd->FormFlag & PTP_DPFF_Enumeration))
 2497         return (GP_ERROR);
 2498     if (dpd->DataType != PTP_DTC_UINT8)
 2499         return (GP_ERROR);
 2500 
 2501     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 2502     gp_widget_set_name (*widget, menu->name);
 2503     for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 2504         char *x;
 2505 
 2506         switch (dpd->FORM.Enum.SupportedValue[i].u8) {
 2507         default:sprintf(buf,_("Unknown %d"),dpd->FORM.Enum.SupportedValue[i].u8);
 2508             x=buf;
 2509             break;
 2510         case 1: x=_("LCD");break;
 2511         case 2: x=_("Video OUT");break;
 2512         case 3: x=_("Off");break;
 2513         }
 2514         gp_widget_add_choice (*widget,x);
 2515         if (dpd->FORM.Enum.SupportedValue[i].u8 == dpd->CurrentValue.u8) {
 2516             gp_widget_set_value (*widget,x);
 2517             isset = 1;
 2518         }
 2519     }
 2520     if (!isset) {
 2521         sprintf(buf,_("Unknown %d"),dpd->CurrentValue.u8);
 2522         gp_widget_set_value (*widget,buf);
 2523     }
 2524     return GP_OK;
 2525 }
 2526 
 2527 static int
 2528 _put_Canon_CameraOutput(CONFIG_PUT_ARGS) {
 2529     int u, i;
 2530     char    *value;
 2531     PTPParams *params = &camera->pl->params;
 2532 
 2533     CR (gp_widget_get_value(widget, &value));
 2534 
 2535     u = -1;
 2536     if (!strcmp(value,_("LCD"))) { u = 1; }
 2537     if (!strcmp(value,_("Video OUT"))) { u = 2; }
 2538     if (!strcmp(value,_("Off"))) { u = 3; }
 2539     if (sscanf(value,_("Unknown %d"),&i)) { u = i; }
 2540     C_PARAMS (u != -1);
 2541 
 2542     if ((u==1) || (u==2)) {
 2543         if (ptp_operation_issupported(params, PTP_OC_CANON_ViewfinderOn)) {
 2544             if (!params->canon_viewfinder_on)  {
 2545                 if (LOG_ON_PTP_E (ptp_canon_viewfinderon (params)) == PTP_RC_OK)
 2546                     params->canon_viewfinder_on=1;
 2547             }
 2548         }
 2549     }
 2550     if (u==3) {
 2551         if (ptp_operation_issupported(params, PTP_OC_CANON_ViewfinderOff)) {
 2552             if (params->canon_viewfinder_on)  {
 2553                 if (LOG_ON_PTP_E (ptp_canon_viewfinderoff (params)) == PTP_RC_OK)
 2554                     params->canon_viewfinder_on=0;
 2555             }
 2556         }
 2557     }
 2558     propval->u8 = u;
 2559     return GP_OK;
 2560 }
 2561 
 2562 static struct deviceproptableu16 canon_isospeed[] = {
 2563     { N_("Factory Default"),0xffff, 0 },
 2564     { "6",          0x0028, 0 },
 2565     { "12",         0x0030, 0 },
 2566     { "25",         0x0038, 0 },
 2567     { "50",         0x0040, 0 },
 2568     { "64",         0x0043, 0 },
 2569     { "80",         0x0045, 0 },
 2570     { "100",        0x0048, 0 },
 2571     { "125",        0x004b, 0 },
 2572     { "160",        0x004d, 0 },
 2573     { "200",        0x0050, 0 },
 2574     { "250",        0x0053, 0 },
 2575     { "320",        0x0055, 0 },
 2576     { "400",        0x0058, 0 },
 2577     { "500",        0x005b, 0 },
 2578     { "640",        0x005d, 0 },
 2579     { "800",        0x0060, 0 },
 2580     { "1000",       0x0063, 0 },
 2581     { "1250",       0x0065, 0 },
 2582     { "1600",       0x0068, 0 },
 2583     { "2000",       0x006b, 0 },
 2584     { "2500",       0x006d, 0 },
 2585     { "3200",       0x0070, 0 },
 2586     { "4000",       0x0073, 0 },
 2587     { "5000",       0x0075, 0 },
 2588     { "6400",       0x0078, 0 },
 2589     { "8000",       0x007b, 0 },
 2590     { "10000",      0x007d, 0 },
 2591     { "12800",      0x0080, 0 },
 2592     { "16000",      0x0083, 0 },
 2593     { "20000",      0x0085, 0 },
 2594     { "25600",      0x0088, 0 },
 2595     { "32000",      0x008b, 0 },
 2596     { "40000",      0x008d, 0 },
 2597     { "51200",      0x0090, 0 },
 2598     { "102400",     0x0098, 0 },
 2599     { "204800",     0x00a0, 0 },
 2600     { "409600",     0x00a8, 0 },
 2601     { "819200",     0x00b0, 0 },
 2602     { N_("Auto"),       0x0000, 0 },
 2603 };
 2604 GENERIC16TABLE(Canon_ISO,canon_isospeed)
 2605 
 2606 /* see ptp-pack.c:ptp_unpack_EOS_ImageFormat */
 2607 static struct deviceproptableu16 canon_eos_image_format[] = {
 2608     { N_("RAW"),                0x0c00, 0 },
 2609     { N_("mRAW"),               0x1c00, 0 },
 2610     { N_("sRAW"),               0x2c00, 0 },
 2611     { N_("cRAW"),               0x0b00, 0 },
 2612     { N_("Large Fine JPEG"),        0x0300, 0 },
 2613     { N_("Large Normal JPEG"),      0x0200, 0 },
 2614     { N_("Medium Fine JPEG"),       0x1300, 0 },
 2615     { N_("Medium Normal JPEG"),     0x1200, 0 },
 2616     { N_("Small Fine JPEG"),        0x2300, 0 },
 2617     { N_("Small Normal JPEG"),      0x2200, 0 },
 2618     { N_("Small Fine JPEG"),        0xd300, 0 },
 2619     { N_("Small Normal JPEG"),      0xd200, 0 },
 2620     { N_("Smaller JPEG"),           0xe300, 0 },
 2621     { N_("Tiny JPEG"),          0xf300, 0 },
 2622     { N_("RAW + Large Fine JPEG"),      0x0c03, 0 },
 2623     { N_("mRAW + Large Fine JPEG"),     0x1c03, 0 },
 2624     { N_("sRAW + Large Fine JPEG"),     0x2c03, 0 },
 2625     { N_("cRAW + Large Fine JPEG"),     0x0b03, 0 },
 2626     { N_("RAW + Medium Fine JPEG"),     0x0c13, 0 },
 2627     { N_("mRAW + Medium Fine JPEG"),    0x1c13, 0 },
 2628     { N_("sRAW + Medium Fine JPEG"),    0x2c13, 0 },
 2629     { N_("cRAW + Medium Fine JPEG"),    0x0b13, 0 },
 2630     { N_("RAW + Small Fine JPEG"),      0x0c23, 0 },
 2631     { N_("RAW + Small Fine JPEG"),      0x0cd3, 0 }, /*Canon EOS 5D Mark III*/
 2632     { N_("mRAW + Small Fine JPEG"),     0x1c23, 0 },
 2633     { N_("mRAW + Small Fine JPEG"),     0x1cd3, 0 }, /*Canon EOS 5D Mark III*/
 2634     { N_("sRAW + Small Fine JPEG"),     0x2c23, 0 },
 2635     { N_("sRAW + Small Fine JPEG"),     0x2cd3, 0 }, /*Canon EOS 5D Mark III*/
 2636     { N_("cRAW + Small Fine JPEG"),     0x0bd3, 0 },
 2637     { N_("RAW + Large Normal JPEG"),    0x0c02, 0 },
 2638     { N_("mRAW + Large Normal JPEG"),   0x1c02, 0 },
 2639     { N_("sRAW + Large Normal JPEG"),   0x2c02, 0 },
 2640     { N_("cRAW + Large Normal JPEG"),   0x0b02, 0 },
 2641     { N_("RAW + Medium Normal JPEG"),   0x0c12, 0 },
 2642     { N_("mRAW + Medium Normal JPEG"),  0x1c12, 0 },
 2643     { N_("sRAW + Medium Normal JPEG"),  0x2c12, 0 },
 2644     { N_("cRAW + Medium Normal JPEG"),  0x0b12, 0 },
 2645     { N_("RAW + Small Normal JPEG"),    0x0c22, 0 },
 2646     { N_("RAW + Small Normal JPEG"),    0x0cd2, 0 }, /*Canon EOS 5D Mark III*/
 2647     { N_("mRAW + Small Normal JPEG"),   0x1c22, 0 },
 2648     { N_("mRAW + Small Normal JPEG"),   0x1cd2, 0 }, /*Canon EOS 5D Mark III*/
 2649     { N_("sRAW + Small Normal JPEG"),   0x2c22, 0 },
 2650     { N_("sRAW + Small Normal JPEG"),   0x2cd2, 0 }, /*Canon EOS 5D Mark III*/
 2651     { N_("cRAW + Small Normal JPEG"),   0x0bd2, 0 },
 2652     { N_("RAW + Smaller JPEG"),     0x0ce3, 0 }, /*Canon EOS 5D Mark III*/
 2653     { N_("mRAW + Smaller JPEG"),        0x1ce3, 0 }, /*Canon EOS 5D Mark III*/
 2654     { N_("sRAW + Smaller JPEG"),        0x2ce3, 0 }, /*Canon EOS 5D Mark III*/
 2655     { N_("cRAW + Smaller JPEG"),        0x0be3, 0 }, /*Canon EOS M50*/
 2656     { N_("RAW + Tiny JPEG"),        0x0cf3, 0 }, /*Canon EOS 5D Mark III*/
 2657     { N_("mRAW + Tiny JPEG"),       0x1cf3, 0 }, /*Canon EOS 5D Mark III*/
 2658     { N_("sRAW + Tiny JPEG"),       0x2cf3, 0 }, /*Canon EOS 5D Mark III*/
 2659     /* There are more RAW + 'smallish' JPEG combinations for at least the 5DM3 possible.
 2660        Axel was simply to lazy to exercise the combinatorial explosion. :-/ */
 2661 };
 2662 GENERIC16TABLE(Canon_EOS_ImageFormat,canon_eos_image_format)
 2663 
 2664 static struct deviceproptableu16 canon_eos_aeb[] = {
 2665     { N_("off"),        0x0000, 0 },
 2666     { "+/- 1/3",        0x0003, 0 },
 2667     { "+/- 1/2",        0x0004, 0 },
 2668     { "+/- 2/3",        0x0005, 0 },
 2669     { "+/- 1",      0x0008, 0 },
 2670     { "+/- 1 1/3",      0x000b, 0 },
 2671     { "+/- 1 1/2",      0x000c, 0 },
 2672     { "+/- 1 2/3",      0x000d, 0 },
 2673     { "+/- 2",      0x0010, 0 },
 2674     { "+/- 2 1/3",      0x0013, 0 },
 2675     { "+/- 2 1/2",      0x0014, 0 },
 2676     { "+/- 2 2/3",      0x0015, 0 },
 2677     { "+/- 3",      0x0018, 0 },
 2678 };
 2679 GENERIC16TABLE(Canon_EOS_AEB,canon_eos_aeb)
 2680 
 2681 static struct deviceproptableu16 canon_eos_drive_mode[] = {
 2682     { N_("Single"),         0x0000, 0 },
 2683     { N_("Continuous"),     0x0001, 0 },
 2684     { N_("Video"),          0x0002, 0 },
 2685     { N_("Continuous high speed"),  0x0004, 0 },
 2686     { N_("Continuous low speed"),   0x0005, 0 },
 2687     { N_("Single: Silent shooting"),0x0006, 0 },
 2688     { N_("Continuous timer"),   0x0007, 0 },
 2689     { N_("Timer 10 sec"),       0x0010, 0 },
 2690     { N_("Timer 2 sec"),        0x0011, 0 },
 2691     { N_("Super high speed continuous shooting"),       0x0012, 0 },
 2692     { N_("Single silent"),      0x0013, 0 },
 2693     { N_("Continuous silent"),  0x0014, 0 },
 2694     { N_("Silent HS continuous"),   0x0015, 0 },
 2695     { N_("Silent LS continuous"),   0x0016, 0 },
 2696 };
 2697 GENERIC16TABLE(Canon_EOS_DriveMode,canon_eos_drive_mode)
 2698 
 2699 static int
 2700 _get_Olympus_ISO(CONFIG_GET_ARGS) {
 2701     int i;
 2702 
 2703     if (!(dpd->FormFlag & PTP_DPFF_Enumeration))
 2704         return GP_ERROR;
 2705     if (dpd->DataType != PTP_DTC_UINT16)
 2706         return GP_ERROR;
 2707 
 2708     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 2709     gp_widget_set_name (*widget, menu->name);
 2710     for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 2711         char    buf[20];
 2712 
 2713         sprintf(buf,"%d",dpd->FORM.Enum.SupportedValue[i].u16);
 2714         if (dpd->FORM.Enum.SupportedValue[i].u16 == 0xffff) { strcpy(buf,_("Auto")); }
 2715         if (dpd->FORM.Enum.SupportedValue[i].u16 == 0xfffd) { strcpy(buf,_("Low")); }
 2716         gp_widget_add_choice (*widget,buf);
 2717         if (dpd->FORM.Enum.SupportedValue[i].u16 == dpd->CurrentValue.u16)
 2718             gp_widget_set_value (*widget,buf);
 2719     }
 2720     return GP_OK;
 2721 }
 2722 
 2723 static int
 2724 _put_Olympus_ISO(CONFIG_PUT_ARGS)
 2725 {
 2726     char *value;
 2727     unsigned int    u;
 2728 
 2729     CR (gp_widget_get_value(widget, &value));
 2730     if (!strcmp(value,_("Auto"))) {
 2731         propval->u16 = 0xffff;
 2732         return GP_OK;
 2733     }
 2734     if (!strcmp(value,_("Low"))) {
 2735         propval->u16 = 0xfffd;
 2736         return GP_OK;
 2737     }
 2738 
 2739     if (sscanf(value, "%ud", &u)) {
 2740         propval->u16 = u;
 2741         return GP_OK;
 2742     }
 2743     return GP_ERROR;
 2744 }
 2745 
 2746 static int
 2747 _get_Olympus_OMD_Bulb(CONFIG_GET_ARGS) {
 2748     int val;
 2749 
 2750     gp_widget_new (GP_WIDGET_TOGGLE, _(menu->label), widget);
 2751     gp_widget_set_name (*widget,menu->name);
 2752     val = 2; /* always changed */
 2753     gp_widget_set_value  (*widget, &val);
 2754     return (GP_OK);
 2755 }
 2756 
 2757 static int
 2758 _put_Olympus_OMD_Bulb(CONFIG_PUT_ARGS)
 2759 {
 2760     PTPParams *params = &(camera->pl->params);
 2761     int val;
 2762     GPContext *context = ((PTPData *) params->data)->context;
 2763 
 2764     CR (gp_widget_get_value(widget, &val));
 2765     if (val) {
 2766         int ret = ptp_olympus_omd_bulbstart (params);
 2767         if (ret == PTP_RC_GeneralError) {
 2768             gp_context_error (((PTPData *) camera->pl->params.data)->context,
 2769             _("For bulb capture to work, make sure the mode dial is switched to 'M' and set 'shutterspeed' to 'bulb'."));
 2770             return translate_ptp_result (ret);
 2771         }
 2772         C_PTP_REP (ret);
 2773     } else {
 2774         C_PTP_REP (ptp_olympus_omd_bulbend (params));
 2775     }
 2776     return GP_OK;
 2777 }
 2778 
 2779 static struct deviceproptableu16 fuji_action[] = {
 2780     { N_("Shoot"),          0x0304, 0 },
 2781     { N_("Bulb On"),        0x0500, 0 },
 2782     { N_("Bulb Off"),       0x000c, 0 },
 2783     { N_("AF"),         0x0200, 0 },
 2784     { N_("Cancel AF"),      0x0004, 0 },
 2785 /* D208 is some kind of control, likely bitmasked. reported like an enum.
 2786  * 0x200 seems to mean focusing?
 2787  * 0x208 capture?
 2788  * camera starts with 0x304
 2789  *
 2790  * After setting usually it does "initiatecapture" to trigger this mode operation.
 2791  *
 2792  * xt2:    0x104,0x200,0x4,0x304,0x500,0xc,0xa000,6,0x9000,2,0x9100,1,0x9300,5
 2793  * xt3:    0x104,0x200,0x4,0x304,0x500,0xc,0xa000,6,0x9000,2,0x9100,1,0x9200,0x40,0x9300,5,0x804,0x80
 2794  * xt30:   0x104,0x200,0x4,0x304,0x500,0xc,0xa000,6,0x9000,2,0x9100,1,0x9200,0x40,0x9300,5
 2795  * xt4:    0x104,0x200,0x4,0x304,0x500,0xc,0x8000,0xa000,6,0x9000,2,0x9100,1,0x9300,5,0xe,0x9200,0x40,0x804,0x80
 2796  * xh1:    0x104,0x200,0x4,0x304,0x500,0xc,0xa000,6,0x9000,2,0x9100,1,0x9300,5
 2797  * gfx100: 0x104,0x200,0x4,0x304,0x500,0xc,0x8000,0xa000,6,0x9000,2,0x9100,1,0x9300,5,0xe,0x9200
 2798  * gfx50r: 0x104,0x200,0x4,0x304,0x500,0xc,0xa000,6,0x9000,2,0x9100,1,0x9300,5,0xe
 2799  * xpro2:  0x104,0x200,0x4,0x304,0x500,0xc,0xa000,6,0x9000,2,0x9100,1
 2800  *
 2801  * 0x304 is for regular capture         SDK_ShootS2toS0 (default) (SDK_Shoot)
 2802  * 0x200 seems for autofocus (s1?)      SDK_ShootS1
 2803  * 0x500 start bulb? 0xc end bulb?      SDK_StartBulb
 2804  * 0xc                                  SDK_EndBulb
 2805  * 0x600                                SDK_1PushAF
 2806  * 0x4                                  SDK_CancelS1
 2807  * 0x300                                SDK_ShootS2
 2808  * 0x8000 migh be autowhitebalance
 2809  * working bulb transition (with autofocus):
 2810  *  0x200 -> wait for d209 turn from 1 to 2 -> 0x500 -> wait BULBTIME seconds -> 0xc
 2811  * seen in fuji webcam traces:
 2812  *  0x9300 -> wait for d209 turn from 1 to 2 -> 0x0005
 2813  *  0x9000 -> ? not sure, was polling with d212 ?  -> 0x0002
 2814  */
 2815 };
 2816 GENERIC16TABLE(Fuji_Action,fuji_action)
 2817 
 2818 static int
 2819 _get_Fuji_AFDrive(CONFIG_GET_ARGS) {
 2820     int val;
 2821 
 2822     gp_widget_new (GP_WIDGET_TOGGLE, _(menu->label), widget);
 2823     gp_widget_set_name (*widget,menu->name);
 2824     val = 2; /* always changed */
 2825     gp_widget_set_value  (*widget, &val);
 2826     return GP_OK;
 2827 }
 2828 
 2829 static int
 2830 _put_Fuji_AFDrive(CONFIG_PUT_ARGS)
 2831 {
 2832     PTPParams       *params = &(camera->pl->params);
 2833     GPContext       *context = ((PTPData *) params->data)->context;
 2834     PTPPropertyValue    pval;
 2835 
 2836     /* Focusing first ... */
 2837     pval.u16 = 0x9300;
 2838     C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &pval, PTP_DTC_UINT16));
 2839     C_PTP_REP (ptp_initiatecapture(params, 0x00000000, 0x00000000));
 2840 
 2841     /* poll camera until it is ready */
 2842     pval.u16 = 0x0001;
 2843     while (pval.u16 == 0x0001) {
 2844         C_PTP (ptp_getdevicepropvalue (params, PTP_DPC_FUJI_AFStatus, &pval, PTP_DTC_UINT16));
 2845         GP_LOG_D ("XXX Ready to shoot? %X", pval.u16);
 2846     }
 2847 
 2848     /* 2 - means OK apparently, 3 - means failed and initiatecapture will get busy. */
 2849     if (pval.u16 == 3) { /* reported on out of focus */
 2850         gp_context_error (context, _("Fuji Capture failed: Perhaps no auto-focus?"));
 2851         return GP_ERROR;
 2852     }
 2853 
 2854     /* release focus lock */
 2855 
 2856     pval.u16 = 0x0005;
 2857     C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &pval, PTP_DTC_UINT16));
 2858     C_PTP_REP (ptp_initiatecapture(params, 0x00000000, 0x00000000));
 2859     return GP_OK;
 2860 }
 2861 
 2862 static int
 2863 _get_Fuji_Bulb(CONFIG_GET_ARGS) {
 2864     int val;
 2865 
 2866     gp_widget_new (GP_WIDGET_TOGGLE, _(menu->label), widget);
 2867     gp_widget_set_name (*widget,menu->name);
 2868     val = 2; /* always changed */
 2869     gp_widget_set_value  (*widget, &val);
 2870     return GP_OK;
 2871 }
 2872 
 2873 static int
 2874 _put_Fuji_Bulb(CONFIG_PUT_ARGS)
 2875 {
 2876     PTPParams       *params = &(camera->pl->params);
 2877     int         val;
 2878     GPContext       *context = ((PTPData *) params->data)->context;
 2879     PTPPropertyValue    pval;
 2880 
 2881     CR (gp_widget_get_value(widget, &val));
 2882     if (val) {
 2883         /* Focusing first ... */
 2884         pval.u16 = 0x0200;
 2885         C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &pval, PTP_DTC_UINT16));
 2886         C_PTP_REP (ptp_initiatecapture(params, 0x00000000, 0x00000000));
 2887 
 2888         /* poll camera until it is ready */
 2889         pval.u16 = 0x0001;
 2890         while (pval.u16 == 0x0001) {
 2891             C_PTP (ptp_getdevicepropvalue (params, PTP_DPC_FUJI_AFStatus, &pval, PTP_DTC_UINT16));
 2892             GP_LOG_D ("XXX Ready to shoot? %X", pval.u16);
 2893         }
 2894 
 2895         /* 2 - means OK apparently, 3 - means failed and initiatecapture will get busy. */
 2896         if (pval.u16 == 3) { /* reported on out of focus */
 2897             gp_context_error (context, _("Fuji Capture failed: Perhaps no auto-focus?"));
 2898             return GP_ERROR;
 2899         }
 2900 
 2901         /* now start bulb capture */
 2902         pval.u16 = 0x0500;
 2903         C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &pval, PTP_DTC_UINT16));
 2904 
 2905         C_PTP_REP (ptp_initiatecapture(params, 0x00000000, 0x00000000));
 2906     } else {
 2907         pval.u16 = 0x000c;
 2908         C_PTP_REP (ptp_setdevicepropvalue (params, 0xd208, &pval, PTP_DTC_UINT16));
 2909 
 2910         C_PTP_REP (ptp_initiatecapture(params, 0x00000000, 0x00000000));
 2911     }
 2912     return GP_OK;
 2913 }
 2914 
 2915 static int
 2916 _get_Sony_ISO(CONFIG_GET_ARGS) {
 2917     int i,isset=0;
 2918     char    buf[50];
 2919 
 2920     if (!(dpd->FormFlag & PTP_DPFF_Enumeration))
 2921         return GP_ERROR;
 2922     if (dpd->DataType != PTP_DTC_UINT32)
 2923         return GP_ERROR;
 2924 
 2925     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 2926     gp_widget_set_name (*widget, menu->name);
 2927 
 2928     for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 2929         if (dpd->FORM.Enum.SupportedValue[i].u32 == 0x00ffffffU) {
 2930             sprintf(buf,_("Auto ISO"));
 2931         } else if (dpd->FORM.Enum.SupportedValue[i].u32 == 0x01ffffffU) {
 2932             sprintf(buf,_("Auto ISO Multi Frame Noise Reduction"));
 2933         } else {
 2934             if (dpd->FORM.Enum.SupportedValue[i].u32 & 0xff000000) {
 2935                 sprintf(buf,_("%d Multi Frame Noise Reduction"),dpd->FORM.Enum.SupportedValue[i].u32 & 0xffff);
 2936             } else {
 2937                 sprintf(buf,"%d",dpd->FORM.Enum.SupportedValue[i].u32);
 2938             }
 2939         }
 2940         gp_widget_add_choice (*widget,buf);
 2941         if (dpd->FORM.Enum.SupportedValue[i].u32 == dpd->CurrentValue.u32) {
 2942             isset=1;
 2943             gp_widget_set_value (*widget,buf);
 2944         }
 2945     }
 2946     if (!isset) {
 2947         if (dpd->CurrentValue.u32 == 0x00ffffffU)
 2948             sprintf(buf,_("Auto ISO"));
 2949         else if (dpd->CurrentValue.u32 == 0x01ffffffU)
 2950             sprintf(buf,_("Auto ISO Multi Frame Noise Reduction"));
 2951         else {
 2952             if (dpd->CurrentValue.u32 & 0xff000000) {
 2953                 sprintf(buf,_("%d Multi Frame Noise Reduction"),dpd->CurrentValue.u32 & 0xffff);
 2954             } else {
 2955                 sprintf(buf,"%d",dpd->CurrentValue.u32);
 2956             }
 2957         }
 2958         gp_widget_set_value (*widget,buf);
 2959     }
 2960     return GP_OK;
 2961 }
 2962 
 2963 /* old method, using stepping */
 2964 static int
 2965 _put_Sony_ISO(CONFIG_PUT_ARGS)
 2966 {
 2967     char        *value;
 2968     uint32_t    u;
 2969     PTPParams   *params = &(camera->pl->params);
 2970 
 2971     CR (gp_widget_get_value(widget, &value));
 2972     if (!strcmp(value,_("Auto ISO"))) {
 2973         u = 0x00ffffff;
 2974         goto setiso;
 2975     }
 2976     if (!strcmp(value,_("Auto ISO Multi Frame Noise Reduction"))) {
 2977         u = 0x01ffffff;
 2978         goto setiso;
 2979     }
 2980 
 2981     if (!sscanf(value, "%ud", &u))
 2982         return GP_ERROR;
 2983 
 2984     if (strstr(value,_("Multi Frame Noise Reduction")))
 2985         u |= 0x1000000;
 2986 
 2987 setiso:
 2988     propval->u32 = u;
 2989 
 2990     return _put_sony_value_u32(params, dpd->DevicePropertyCode, u, 1);
 2991 }
 2992 
 2993 /* new method, can just set the value via setcontroldevicea */
 2994 static int
 2995 _put_Sony_ISO2(CONFIG_PUT_ARGS)
 2996 {
 2997     char        *value;
 2998     uint32_t    u;
 2999     PTPParams   *params = &(camera->pl->params);
 3000 
 3001     CR (gp_widget_get_value(widget, &value));
 3002     if (!strcmp(value,_("Auto ISO"))) {
 3003         u = 0x00ffffff;
 3004         goto setiso;
 3005     }
 3006     if (!strcmp(value,_("Auto ISO Multi Frame Noise Reduction"))) {
 3007         u = 0x01ffffff;
 3008         goto setiso;
 3009     }
 3010 
 3011     if (!sscanf(value, "%ud", &u))
 3012         return GP_ERROR;
 3013 
 3014     if (strstr(value,_("Multi Frame Noise Reduction")))
 3015         u |= 0x1000000;
 3016 
 3017 setiso:
 3018     propval->u32 = u;
 3019 
 3020     return translate_ptp_result (ptp_sony_setdevicecontrolvaluea(params, dpd->DevicePropertyCode, propval, PTP_DTC_UINT32));
 3021 }
 3022 
 3023 static int
 3024 _put_Sony_QX_ISO(CONFIG_PUT_ARGS)
 3025 {
 3026     char        *value;
 3027     uint32_t    u;
 3028 
 3029     CR (gp_widget_get_value(widget, &value));
 3030     if (!strcmp(value,_("Auto ISO"))) {
 3031         u = 0x00ffffff;
 3032         goto setiso;
 3033     }
 3034     if (!strcmp(value,_("Auto ISO Multi Frame Noise Reduction"))) {
 3035         u = 0x01ffffff;
 3036         goto setiso;
 3037     }
 3038 
 3039     if (!sscanf(value, "%ud", &u))
 3040         return GP_ERROR;
 3041 
 3042     if (strstr(value,_("Multi Frame Noise Reduction")))
 3043         u |= 0x1000000;
 3044 
 3045 setiso:
 3046     propval->u32 = u;
 3047 
 3048     /*return translate_ptp_result (ptp_sony_qx_setdevicecontrolvaluea(params, dpd->DevicePropertyCode, propval, PTP_DTC_UINT32));*/
 3049 
 3050     return GP_OK; /* will be set by generic code */
 3051 }
 3052 
 3053 
 3054 static int
 3055 _get_Olympus_AspectRatio(CONFIG_GET_ARGS) {
 3056     int i;
 3057 
 3058     if (!(dpd->FormFlag & PTP_DPFF_Enumeration))
 3059         return GP_ERROR;
 3060     if (dpd->DataType != PTP_DTC_UINT32)
 3061         return GP_ERROR;
 3062 
 3063     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 3064     gp_widget_set_name (*widget, menu->name);
 3065     for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3066         char    buf[20];
 3067 
 3068         sprintf(buf,"%d:%d",(dpd->FORM.Enum.SupportedValue[i].u32 >> 16), dpd->FORM.Enum.SupportedValue[i].u32 & 0xffff);
 3069         gp_widget_add_choice (*widget,buf);
 3070         if (dpd->FORM.Enum.SupportedValue[i].u32 == dpd->CurrentValue.u32)
 3071             gp_widget_set_value (*widget,buf);
 3072     }
 3073     return GP_OK;
 3074 }
 3075 
 3076 static int
 3077 _put_Olympus_AspectRatio(CONFIG_PUT_ARGS)
 3078 {
 3079     char        *value;
 3080     unsigned int    x,y;
 3081 
 3082     CR (gp_widget_get_value(widget, &value));
 3083 
 3084     if (2 == sscanf(value, "%d:%d", &x, &y)) {
 3085         propval->u32 = (x<<16) | y;
 3086         return GP_OK;
 3087     }
 3088     return GP_ERROR;
 3089 }
 3090 
 3091 
 3092 static int
 3093 _get_Milliseconds(CONFIG_GET_ARGS) {
 3094     unsigned int i, min, max;
 3095 
 3096     if (!(dpd->FormFlag & (PTP_DPFF_Range|PTP_DPFF_Enumeration)))
 3097         return (GP_ERROR);
 3098     if ((dpd->DataType != PTP_DTC_UINT32) && (dpd->DataType != PTP_DTC_UINT16))
 3099         return (GP_ERROR);
 3100     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 3101     gp_widget_set_name (*widget, menu->name);
 3102     if (dpd->FormFlag & PTP_DPFF_Enumeration) {
 3103         unsigned int t;
 3104 
 3105         if (dpd->DataType == PTP_DTC_UINT32)
 3106             t = dpd->CurrentValue.u32;
 3107         else
 3108             t = dpd->CurrentValue.u16;
 3109         for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3110             char    buf[20];
 3111             unsigned int x;
 3112 
 3113             if (dpd->DataType == PTP_DTC_UINT32)
 3114                 x = dpd->FORM.Enum.SupportedValue[i].u32;
 3115             else
 3116                 x = dpd->FORM.Enum.SupportedValue[i].u16;
 3117 
 3118             sprintf(buf,"%0.3fs",x/1000.0);
 3119             gp_widget_add_choice (*widget,buf);
 3120             if (x == t)
 3121                 gp_widget_set_value (*widget,buf);
 3122         }
 3123     }
 3124     if (dpd->FormFlag & PTP_DPFF_Range) {
 3125         unsigned int s;
 3126 
 3127         if (dpd->DataType == PTP_DTC_UINT32) {
 3128             min = dpd->FORM.Range.MinimumValue.u32;
 3129             max = dpd->FORM.Range.MaximumValue.u32;
 3130             s = dpd->FORM.Range.StepSize.u32;
 3131         } else {
 3132             min = dpd->FORM.Range.MinimumValue.u16;
 3133             max = dpd->FORM.Range.MaximumValue.u16;
 3134             s = dpd->FORM.Range.StepSize.u16;
 3135         }
 3136         for (i=min; i<=max; i+=s) {
 3137             char buf[20];
 3138 
 3139             sprintf (buf, "%0.3fs", i/1000.0);
 3140             CR (gp_widget_add_choice (*widget, buf));
 3141             if (    ((dpd->DataType == PTP_DTC_UINT32) && (dpd->CurrentValue.u32 == i)) ||
 3142                 ((dpd->DataType == PTP_DTC_UINT16) && (dpd->CurrentValue.u16 == i))
 3143                )
 3144                 CR (gp_widget_set_value (*widget, buf));
 3145 
 3146             /* device might report stepsize 0. but we do at least 1 round */
 3147             if (s == 0)
 3148                 break;
 3149         }
 3150 
 3151     }
 3152     return GP_OK;
 3153 }
 3154 
 3155 static int
 3156 _put_Milliseconds(CONFIG_PUT_ARGS)
 3157 {
 3158     char *value;
 3159     float   f;
 3160 
 3161     CR (gp_widget_get_value(widget, &value));
 3162 
 3163     if (sscanf(value, "%f", &f)) {
 3164         if (dpd->DataType == PTP_DTC_UINT32)
 3165             propval->u32 = f*1000;
 3166         else
 3167             propval->u16 = f*1000;
 3168         return GP_OK;
 3169     }
 3170     return GP_ERROR;
 3171 }
 3172 
 3173 static int
 3174 _get_FNumber(CONFIG_GET_ARGS) {
 3175     int i;
 3176 
 3177     GP_LOG_D ("get_FNumber");
 3178     if (!(dpd->FormFlag & (PTP_DPFF_Enumeration|PTP_DPFF_Range)))
 3179         return (GP_ERROR);
 3180     if (dpd->DataType != PTP_DTC_UINT16)
 3181         return (GP_ERROR);
 3182 
 3183     if (dpd->FormFlag & PTP_DPFF_Enumeration) {
 3184         gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 3185         gp_widget_set_name (*widget, menu->name);
 3186 
 3187         for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3188             char    buf[20];
 3189 
 3190             sprintf(buf,"f/%g",(dpd->FORM.Enum.SupportedValue[i].u16*1.0)/100.0);
 3191             gp_widget_add_choice (*widget,buf);
 3192             if (dpd->FORM.Enum.SupportedValue[i].u16 == dpd->CurrentValue.u16)
 3193                 gp_widget_set_value (*widget,buf);
 3194         }
 3195         GP_LOG_D ("get_FNumber via enum");
 3196     } else { /* Range */
 3197         float value_float;
 3198 
 3199         gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 3200         gp_widget_set_name (*widget, menu->name);
 3201         gp_widget_set_range (*widget,
 3202                 dpd->FORM.Range.MinimumValue.u16/100.0,
 3203                 dpd->FORM.Range.MaximumValue.u16/100.0,
 3204                 dpd->FORM.Range.StepSize.u16/100.0
 3205                 );
 3206         value_float = dpd->CurrentValue.u16/100.0;
 3207         gp_widget_set_value (*widget, &value_float);
 3208         GP_LOG_D ("get_FNumber via float");
 3209     }
 3210     return GP_OK;
 3211 }
 3212 
 3213 static int
 3214 _put_FNumber(CONFIG_PUT_ARGS)
 3215 {
 3216     int i;
 3217 
 3218     if (dpd->FormFlag & PTP_DPFF_Enumeration) {
 3219         char    *value;
 3220         float   f;
 3221 
 3222         CR (gp_widget_get_value(widget, &value));
 3223         if (strstr (value, "f/") == value)
 3224             value += strlen("f/");
 3225 
 3226         for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3227             char    buf[20];
 3228 
 3229             sprintf(buf,"%g",(dpd->FORM.Enum.SupportedValue[i].u16*1.0)/100.0);
 3230             if (!strcmp (buf, value)) {
 3231                 propval->u16 = dpd->FORM.Enum.SupportedValue[i].u16;
 3232                 return GP_OK;
 3233             }
 3234         }
 3235         if (sscanf(value, "%g", &f)) {
 3236             propval->u16 = f*100;
 3237             return GP_OK;
 3238         }
 3239     } else { /* RANGE uses float */
 3240         float fvalue;
 3241 
 3242         CR (gp_widget_get_value (widget, &fvalue));
 3243         propval->u16 = fvalue*100;
 3244         return GP_OK;
 3245     }
 3246     return GP_ERROR;
 3247 }
 3248 
 3249 /* the common sony f-numbers */
 3250 static int sony_fnumbers[] = {
 3251     100,
 3252     110,
 3253     120,
 3254     140,
 3255     160,
 3256     180,
 3257     200,
 3258     220,
 3259     250,
 3260     280,
 3261     320,
 3262     350,
 3263     400,
 3264     450,
 3265     500,
 3266     560,
 3267     630,
 3268     710,
 3269     800,
 3270     900,
 3271     1000,
 3272     1100,
 3273     1300,
 3274     1400,
 3275     1600,
 3276     1800,
 3277     2000,
 3278     2200,
 3279     2500,
 3280     2900,
 3281     3200,
 3282     3600,
 3283     4200,
 3284     4500,
 3285     5000,
 3286     5700,
 3287     6400,
 3288 };
 3289 
 3290 static int
 3291 _get_Sony_FNumber(CONFIG_GET_ARGS) {
 3292     unsigned int    i;
 3293 
 3294     GP_LOG_D ("get_Sony_FNumber");
 3295     if (!(dpd->FormFlag & (PTP_DPFF_Enumeration|PTP_DPFF_Range)))
 3296         return GP_ERROR;
 3297     if (dpd->DataType != PTP_DTC_UINT16)
 3298         return GP_ERROR;
 3299 
 3300     if (dpd->FormFlag & PTP_DPFF_Enumeration)
 3301         return _get_FNumber(CONFIG_GET_NAMES);  /* just use the normal code */
 3302 
 3303     /* Range */
 3304     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 3305     gp_widget_set_name (*widget, menu->name);
 3306 
 3307     for (i=0;i<sizeof(sony_fnumbers)/sizeof(sony_fnumbers[0]); i++) {
 3308         char    buf[20];
 3309 
 3310         sprintf(buf,"f/%g",sony_fnumbers[i]/100.0);
 3311         gp_widget_add_choice (*widget,buf);
 3312         if (sony_fnumbers[i] == dpd->CurrentValue.u16)
 3313             gp_widget_set_value (*widget,buf);
 3314     }
 3315     GP_LOG_D ("get_Sony_FNumber via range and table");
 3316     return GP_OK;
 3317 }
 3318 
 3319 
 3320 static int
 3321 _put_Sony_FNumber(CONFIG_PUT_ARGS)
 3322 {
 3323     float       fvalue = 0.0;
 3324     char *      value;
 3325     PTPParams   *params = &(camera->pl->params);
 3326 
 3327     CR (gp_widget_get_value (widget, &value));
 3328     if (strstr (value, "f/") == value)
 3329         value += strlen("f/");
 3330     if (sscanf(value, "%g", &fvalue))
 3331         propval->u16 = fvalue*100;
 3332     else
 3333         return GP_ERROR;
 3334     return _put_sony_value_u16 (params, PTP_DPC_FNumber, fvalue*100, 0);
 3335 }
 3336 
 3337 static int
 3338 _get_ExpTime(CONFIG_GET_ARGS) {
 3339     int     i;
 3340     PTPParams   *params = &(camera->pl->params);
 3341 
 3342     if (!(dpd->FormFlag & PTP_DPFF_Enumeration))
 3343         return (GP_ERROR);
 3344     if (dpd->DataType != PTP_DTC_UINT32)
 3345         return (GP_ERROR);
 3346 
 3347     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 3348     gp_widget_set_name (*widget, menu->name);
 3349     for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3350         char    buf[20];
 3351 
 3352         if (params->deviceinfo.VendorExtensionID == PTP_VENDOR_NIKON) {
 3353             if (dpd->FORM.Enum.SupportedValue[i].u32 == 0xffffffff) {
 3354                 sprintf(buf,_("Bulb"));
 3355                 goto choicefound;
 3356             }
 3357             if (dpd->FORM.Enum.SupportedValue[i].u32 == 0xfffffffd) {
 3358                 sprintf(buf,_("Time"));
 3359                 goto choicefound;
 3360             }
 3361         }
 3362         sprintf (buf,_("%0.4fs"), (1.0*dpd->FORM.Enum.SupportedValue[i].u32)/10000.0);
 3363 choicefound:
 3364         gp_widget_add_choice (*widget,buf);
 3365         if (dpd->FORM.Enum.SupportedValue[i].u32 == dpd->CurrentValue.u32)
 3366             gp_widget_set_value (*widget,buf);
 3367     }
 3368     return (GP_OK);
 3369 }
 3370 
 3371 static int
 3372 _put_ExpTime(CONFIG_PUT_ARGS)
 3373 {
 3374     unsigned int    i, delta, xval, ival1, ival2, ival3;
 3375     float       val;
 3376     char        *value;
 3377     PTPParams   *params = &(camera->pl->params);
 3378 
 3379     CR (gp_widget_get_value (widget, &value));
 3380 
 3381     if (params->deviceinfo.VendorExtensionID == PTP_VENDOR_NIKON) {
 3382         if (!strcmp(value,_("Bulb"))) {
 3383             propval->u32 = 0xffffffff;
 3384             return GP_OK;
 3385         }
 3386         if (!strcmp(value,_("Time"))) {
 3387             propval->u32 = 0xfffffffd;
 3388             return GP_OK;
 3389         }
 3390     }
 3391 
 3392     if (sscanf(value,_("%d %d/%d"),&ival1,&ival2,&ival3) == 3) {
 3393         GP_LOG_D ("%d %d/%d case", ival1, ival2, ival3);
 3394         val = ((float)ival1) + ((float)ival2/(float)ival3);
 3395     } else if (sscanf(value,_("%d/%d"),&ival1,&ival2) == 2) {
 3396         GP_LOG_D ("%d/%d case", ival1, ival2);
 3397         val = (float)ival1/(float)ival2;
 3398     } else if (!sscanf(value,_("%f"),&val)) {
 3399         GP_LOG_E ("failed to parse: %s", value);
 3400         return (GP_ERROR);
 3401     } else
 3402         GP_LOG_D ("%fs case", val);
 3403     val = val*10000.0;
 3404     delta = 1000000;
 3405     xval = val;
 3406     /* match the closest value */
 3407     for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3408         /*GP_LOG_D ("delta is currently %d, val is %f, supval is %u, abs is %u",delta,val,dpd->FORM.Enum.SupportedValue[i].u32,abs(val - dpd->FORM.Enum.SupportedValue[i].u32));*/
 3409         if (abs((int)(val - dpd->FORM.Enum.SupportedValue[i].u32))<delta) {
 3410             xval = dpd->FORM.Enum.SupportedValue[i].u32;
 3411             delta = abs((int)(val - dpd->FORM.Enum.SupportedValue[i].u32));
 3412         }
 3413     }
 3414     GP_LOG_D ("value %s is %f, closest match was %d",value,val,xval);
 3415     propval->u32 = xval;
 3416     return GP_OK;
 3417 }
 3418 
 3419 static int
 3420 _get_Video_Framerate(CONFIG_GET_ARGS) {
 3421     char        buf[20];
 3422 
 3423     if (dpd->DataType != PTP_DTC_UINT32)
 3424         return GP_ERROR;
 3425 
 3426     if (dpd->FormFlag == PTP_DPFF_Enumeration) {
 3427         gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 3428         /* value will be set below */
 3429     } else {
 3430         if (dpd->FormFlag == PTP_DPFF_Range) {
 3431             gp_widget_new (GP_WIDGET_RANGE, _(menu->label), widget);
 3432             float val = dpd->CurrentValue.u32 / 1000000.0;
 3433             gp_widget_set_value (*widget, &val);
 3434         } else {
 3435             gp_widget_new (GP_WIDGET_TEXT, _(menu->label), widget);
 3436             sprintf (buf, "%0.4f", (1.0*dpd->CurrentValue.u32) / 1000000.0);
 3437             gp_widget_set_value (*widget, buf);
 3438         }
 3439     }
 3440 
 3441     gp_widget_set_name (*widget, menu->name);
 3442 
 3443     if (dpd->FormFlag == PTP_DPFF_Enumeration) {
 3444         int     i;
 3445 
 3446         for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3447             sprintf (buf,"%0.4f", (1.0*dpd->FORM.Enum.SupportedValue[i].u32)/1000000.0);
 3448             gp_widget_add_choice (*widget,buf);
 3449             if (dpd->FORM.Enum.SupportedValue[i].u32 == dpd->CurrentValue.u32)
 3450                 gp_widget_set_value (*widget,buf);
 3451         }
 3452     }
 3453     if (dpd->FormFlag == PTP_DPFF_Range) {
 3454         float b, t, s;
 3455 
 3456         b = (1.0*dpd->FORM.Range.MinimumValue.u32) / 1000000.0;
 3457         t = (1.0*dpd->FORM.Range.MaximumValue.u32) / 1000000.0;
 3458         s = (1.0*dpd->FORM.Range.StepSize.u32) / 1000000.0;
 3459         gp_widget_set_range (*widget, b, t, s);
 3460     }
 3461     return GP_OK;
 3462 }
 3463 
 3464 static int
 3465 _put_Video_Framerate(CONFIG_PUT_ARGS)
 3466 {
 3467     float       val;
 3468     char        *value;
 3469 
 3470     if (dpd->FormFlag == PTP_DPFF_Range) {
 3471         CR (gp_widget_get_value (widget, &val));
 3472     } else {
 3473         CR (gp_widget_get_value (widget, &value));
 3474 
 3475         if (!sscanf(value,_("%f"),&val)) {
 3476             GP_LOG_E ("failed to parse: %s", value);
 3477             return GP_ERROR;
 3478         }
 3479     }
 3480     propval->u32 = val * 1000000;
 3481     return GP_OK;
 3482 }
 3483 
 3484 static int
 3485 _get_Sharpness(CONFIG_GET_ARGS) {
 3486     int i, min, max, t;
 3487 
 3488     if (!(dpd->FormFlag & (PTP_DPFF_Enumeration|PTP_DPFF_Range)))
 3489         return (GP_ERROR);
 3490     if ((dpd->DataType != PTP_DTC_UINT8) && (dpd->DataType != PTP_DTC_INT8))
 3491         return (GP_ERROR);
 3492 
 3493     gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
 3494     gp_widget_set_name (*widget, menu->name);
 3495 
 3496     if (dpd->FormFlag & PTP_DPFF_Range) {
 3497         int s;
 3498 
 3499         if (dpd->DataType == PTP_DTC_UINT8) {
 3500             min = dpd->FORM.Range.MinimumValue.u8;
 3501             max = dpd->FORM.Range.MaximumValue.u8;
 3502             s = dpd->FORM.Range.StepSize.u8;
 3503         } else {
 3504             min = dpd->FORM.Range.MinimumValue.i8;
 3505             max = dpd->FORM.Range.MaximumValue.i8;
 3506             s = dpd->FORM.Range.StepSize.i8;
 3507         }
 3508         if (!s) {
 3509             gp_widget_set_value (*widget, "invalid range, stepping 0");
 3510             return GP_OK;
 3511         }
 3512         for (i=min; i<=max; i+=s) {
 3513             char buf[20];
 3514 
 3515             if (max != min)
 3516                 sprintf (buf, "%d%%", (i-min)*100/(max-min));
 3517             else
 3518                 strcpy (buf, "range max=min?");
 3519             gp_widget_add_choice (*widget, buf);
 3520             if (    ((dpd->DataType == PTP_DTC_UINT8) && (dpd->CurrentValue.u8 == i)) ||
 3521                 ((dpd->DataType == PTP_DTC_INT8)  && (dpd->CurrentValue.i8 == i))
 3522             )
 3523                 gp_widget_set_value (*widget, buf);
 3524         }
 3525     }
 3526 
 3527     if (dpd->FormFlag & PTP_DPFF_Enumeration) {
 3528         min = 256;
 3529         max = -256;
 3530         for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3531             if (dpd->DataType == PTP_DTC_UINT8) {
 3532                 if (dpd->FORM.Enum.SupportedValue[i].u8 < min)
 3533                     min = dpd->FORM.Enum.SupportedValue[i].u8;
 3534                 if (dpd->FORM.Enum.SupportedValue[i].u8 > max)
 3535                     max = dpd->FORM.Enum.SupportedValue[i].u8;
 3536             } else {
 3537                 if (dpd->FORM.Enum.SupportedValue[i].i8 < min)
 3538                     min = dpd->FORM.Enum.SupportedValue[i].i8;
 3539                 if (dpd->FORM.Enum.SupportedValue[i].i8 > max)
 3540                     max = dpd->FORM.Enum.SupportedValue[i].i8;
 3541             }
 3542         }
 3543         if (dpd->DataType == PTP_DTC_UINT8)
 3544             t = dpd->CurrentValue.u8;
 3545         else
 3546             t = dpd->CurrentValue.i8;
 3547         for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3548             char buf[20];
 3549             int x;
 3550 
 3551             if (dpd->DataType == PTP_DTC_UINT8)
 3552                 x = dpd->FORM.Enum.SupportedValue[i].u8;
 3553             else
 3554                 x = dpd->FORM.Enum.SupportedValue[i].i8;
 3555 
 3556             if (max != min)
 3557                 sprintf (buf, "%d%%", (x-min)*100/(max-min));
 3558             else
 3559                 strcpy (buf, "range max=min?");
 3560             gp_widget_add_choice (*widget, buf);
 3561             if (t == x)
 3562                 gp_widget_set_value (*widget, buf);
 3563         }
 3564     }
 3565     return (GP_OK);
 3566 }
 3567 
 3568 static int
 3569 _put_Sharpness(CONFIG_PUT_ARGS) {
 3570     const char *val;
 3571     int i, min, max, x;
 3572 
 3573     gp_widget_get_value (widget, &val);
 3574     if (dpd->FormFlag & PTP_DPFF_Enumeration) {
 3575         min = 256;
 3576         max = -256;
 3577         for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3578             if (dpd->DataType == PTP_DTC_UINT8) {
 3579                 if (dpd->FORM.Enum.SupportedValue[i].u8 < min)
 3580                     min = dpd->FORM.Enum.SupportedValue[i].u8;
 3581                 if (dpd->FORM.Enum.SupportedValue[i].u8 > max)
 3582                     max = dpd->FORM.Enum.SupportedValue[i].u8;
 3583             } else {
 3584                 if (dpd->FORM.Enum.SupportedValue[i].i8 < min)
 3585                     min = dpd->FORM.Enum.SupportedValue[i].i8;
 3586                 if (dpd->FORM.Enum.SupportedValue[i].i8 > max)
 3587                     max = dpd->FORM.Enum.SupportedValue[i].i8;
 3588             }
 3589         }
 3590         for (i=0;i<dpd->FORM.Enum.NumberOfValues; i++) {
 3591             char buf[20];
 3592 
 3593             if (dpd->DataType == PTP_DTC_UINT8)
 3594                 x = dpd->FORM.Enum.SupportedValue[i].u8;
 3595             else
 3596                 x = dpd->FORM.Enum.SupportedValue[i].i8;
 3597 
 3598             sprintf (buf, "%d%%", (x-min)*100/(max-min));
 3599             if (!strcmp(buf, val)) {
 3600                 if (dpd->DataType == PTP_DTC_UINT8)
 3601                     propval->u8 = x;
 3602                 else
 3603                     propval->i8 = x;
 3604                 return GP_OK;
 3605             }
 3606         }
 3607     }
 3608     if (dpd->FormFlag & PTP_DPFF_Range) {
 3609         int s;
 3610 
 3611         if (dpd->DataType == PTP_DTC_UINT8) {
 3612             min = dpd->FORM.Range.MinimumValue.u8;
 3613             max = dpd->FORM.Range.MaximumValue.u8;
 3614             s = dpd->FORM.Range.StepSize.u8;
 3615         } else {
 3616             min = dpd->FORM.Range.MinimumValue.i8;
 3617             max = dpd->FORM.Range.MaximumValue.i8;
 3618             s = dpd->FORM.Range.StepSize.i8;
 3619         }
 3620         for (i=min; i<=max; i+=s) {
 3621             char buf[20];
 3622 
 3623             sprintf (buf, "%d%%", (i-min)*100/(max-min));
 3624             if (strcmp (buf, val)) {
 3625                 if (s == 0)
 3626                     break;
 3627                 continue;
 3628             }
 3629             if (dpd->DataType == PTP_DTC_UINT8)
 3630                 propval->u8 = i;
 3631             else
 3632                 propval->i8 = i;
 3633             return GP_OK;
 3634         }
 3635     }
 3636     return GP_ERROR;
 3637 }
 3638 
 3639 
 3640 static struct deviceproptableu16 exposure_program_modes[] = {
 3641     { "M",          0x0001, 0 },
 3642     { "P",          0x0002, 0 },
 3643     { "A",          0x0003, 0 },
 3644     { "S",          0x0004, 0 },
 3645     { N_("Creative"),   0x0005, 0 },
 3646     { N_("Action"),     0x0006, 0 },
 3647     { N_("Portrait"),   0x0007, 0 },
 3648     { N_("Auto"),       0x8010, PTP_VENDOR_NIKON},
 3649     { N_("Portrait"),   0x8011, PTP_VENDOR_NIKON},
 3650     { N_("Landscape"),  0x8012, PTP_VENDOR_NIKON},
 3651     { N_("Macro"),      0x8013, PTP_VENDOR_NIKON},
 3652     { N_("Sports"),     0x8014, PTP_VENDOR_NIKON},
 3653     { N_("Night Portrait"), 0x8015, PTP_VENDOR_NIKON},
 3654     { N_("Night Landscape"),0x8016, PTP_VENDOR_NIKON},
 3655     { N_("Children"),   0x8017, PTP_VENDOR_NIKON},
 3656     { N_("Automatic (No Flash)"),   0x8018, PTP_VENDOR_NIKON},
 3657 
 3658     { N_("Intelligent Auto"),       0x8000, PTP_VENDOR_SONY},
 3659     { N_("Superior Auto"),          0x8001, PTP_VENDOR_SONY},
 3660     { N_("Movie"),              0x8050, PTP_VENDOR_SONY},
 3661     { N_("Tele-zoom Cont. Priority AE"),    0x8031, PTP_VENDOR_SONY},
 3662     { N_("Sweep Panorama"),         0x8041, PTP_VENDOR_SONY},
 3663     { N_("Intelligent Auto Flash Off"), 0x8060, PTP_VENDOR_SONY},
 3664     { N_("Sports Action"),          0x8011, PTP_VENDOR_SONY},
 3665     { N_("Macro"),              0x8015, PTP_VENDOR_SONY},
 3666     { N_("Landscape"),          0x8014, PTP_VENDOR_SONY},
 3667     { N_("Sunset"),             0x8012, PTP_VENDOR_SONY},
 3668     { N_("Night Scene"),            0x8013, PTP_VENDOR_SONY},
 3669     { N_("Hand-held Twilight"),     0x8016, PTP_VENDOR_SONY},
 3670     { N_("Night Portrait"),         0x8017, PTP_VENDOR_SONY},
 3671     { N_("Picture Effect"),         0x8070, PTP_VENDOR_SONY},
 3672     { N_("S&Q"),                0x8084, PTP_VENDOR_SONY}, /* on A7III */
 3673 };
 3674 GENERIC16TABLE(ExposureProgram,exposure_program_modes)
 3675 
 3676 static struct deviceproptableu8 nikon_scenemode[] = {
 3677     { N_("Night landscape"),    0, 0 },
 3678     { N_("Party/Indoor"),       1, 0 },
 3679     { N_("Beach/Snow"),     2, 0 },
 3680     { N_("Sunset"),         3, 0 },
 3681     { N_("Dusk/Dawn"),      4, 0 },
 3682     { N_("Pet Portrait"),       5, 0 },
 3683     { N_("Candlelight"),        6, 0 },
 3684     { N_("Blossom"),        7, 0 },
 3685     { N_("Autumn colors"),      8, 0 },
 3686     { N_("Food"),           9, 0 },
 3687     /* ? */
 3688     { N_("Portrait"),       13, 0 },
 3689     { N_("Landscape"),      14, 0 },
 3690     { N_("Child"),          15, 0 },
 3691     { N_("Sports"),         16, 0 },
 3692     { N_("Close up"),       17, 0 },
 3693     { N_("Night Portrait"),     18, 0 },
 3694 
 3695 };
 3696 GENERIC8TABLE(NIKON_SceneMode,nikon_scenemode);
 3697 
 3698 /* Nikon 1 S1 specials in here */
 3699 static struct deviceproptableu8 nikon_1_j3_iso[] = {
 3700     /* values from a J3 */
 3701     { N_("A6400 (160-6400)"),   0x01, 0 },
 3702     { N_("A3200 (160-3200)"),   0x02, 0 },
 3703     { N_("A800 (160-800)"),     0x03, 0 },
 3704 
 3705     /* these same same for all 1 */
 3706     { "100",    0x0a, 0 },
 3707     { "110",    0x0b, 0 },
 3708     { "125",    0x0c, 0 },
 3709     { "140",    0x0d, 0 },
 3710     { "160",    0x0e, 0 },
 3711     { "180",    0x0f, 0 },
 3712     { "200",    0x10, 0 },
 3713     { "220",    0x11, 0 },
 3714     { "250",    0x12, 0 },
 3715     { "280",    0x13, 0 },
 3716     { "320",    0x14, 0 },
 3717     { "360",    0x15, 0 },
 3718     { "400",    0x16, 0 },
 3719     { "400",    0x16, 0 },
 3720     { "450",    0x17, 0 },
 3721     { "500",    0x18, 0 },
 3722     { "560",    0x19, 0 },
 3723     { "640",    0x1a, 0 },
 3724     { "720",    0x1b, 0 },
 3725     { "800",    0x1c, 0 },
 3726     { "900",    0x1d, 0 },
 3727     { "1000",   0x1e, 0 },
 3728     { "1100",   0x1f, 0 },
 3729     { "1250",   0x20, 0 },
 3730     { "1400",   0x21, 0 },
 3731     { "1600",   0x22, 0 },
 3732     { "1800",   0x23, 0 },
 3733     { "2000",   0x24, 0 },
 3734     { "2200",   0x25, 0 },
 3735     { "2500",   0x26, 0 },
 3736     { "2800",   0x27, 0 },
 3737     { "3200",   0x28, 0 },
 3738     { "6400",   0x2e, 0 },
 3739     /* more unknown values */
 3740 };
 3741 GENERIC8TABLE(Nikon_1_J3_ISO,nikon_1_j3_iso);
 3742 
 3743 /* Nikon 1 S1 specials in here */
 3744 static struct deviceproptableu8 nikon_1_s1_iso[] = {
 3745     { "100",    0x0a, 0 },
 3746     { "110",    0x0b, 0 },
 3747     { "125",    0x0c, 0 },
 3748     { "140",    0x0d, 0 },
 3749     { "160",    0x0e, 0 },
 3750     { "180",    0x0f, 0 },
 3751     { "200",    0x10, 0 },
 3752     { "220",    0x11, 0 },
 3753     { "250",    0x12, 0 },
 3754     { "280",    0x13, 0 },
 3755     { "320",    0x14, 0 },
 3756     { "360",    0x15, 0 },
 3757     { "400",    0x16, 0 },
 3758     { "450",    0x17, 0 },
 3759     { "500",    0x18, 0 },
 3760     { "560",    0x19, 0 },
 3761     { "640",    0x1a, 0 },
 3762     { "720",    0x1b, 0 },
 3763     { "800",    0x1c, 0 },
 3764     { "900",    0x1d, 0 },
 3765     { "1000",   0x1e, 0 },
 3766     { "1100",   0x1f, 0 },
 3767     { "1250",   0x20, 0 },
 3768     { "1400",   0x21, 0 },
 3769     { "1600",   0x22, 0 },
 3770     { "1800",   0x23, 0 },
 3771     { "2000",   0x24, 0 },
 3772     { "2200",   0x25, 0 },
 3773     { "2500",   0x26, 0 },
 3774     { "2800",   0x27, 0 },
 3775     { "3200",   0x28, 0 },
 3776     { "6400",   0x2e, 0 },
 3777 };
 3778 GENERIC8TABLE(Nikon_1_S1_ISO,nikon_1_s1_iso);
 3779 
 3780 /* Generic Nikon 1 ISO */
 3781 static struct deviceproptableu8 nikon_1_iso[] = {
 3782     { "ISO Auto 6400",  0x01, 0 },
 3783     { "ISO Auto 3200",  0x02, 0 },
 3784     { "ISO Auto 800",   0x03, 0 },
 3785     { "110",    0x0b, 0 },
 3786     { "125",    0x0c, 0 },
 3787     { "140",    0x0d, 0 },
 3788     { "160",    0x0e, 0 },
 3789     { "180",    0x0f, 0 },
 3790     { "200",    0x10, 0 },
 3791     { "220",    0x11, 0 },
 3792     { "250",    0x12, 0 },
 3793     { "280",    0x13, 0 },
 3794     { "320",    0x14, 0 },
 3795     { "360",    0x15, 0 },
 3796     { "400",    0x16, 0 },
 3797     { "450",    0x17, 0 },
 3798     { "500",    0x18, 0 },
 3799     { "560",    0x19, 0 },
 3800     { "640",    0x1a, 0 },
 3801     { "720",    0x1b, 0 },
 3802     { "800",    0x1c, 0 },
 3803     { "900",    0x1d, 0 },
 3804     { "1000",   0x1e, 0 },
 3805     { "1100",   0x1f, 0 },
 3806     { "1250",   0x20, 0 },
 3807     { "1400",   0x21, 0 },
 3808     { "1600",   0x22, 0 },
 3809     { "1800",   0x23, 0 },
 3810     { "2000",   0x24, 0 },
 3811     { "2200",   0x25, 0 },
 3812     { "2500",   0x26, 0 },
 3813     { "2800",   0x27, 0 },
 3814     { "3200",   0x28, 0 },
 3815     { "6400",   0x2e, 0 },
 3816 };
 3817 GENERIC8TABLE(Nikon_1_ISO,nikon_1_iso);
 3818 
 3819 static struct deviceproptableu8 nikon_1_whitebalance[] = {
 3820     /* values from a J3 */
 3821     { N_("Auto"),           0x00, 0 },
 3822     { N_("Tungsten"),       0x01, 0 },
 3823     { N_("Fluorescent"),        0x02, 0 },
 3824     { N_("Daylight"),       0x03, 0 },
 3825     { N_("Flash"),          0x04, 0 },
 3826     { N_("Cloudy"),         0x05, 0 },
 3827     { N_("Shade"),          0x06, 0 },
 3828 
 3829     /* these are not in the enum range on the j3 ... but reported? */
 3830     { N_("Water"),          0x0a, 0 },
 3831     { N_("Preset"),         0x08, 0 },
 3832 };
 3833 GENERIC8TABLE(Nikon_1_WhiteBalance,nikon_1_whitebalance);
 3834 
 3835 static struct deviceproptableu8 nikon_hdrhighdynamic[] = {
 3836     { N_("Auto"),   0, 0 },
 3837     { N_("1 EV"),   1, 0 },
 3838     { N_("2 EV"),   2, 0 },
 3839     { N_("3 EV"),   3, 0 },
 3840 };
 3841 GENERIC8TABLE(Nikon_HDRHighDynamic,nikon_hdrhighdynamic);
 3842 
 3843 static struct deviceproptableu8 nikon_aebracketstep[] = {
 3844     { N_("1/3 EV"), 0, 0 },
 3845     { N_("1/2 EV"), 1, 0 },
 3846     { N_("2/3 EV"), 2, 0 },
 3847     { N_("1 EV"),   3, 0 },
 3848     { N_("2 EV"),   4, 0 },
 3849     { N_("3 EV"),   5, 0 },
 3850 };
 3851 GENERIC8TABLE(Nikon_AEBracketStep,nikon_aebracketstep);
 3852 
 3853 static struct deviceproptableu8 nikon_wbbracketstep[] = {
 3854     { N_("1 EV"),   0, 0 },
 3855     { N_("2 EV"),   1, 0 },
 3856     { N_("3 EV"),   2, 0 },
 3857 };
 3858 GENERIC8TABLE(Nikon_WBBracketStep,nikon_wbbracketstep);
 3859 
 3860 static struct deviceproptableu8 nikon_adlbracketstep[] = {
 3861     { N_("Auto"),       0, 0 },
 3862     { N_("Low"),        1, 0 },
 3863     { N_("Normal"),     2, 0 },
 3864     { N_("High"),       3, 0 },
 3865     { N_("Extra high"), 4, 0 },
 3866 };
 3867 GENERIC8TABLE(Nikon_ADLBracketStep,nikon_adlbracketstep);
 3868 
 3869 static struct deviceproptableu8 nikon_bracketpattern[] = {
 3870     { N_("2 images (normal and under)"),            0, 0 },
 3871     { N_("2 images (normal and over)"),         1, 0 },
 3872     { N_("3 images (normal and 2 unders)"),         2, 0 },
 3873     { N_("3 images (normal and 2 overs)"),          3, 0 },
 3874     { N_("3 images (normal, under and over)"),      4, 0 },
 3875     { N_("5 images (normal, 2 unders and 2 overs)"),    5, 0 },
 3876     { N_("7 images (normal, 3 unders and 3 overs)"),    6, 0 },
 3877     { N_("9 images (normal, 4 unders and 4 overs)"),    7, 0 },
 3878     { N_("0 image"),                    8, 0 },
 3879 };
 3880 GENERIC8TABLE(Nikon_BracketPattern,nikon_bracketpattern);
 3881 
 3882 static struct deviceproptableu8 nikon_adlbracketpattern[] = {
 3883     { N_("2 shots (Off -> User setting)"),              0, 0 },
 3884     { N_("3 shots (Off -> Low -> User setting)"),           1, 0 },
 3885     { N_("4 shots (Off -> Low -> Normal -> High)"),         2, 0 },
 3886     { N_("5 shots (Off -> Low -> Normal -> High -> Extra High)"),   3, 0 },
 3887     { N_("0 image"),                        4, 0 },
 3888 };
 3889 GENERIC8TABLE(Nikon_ADLBracketPattern,nikon_adlbracketpattern);
 3890 
 3891 static struct deviceproptableu8 nikon_hdrsmoothing[] = {
 3892     { N_("Auto"),       3, 0 },
 3893     { N_("Low"),        2, 0 },
 3894     { N_("Normal"),     1, 0 },
 3895     { N_("High"),       0, 0 },
 3896     { N_("Extra high"), 4, 0 },
 3897 };
 3898 GENERIC8TABLE(Nikon_HDRSmoothing,nikon_hdrsmoothing);
 3899 
 3900 static struct deviceproptableu16 nikon_d7100_exposure_program_modes[] = {
 3901     { "M",          0x0001, 0 },
 3902     { "P",          0x0002, 0 },
 3903     { "A",          0x0003, 0 },
 3904     { "S",          0x0004, 0 },
 3905     { N_("Auto"),       0x8010, PTP_VENDOR_NIKON},
 3906     { N_("Portrait"),   0x8011, PTP_VENDOR_NIKON},
 3907     { N_("Landscape"),  0x8012, PTP_VENDOR_NIKON},
 3908     { N_("Macro"),      0x8013, PTP_VENDOR_NIKON},
 3909     { N_("Sports"),     0x8014, PTP_VENDOR_NIKON},
 3910     { N_("No Flash"),   0x8016, PTP_VENDOR_NIKON},
 3911     { N_("Children"),   0x8017, PTP_VENDOR_NIKON},
 3912     { N_("Scene"),      0x8018, PTP_VENDOR_NIKON},
 3913     { N_("Effects"),    0x8019, PTP_VENDOR_NIKON},
 3914     { N_("U1"),     0x8050, PTP_VENDOR_NIKON},
 3915     { N_("U2"),     0x8051, PTP_VENDOR_NIKON},
 3916 };
 3917 GENERIC16TABLE(NIKON_D7100_ExposureProgram,nikon_d7100_exposure_program_modes)
 3918 
 3919 static struct deviceproptableu16 nikon_d5100_exposure_program_modes[] = {
 3920     { "M",          0x0001, 0 },
 3921     { "P",          0x0002, 0 },
 3922     { "A",          0x0003, 0 },
 3923     { "S",          0x0004, 0 },
 3924     { N_("Auto"),       0x8010, PTP_VENDOR_NIKON},
 3925     { N_("Portrait"),   0x8011, PTP_VENDOR_NIKON},
 3926     { N_("Landscape"),  0x8012, PTP_VENDOR_NIKON},
 3927     { N_("Macro"),      0x8013, PTP_VENDOR_NIKON},
 3928     { N_("Sports"),     0x8014, PTP_VENDOR_NIKON},
 3929     { N_("No Flash"),   0x8016, PTP_VENDOR_NIKON},
 3930     { N_("Children"),   0x8017, PTP_VENDOR_NIKON},
 3931     { N_("Scene"),      0x8018, PTP_VENDOR_NIKON},
 3932     { N_("Effects"),    0x8019, PTP_VENDOR_NIKON},
 3933 };
 3934 GENERIC16TABLE(NIKON_D5100_ExposureProgram,nikon_d5100_exposure_program_modes)
 3935 
 3936 static struct deviceproptableu8 nikon_1_exposure_program_modes[] = {
 3937     { "P",          0x00, 0 },
 3938     { "S",          0x01, 0 },
 3939     { "A",          0x02, 0 },
 3940     { "M",          0x03, 0 },
 3941     { N_("Night Landscape"),0x04, 0 },
 3942     { N_("Night Portrait"), 0x05, 0 },
 3943     { N_("Back Light"), 0x06, 0 },
 3944     { N_("Panorama"),   0x07, 0 },
 3945     { N_("Smoothing"),  0x08, 0 },
 3946     { N_("Tilt-Shift"), 0x09, 0 },
 3947     { N_("Select Color"),   0x0a, 0 },
 3948 };
 3949 GENERIC8TABLE(NIKON_1_ExposureProgram,nikon_1_exposure_program_modes)
 3950 
 3951 static struct deviceproptableu16 capture_mode[] = {
 3952     { N_("Single Shot"),        0x0001, 0 },
 3953     { N_("Burst"),          0x0002, 0 },
 3954     { N_("Timelapse"),      0x0003, 0 },
 3955     { N_("Continuous Low Speed"),   0x8010, PTP_VENDOR_NIKON},
 3956     { N_("Timer"),          0x8011, PTP_VENDOR_NIKON},
 3957     { N_("Mirror Up"),      0x8012, PTP_VENDOR_NIKON},
 3958     { N_("Remote"),         0x8013, PTP_VENDOR_NIKON},
 3959     { N_("Quick Response Remote"),  0x8014, PTP_VENDOR_NIKON}, /* others nikons */
 3960     { N_("Delayed Remote"),     0x8015, PTP_VENDOR_NIKON}, /* d90 */
 3961     { N_("Quiet Release"),      0x8016, PTP_VENDOR_NIKON}, /* d5000 */
 3962     { N_("Continuous Quiet Release"),   0x8018, PTP_VENDOR_NIKON}, /* d850 */
 3963 
 3964     { N_("Continuous Low Speed"),   0x8012, PTP_VENDOR_SONY},
 3965     { N_("Selftimer 2s"),       0x8005, PTP_VENDOR_SONY},
 3966     { N_("Selftimer 5s"),       0x8003, PTP_VENDOR_SONY},
 3967     { N_("Selftimer 10s"),      0x8004, PTP_VENDOR_SONY},
 3968     { N_("Selftimer 10s 3 Pictures"),0x8008, PTP_VENDOR_SONY},
 3969     { N_("Selftimer 10s 5 Pictures"),0x8009, PTP_VENDOR_SONY},
 3970     { N_("Selftimer 5s 3 Pictures"),0x800c, PTP_VENDOR_SONY},
 3971     { N_("Selftimer 5s 5 Pictures"),0x800d, PTP_VENDOR_SONY},
 3972     { N_("Selftimer 2s 3 Pictures"),0x800e, PTP_VENDOR_SONY},
 3973     { N_("Selftimer 2s 5 Pictures"),0x800f, PTP_VENDOR_SONY},
 3974     { N_("Continuous Hi+ Speed"),   0x8010, PTP_VENDOR_SONY}, /* A7III */
 3975     { N_("Continuous Med Speed"),   0x8015, PTP_VENDOR_SONY}, /* A7III */
 3976 
 3977     { N_("Bracketing C 0.3 Steps 3 Pictures"),  0x8337, PTP_VENDOR_SONY},
 3978     { N_("Bracketing C 0.3 Steps 5 Pictures"),  0x8537, PTP_VENDOR_SONY},
 3979     { N_("Bracketing C 0.3 Steps 9 Pictures"),  0x8937, PTP_VENDOR_SONY},
 3980 
 3981     { N_("Bracketing C 0.5 Steps 3 Pictures"),  0x8357, PTP_VENDOR_SONY},
 3982     { N_("Bracketing C 0.5 Steps 5 Pictures"),  0x8557, PTP_VENDOR_SONY},
 3983     { N_("Bracketing C 0.5 Steps 9 Pictures"),  0x8957, PTP_VENDOR_SONY},
 3984 
 3985     { N_("Bracketing C 0.7 Steps 3 Pictures"),  0x8377, PTP_VENDOR_SONY},
 3986     { N_("Bracketing C 0.7 Steps 5 Pictures"),  0x8577, PTP_VENDOR_SONY},
 3987     { N_("Bracketing C 0.7 Steps 9 Pictures"),  0x8977, PTP_VENDOR_SONY},
 3988 
 3989     { N_("Bracketing C 1.0 Steps 3 Pictures"),  0x8311, PTP_VENDOR_SONY},
 3990     { N_("Bracketing C 1.0 Steps 5 Pictures"),  0x8511, PTP_VENDOR_SONY},
 3991     { N_("Bracketing C 1.0 Steps 9 Pictures"),  0x8911, PTP_VENDOR_SONY},
 3992 
 3993     { N_("Bracketing C 2.0 Steps 3 Pictures"),  0x8321, PTP_VENDOR_SONY},
 3994     { N_("Bracketing C 2.0 Steps 5 Pictures"),  0x8521, PTP_VENDOR_SONY},
 3995 
 3996     { N_("Bracketing C 3.0 Steps 3 Pictures"),  0x8331, PTP_VENDOR_SONY},
 3997     { N_("Bracketing C 3.0 Steps 5 Pictures"),  0x8531, PTP_VENDOR_SONY},
 3998 
 3999     { N_("Bracketing S 0.3 Steps 3 Pictures"),  0x8336, PTP_VENDOR_SONY},
 4000     { N_("Bracketing S 0.3 Steps 5 Pictures"),  0x8536, PTP_VENDOR_SONY},
 4001     { N_("Bracketing S 0.3 Steps 9 Pictures"),  0x8936, PTP_VENDOR_SONY},
 4002 
 4003     { N_("Bracketing S 0.5 Steps 3 Pictures"),  0x8356, PTP_VENDOR_SONY},
 4004     { N_("Bracketing S 0.5 Steps 5 Pictures"),  0x8556, PTP_VENDOR_SONY},
 4005     { N_("Bracketing S 0.5 Steps 9 Pictures"),  0x8956, PTP_VENDOR_SONY},
 4006 
 4007     { N_("Bracketing S 0.7 Steps 3 Pictures"),  0x8376, PTP_VENDOR_SONY},
 4008     { N_("Bracketing S 0.7 Steps 5 Pictures"),  0x8576, PTP_VENDOR_SONY},
 4009     { N_("Bracketing S 0.7 Steps 9 Pictures"),  0x8976, PTP_VENDOR_SONY},
 4010 
 4011     { N_("Bracketing S 1.0 Steps 3 Pictures"),  0x8310, PTP_VENDOR_SONY},
 4012     { N_("Bracketing S 1.0 Steps 5 Pictures"),  0x8510, PTP_VENDOR_SONY},
 4013     { N_("Bracketing S 1.0 Steps 9 Pictures"),  0x8910, PTP_VENDOR_SONY},
 4014 
 4015     { N_("Bracketing S 2.0 Steps 3 Pictures"),  0x8320, PTP_VENDOR_SONY},
 4016     { N_("Bracketing S 2.0 Steps 5 Pictures"),  0x8520, PTP_VENDOR_SONY},
 4017     { N_("Bracketing S 3.0 Steps 3 Pictures"),  0x8330, PTP_VENDOR_SONY},
 4018     { N_("Bracketing S 3.0 Steps 5 Pictures"),  0x8530, PTP_VENDOR_SONY},
 4019     { N_("Bracketing WB Lo"),   0x8018, PTP_VENDOR_SONY},
 4020     { N_("Bracketing DRO Lo"),  0x8019, PTP_VENDOR_SONY},
 4021     { N_("Bracketing WB Hi"),   0x8028, PTP_VENDOR_SONY},
 4022     { N_("Bracketing DRO Hi"),  0x8029, PTP_VENDOR_SONY},
 4023 /*
 4024     { N_("Continuous"),     0x8001, PTP_VENDOR_CASIO},
 4025     { N_("Prerecord"),      0x8002, PTP_VENDOR_CASIO},
 4026 */
 4027 };
 4028 GENERIC16TABLE(CaptureMode,capture_mode)
 4029 
 4030 static struct deviceproptableu16 focus_metering[] = {
 4031     { N_("Centre-spot"),    0x0001, 0 },
 4032     { N_("Multi-spot"), 0x0002, 0 },
 4033     { N_("Single Area"),    0x8010, PTP_VENDOR_NIKON},
 4034     { N_("Closest Subject"),0x8011, PTP_VENDOR_NIKON},
 4035     { N_("Group Dynamic"),  0x8012, PTP_VENDOR_NIKON},
 4036     { N_("Single-area AF"), 0x8001, PTP_VENDOR_FUJI},
 4037     { N_("Dynamic-area AF"),0x8002, PTP_VENDOR_FUJI},
 4038     { N_("Group-dynamic AF"),0x8003, PTP_VENDOR_FUJI},
 4039     { N_("Dynamic-area AF with closest subject priority"),0x8004, PTP_VENDOR_FUJI},
 4040 };
 4041 GENERIC16TABLE(FocusMetering,focus_metering)
 4042 
 4043 static struct deviceproptableu16 nikon_d7100_focus_metering[] = {
 4044     { N_("Auto"),0x8011, PTP_VENDOR_NIKON},
 4045     { N_("Single Area"),    0x8010, PTP_VENDOR_NIKON},
 4046     { N_("Dynamic Area (9)"),   0x0002, 0 },
 4047     { N_("Dynamic Area (21)"),  0x8013, PTP_VENDOR_NIKON},
 4048     { N_("Dynamic Area (51)"),  0x8014, PTP_VENDOR_NIKON},
 4049     { N_("3D Tracking"),  0x8012, PTP_VENDOR_NIKON},
 4050 };
 4051 GENERIC16TABLE(Nikon_D7100_FocusMetering,nikon_d7100_focus_metering)
 4052 
 4053 static struct deviceproptableu16 nikon_d850_focus_metering[] = {
 4054     { N_("Dynamic-area AF (25 points)"),0x0002, PTP_VENDOR_NIKON},
 4055     { N_("Single-point AF"),0x8010, PTP_VENDOR_NIKON},
 4056     { N_("Auto-area AF"),   0x8011, PTP_VENDOR_NIKON},
 4057     { N_("3D-tracking"),    0x8012, PTP_VENDOR_NIKON},
 4058     { N_("Dynamic-area AF (72 points)"),0x8013, PTP_VENDOR_NIKON},
 4059     { N_("Dynamic-area AF (153 points)"),   0x8014, PTP_VENDOR_NIKON},
 4060     { N_("Group-area AF"),  0x8015, PTP_VENDOR_NIKON},
 4061     { N_("Dynamic-area AF (9 points)"), 0x8016, PTP_VENDOR_NIKON},
 4062 
 4063     { N_("Pinpoint AF"),        0x8017, PTP_VENDOR_NIKON}, /* on Z */
 4064     { N_("Wide-area AF (S)"),   0x8018, PTP_VENDOR_NIKON}, /* on Z */
 4065     { N_("Wide-area AF (L)"),   0x8019, PTP_VENDOR_NIKON}, /* on Z */
 4066 };
 4067 GENERIC16TABLE(Nikon_D850_FocusMetering,nikon_d850_focus_metering)
 4068 
 4069 static struct deviceproptableu8 nikon_colormodel[] = {
 4070     { N_("sRGB (portrait)"),0x00, 0 },
 4071     { N_("AdobeRGB"),   0x01, 0 },
 4072     { N_("sRGB (nature)"),  0x02, 0 },
 4073 };
 4074 GENERIC8TABLE(Nikon_ColorModel,nikon_colormodel)
 4075 
 4076 static struct deviceproptableu8 nikon_colorspace[] = {
 4077     { N_("sRGB"),       0x00, 0 },
 4078     { N_("AdobeRGB"),   0x01, 0 },
 4079 };
 4080 GENERIC8TABLE(Nikon_ColorSpace,nikon_colorspace)
 4081 
 4082 static struct deviceproptableu16 canon_eos_colorspace[] = {
 4083     { N_("sRGB"),       0x01, 0 },
 4084     { N_("AdobeRGB"),   0x02, 0 },
 4085 };
 4086 GENERIC16TABLE(Canon_EOS_ColorSpace,canon_eos_colorspace)
 4087 
 4088 static struct deviceproptableu8 nikon_evstep[] = {
 4089     { "1/3",    0, 0 },
 4090     { "1/2",    1, 0 },
 4091 };
 4092 GENERIC8TABLE(Nikon_EVStep,nikon_evstep)
 4093 
 4094 static struct deviceproptableu8 nikon_orientation[] = {
 4095     { "0'",     0, 0 },
 4096     { "270'",   1, 0 },
 4097     { "90'",    2, 0 },
 4098     { "180'",   3, 0 },
 4099 };
 4100 GENERIC8TABLE(Nikon_CameraOrientation,nikon_orientation)
 4101 
 4102 static struct deviceproptableu16 canon_orientation[] = {
 4103     { "0'",     0, 0 },
 4104     { "90'",    1, 0 },
 4105     { "180'",   2, 0 },
 4106     { "270'",   3, 0 },
 4107 };
 4108 
 4109 static int
 4110 _get_Canon_CameraOrientation(CONFIG_GET_ARGS) {
 4111     char    orient[50]; /* needs also to fit the translated string */
 4112     unsigned int    i;
 4113 
 4114     if (dpd->DataType != PTP_DTC_UINT16)
 4115         return (GP_ERROR);
 4116     gp_widget_new (GP_WIDGET_TEXT, _(menu->label), widget);
 4117     gp_widget_set_name (*widget, menu->name);
 4118     for (i=0;i<sizeof(canon_orientation)/sizeof(canon_orientation[0]);i++) {
 4119         if (canon_orientation[i].value != dpd->CurrentValue.u16)
 4120             continue;
 4121         gp_widget_set_value (*widget, canon_orientation[i].label);
 4122         return GP_OK;
 4123     }
 4124     sprintf (orient, _("Unknown value 0x%04x"), dpd->CurrentValue.u16);
 4125     gp_widget_set_value (*widget, orient);
 4126     return GP_OK;
 4127 }
 4128 
 4129 static int
 4130 _get_Nikon_AngleLevel(CONFIG_GET_ARGS) {
 4131     char    orient[20];
 4132 
 4133     if (dpd->DataType != PTP_DTC_INT32)
 4134         return (GP_ERROR);
 4135     gp_widget_new (GP_WIDGET_TEXT, _(menu->label), widget);
 4136     gp_widget_set_name (*widget, menu->name);
 4137     sprintf (orient, "%.f'", dpd->CurrentValue.i32/65536.0);
 4138     gp_widget_set_value (*widget, orient);
 4139     return GP_OK;
 4140 }
 4141 
 4142 
 4143 static struct deviceproptableu8 nikon_afsensor[] = {
 4144     { N_("Centre"), 0x00, 0 },
 4145     { N_("Top"),    0x01, 0 },
 4146     { N_("Bottom"), 0x02, 0 },
 4147     { N_("Left"),   0x03, 0 },
 4148     { N_("Right"),  0x04, 0 },
 4149 };
 4150 GENERIC8TABLE(Nikon_AutofocusArea,nikon_afsensor)
 4151 
 4152 
 4153 static struct deviceproptableu16 exposure_metering[] = {
 4154     { N_("Average"),    0x0001, 0 },
 4155     { N_("Center Weighted"),0x0002, 0 },
 4156     { N_("Multi Spot"), 0x0003, 0 },
 4157     { N_("Center Spot"),    0x0004, 0 },
 4158     { N_("Spot"),       0x8001, PTP_VENDOR_FUJI },
 4159     { N_("ESP"),        0x8001, PTP_VENDOR_GP_OLYMPUS_OMD },
 4160     { N_("Spot+Highlights"),0x8011, PTP_VENDOR_GP_OLYMPUS_OMD },
 4161     { N_("Spot+Shadows"),   0x8012, PTP_VENDOR_GP_OLYMPUS_OMD },
 4162     /* next ones taken from A7III */
 4163     { N_("Multi"),          0x8001, PTP_VENDOR_SONY },
 4164     { N_("Center"),         0x8002, PTP_VENDOR_SONY },
 4165     { N_("Entire Screen Avg."), 0x8003, PTP_VENDOR_SONY },
 4166     { N_("Spot Standard"),      0x8004, PTP_VENDOR_SONY },
 4167     { N_("Spot Large"),     0x8005, PTP_VENDOR_SONY },
 4168     { N_("Highlight"),      0x8006, PTP_VENDOR_SONY },
 4169 };