"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/camlibs/ptp2/library.c" (14 Feb 2021, 375040 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 "library.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 /* library.c
    2  *
    3  * Copyright (C) 2001-2005 Mariusz Woloszyn <emsi@ipartners.pl>
    4  * Copyright (C) 2003-2021 Marcus Meissner <marcus@jet.franken.de>
    5  * Copyright (C) 2005 Hubert Figuiere <hfiguiere@teaser.fr>
    6  * Copyright (C) 2009 Axel Waggershauser <awagger@web.de>
    7  *
    8  * This library is free software; you can redistribute it and/or
    9  * modify it under the terms of the GNU Lesser General Public
   10  * License as published by the Free Software Foundation; either
   11  * version 2 of the License, or (at your option) any later version.
   12  *
   13  * This library is distributed in the hope that it will be useful,
   14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   16  * Lesser General Public License for more details.
   17  *
   18  * You should have received a copy of the GNU Lesser General Public
   19  * License along with this library; if not, write to the
   20  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   21  * Boston, MA  02110-1301  USA
   22  */
   23 
   24 #define _DEFAULT_SOURCE
   25 #define _DARWIN_C_SOURCE
   26 #include "config.h"
   27 
   28 #include <stdlib.h>
   29 #include <string.h>
   30 #include <stdio.h>
   31 #include <stdarg.h>
   32 #include <time.h>
   33 #include <sys/time.h>
   34 #if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
   35 #include <langinfo.h>
   36 #endif
   37 
   38 #include <gphoto2/gphoto2-library.h>
   39 #include <gphoto2/gphoto2-port-log.h>
   40 #include <gphoto2/gphoto2-setting.h>
   41 
   42 #ifdef ENABLE_NLS
   43 #  include <libintl.h>
   44 #  undef _
   45 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
   46 #  ifdef gettext_noop
   47 #    define N_(String) gettext_noop (String)
   48 #  else
   49 #    define N_(String) (String)
   50 #  endif
   51 #else
   52 #  define textdomain(String) (String)
   53 #  define gettext(String) (String)
   54 #  define dgettext(Domain,Message) (Message)
   55 #  define dcgettext(Domain,Message,Type) (Message)
   56 #  define bindtextdomain(Domain,Directory) (Domain)
   57 #  define _(String) (String)
   58 #  define N_(String) (String)
   59 #endif
   60 
   61 #include "ptp.h"
   62 #include "ptp-bugs.h"
   63 #include "ptp-private.h"
   64 #include "ptp-pack.c"
   65 #include "olympus-wrap.h"
   66 
   67 #ifdef HAVE_LIBWS232
   68 #include <winsock2.h>
   69 #endif
   70 
   71 #define USB_START_TIMEOUT 8000
   72 #define USB_CANON_START_TIMEOUT 1500    /* 1.5 seconds (0.5 was too low) */
   73 #define USB_NORMAL_TIMEOUT 20000
   74 static int normal_timeout = USB_NORMAL_TIMEOUT;
   75 #define USB_TIMEOUT_CAPTURE 100000
   76 static int capture_timeout = USB_TIMEOUT_CAPTURE;
   77 
   78 #define SET_CONTEXT(camera, ctx) ((PTPData *) camera->pl->params.data)->context = ctx
   79 #define SET_CONTEXT_P(p, ctx) ((PTPData *) p->data)->context = ctx
   80 
   81 /* below macro makes a copy of fn without leading character ('/'),
   82  * removes the '/' at the end if present, and calls folder_to_handle()
   83  * function proviging as the first argument the string after the second '/'.
   84  * for example if fn is '/store_00010001/DCIM/somefolder/', the macro will
   85  * call folder_to_handle() with 'DCIM/somefolder' as the very first argument.
   86  * it's used to omit storage pseudofolder and remove trailing '/'
   87  */
   88 
   89 #define find_folder_handle(params,fn,s,p)   {       \
   90         {                       \
   91         int len=strlen(fn);             \
   92         char *backfolder=malloc(len);           \
   93         char *tmpfolder;                \
   94         memcpy(backfolder,fn+1, len);           \
   95         if (backfolder[len-2]=='/') backfolder[len-2]='\0';\
   96         if ((tmpfolder=strchr(backfolder+1,'/'))==NULL) tmpfolder="/";\
   97         p=folder_to_handle(params, tmpfolder+1,s,0,NULL);\
   98         free(backfolder);               \
   99         }                       \
  100 }
  101 
  102 #define folder_to_storage(fn,s) {               \
  103         if (!strncmp(fn,"/"STORAGE_FOLDER_PREFIX,strlen(STORAGE_FOLDER_PREFIX)+1))                          \
  104         {                       \
  105             if (strlen(fn)<strlen(STORAGE_FOLDER_PREFIX)+8+1) \
  106                 return (GP_ERROR);      \
  107             s = strtoul(fn + strlen(STORAGE_FOLDER_PREFIX)+1, NULL, 16);                                \
  108         } else {                    \
  109             gp_context_error (context, _("You need to specify a folder starting with /store_xxxxxxxxx/"));              \
  110             return (GP_ERROR);          \
  111         }                       \
  112 }
  113 
  114 typedef int (*getfunc_t)(CameraFilesystem*, const char*, const char *, CameraFileType, CameraFile *, void *, GPContext *);
  115 typedef int (*putfunc_t)(CameraFilesystem*, const char*, CameraFile*, void*, GPContext*);
  116 
  117 struct special_file {
  118     char        *name;
  119     getfunc_t   getfunc;
  120     putfunc_t   putfunc;
  121 };
  122 
  123 static unsigned int nrofspecial_files = 0;
  124 static struct special_file *special_files = NULL;
  125 
  126 static int
  127 add_special_file (char *name, getfunc_t getfunc, putfunc_t putfunc) {
  128     C_MEM (special_files = realloc (special_files, sizeof(special_files[0])*(nrofspecial_files+1)));
  129     C_MEM (special_files[nrofspecial_files].name = strdup(name));
  130     special_files[nrofspecial_files].putfunc = putfunc;
  131     special_files[nrofspecial_files].getfunc = getfunc;
  132     nrofspecial_files++;
  133     return (GP_OK);
  134 }
  135 
  136 #define STORAGE_FOLDER_PREFIX       "store_"
  137 
  138 int
  139 translate_ptp_result (uint16_t result)
  140 {
  141     switch (result) {
  142     case PTP_RC_OK:             return GP_OK;
  143     case PTP_RC_ParameterNotSupported:  return GP_ERROR_BAD_PARAMETERS;
  144     case PTP_RC_OperationNotSupported:  return GP_ERROR_NOT_SUPPORTED;
  145     case PTP_RC_DeviceBusy:         return GP_ERROR_CAMERA_BUSY;
  146     case PTP_ERROR_NODEVICE:        return GP_ERROR_IO_USB_FIND;
  147     case PTP_ERROR_TIMEOUT:         return GP_ERROR_TIMEOUT;
  148     case PTP_ERROR_CANCEL:          return GP_ERROR_CANCEL;
  149     case PTP_ERROR_BADPARAM:        return GP_ERROR_BAD_PARAMETERS;
  150     case PTP_ERROR_IO:
  151     case PTP_ERROR_DATA_EXPECTED:
  152     case PTP_ERROR_RESP_EXPECTED:       return GP_ERROR_IO;
  153     default:                return GP_ERROR;
  154     }
  155 }
  156 
  157 uint16_t
  158 translate_gp_result_to_ptp (int gp_result)
  159 {
  160     switch (gp_result) {
  161     case GP_OK:             return PTP_RC_OK;
  162     case GP_ERROR_BAD_PARAMETERS:       return PTP_RC_ParameterNotSupported;
  163     case GP_ERROR_NOT_SUPPORTED:        return PTP_RC_OperationNotSupported;
  164     case GP_ERROR_CAMERA_BUSY:      return PTP_RC_DeviceBusy;
  165     case GP_ERROR_IO_USB_FIND:      return PTP_ERROR_NODEVICE;
  166     case GP_ERROR_TIMEOUT:          return PTP_ERROR_TIMEOUT;
  167     case GP_ERROR_CANCEL:           return PTP_ERROR_CANCEL;
  168     case GP_ERROR_IO:           return PTP_ERROR_IO;
  169     default:                return PTP_RC_GeneralError;
  170     }
  171 }
  172 
  173 static void
  174 print_debug_deviceinfo (PTPParams *params, PTPDeviceInfo *di)
  175 {
  176     unsigned int i;
  177 
  178     GP_LOG_D ("Device info:");
  179     GP_LOG_D ("Manufacturer: %s",di->Manufacturer);
  180     GP_LOG_D ("  Model: %s", di->Model);
  181     GP_LOG_D ("  device version: %s", di->DeviceVersion);
  182     GP_LOG_D ("  serial number: '%s'",di->SerialNumber);
  183     GP_LOG_D ("Vendor extension ID: 0x%08x",di->VendorExtensionID);
  184     GP_LOG_D ("Vendor extension version: %d",di->VendorExtensionVersion);
  185     GP_LOG_D ("Vendor extension description: %s",di->VendorExtensionDesc);
  186     GP_LOG_D ("Functional Mode: 0x%04x",di->FunctionalMode);
  187     GP_LOG_D ("PTP Standard Version: %d",di->StandardVersion);
  188     GP_LOG_D ("Supported operations:");
  189     for (i=0; i<di->OperationsSupported_len; i++)
  190         GP_LOG_D ("  0x%04x (%s)", di->OperationsSupported[i], ptp_get_opcode_name (params, di->OperationsSupported[i]));
  191     GP_LOG_D ("Events Supported:");
  192     for (i=0; i<di->EventsSupported_len; i++)
  193         GP_LOG_D ("  0x%04x (%s)", di->EventsSupported[i], ptp_get_event_code_name (params, di->EventsSupported[i]));
  194     GP_LOG_D ("Device Properties Supported:");
  195     for (i=0; i<di->DevicePropertiesSupported_len; i++) {
  196         const char *ptpname = ptp_get_property_description (params, di->DevicePropertiesSupported[i]);
  197         GP_LOG_D ("  0x%04x (%s)", di->DevicePropertiesSupported[i], ptpname ? ptpname : "Unknown DPC code");
  198     }
  199 }
  200 
  201 /* struct timeval is simply two long int values, so passing it by value is not expensive.
  202  * It is most likely going to be inlined anyway and therefore 'free'. Passing it by value
  203  * leads to a cleaner interface. */
  204 static struct timeval
  205 time_now() {
  206     struct timeval curtime;
  207     gettimeofday (&curtime, NULL);
  208     return curtime;
  209 }
  210 
  211 static int
  212 time_since (const struct timeval start) {
  213     struct timeval curtime = time_now();
  214     return ((curtime.tv_sec - start.tv_sec)*1000)+((curtime.tv_usec - start.tv_usec)/1000);
  215 }
  216 
  217 static int
  218 waiting_for_timeout (int *current_wait, struct timeval start, int timeout) {
  219 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  220         int time_to_timeout = timeout - time_since (start);
  221 
  222     if (time_to_timeout <= 0) /* we timed out already ... */
  223         return 0;
  224         *current_wait += 50; /* increase sleep time by 50ms per cycle */
  225         if (*current_wait > 200)
  226                 *current_wait = 200; /* 200ms is the maximum sleep time */
  227         if (*current_wait > time_to_timeout)
  228                 *current_wait = time_to_timeout; /* never sleep 'into' the timeout */
  229         if (*current_wait > 0)
  230                 usleep (*current_wait * 1000);
  231         return *current_wait > 0;
  232 #else
  233     /* Wait always timeout during fuzzing! */
  234     return 0;
  235 #endif
  236 }
  237 
  238 /* Changes the ptp deviceinfo with additional hidden information available,
  239  * or stuff that requires special tricks
  240  */
  241 int
  242 fixup_cached_deviceinfo (Camera *camera, PTPDeviceInfo *di) {
  243     CameraAbilities a;
  244     PTPParams   *params = &camera->pl->params;
  245 
  246         gp_camera_get_abilities(camera, &a);
  247 
  248     /* Panasonic GH5, GC9 */
  249     if (    (di->VendorExtensionID == PTP_VENDOR_PANASONIC) &&
  250         (camera->port->type == GP_PORT_USB) &&
  251         (a.usb_product == 0x2382)
  252     ) {
  253         C_MEM (di->OperationsSupported = realloc(di->OperationsSupported,sizeof(di->OperationsSupported[0])*(di->OperationsSupported_len + 9)));
  254         di->OperationsSupported[di->OperationsSupported_len+0] = PTP_OC_PANASONIC_GetProperty;
  255         di->OperationsSupported[di->OperationsSupported_len+1]  = PTP_OC_PANASONIC_SetProperty;
  256         di->OperationsSupported[di->OperationsSupported_len+2]  = PTP_OC_PANASONIC_ListProperty;
  257         di->OperationsSupported[di->OperationsSupported_len+3]  = PTP_OC_PANASONIC_InitiateCapture;
  258         di->OperationsSupported[di->OperationsSupported_len+4]  = PTP_OC_PANASONIC_Liveview;
  259         di->OperationsSupported[di->OperationsSupported_len+5]  = PTP_OC_PANASONIC_LiveviewImage;
  260         di->OperationsSupported[di->OperationsSupported_len+6]  = PTP_OC_PANASONIC_MovieRecControl;
  261         di->OperationsSupported[di->OperationsSupported_len+7]  = PTP_OC_PANASONIC_GetLiveViewParameters;
  262         di->OperationsSupported[di->OperationsSupported_len+8]  = PTP_OC_PANASONIC_SetLiveViewParameters;
  263         di->OperationsSupported_len += 9;
  264     }
  265 
  266     /* Panasonic hack */
  267     if (    (di->VendorExtensionID == PTP_VENDOR_MICROSOFT) &&
  268         (camera->port->type == GP_PORT_USB) &&
  269         (a.usb_vendor == 0x04da)
  270     ) {
  271         PTPPropertyValue propval;
  272         /* Panasonic changes its device info if the MTP Initiator
  273          * is set, and e.g. adds DeleteObject.
  274          * (found in Windows USB traces) */
  275 
  276         if (!ptp_property_issupported(params, PTP_DPC_MTP_SessionInitiatorInfo))
  277             return GP_OK;
  278 
  279         propval.str = "Windows/6.2.9200 MTPClassDriver/6.2.9200.16384";
  280 
  281         C_PTP (ptp_setdevicepropvalue (params, PTP_DPC_MTP_SessionInitiatorInfo, &propval, PTP_DTC_STR));
  282         C_PTP (ptp_getdeviceinfo (params, di));
  283         return GP_OK;
  284     }
  285 
  286     if (    (di->VendorExtensionID == PTP_VENDOR_MICROSOFT) &&
  287         (camera->port->type == GP_PORT_USB) &&
  288         (a.usb_vendor == 0x1a98)
  289     ) {
  290         di->VendorExtensionID = PTP_VENDOR_GP_LEICA;
  291     }
  292 
  293     /* XML style Olympus E series control. internal deviceInfos is encoded in XML. */
  294     if (    di->Manufacturer && !strcmp(di->Manufacturer,"OLYMPUS") &&
  295         (params->device_flags & DEVICE_FLAG_OLYMPUS_XML_WRAPPED)
  296     ) {
  297         PTPDeviceInfo   ndi, newdi, *outerdi;
  298         unsigned int    i;
  299 
  300         C_PTP (ptp_getdeviceinfo (params, &params->outer_deviceinfo));
  301         outerdi = &params->outer_deviceinfo;
  302 
  303         C_PTP (ptp_olympus_getdeviceinfo (&camera->pl->params, &ndi));
  304 
  305         /* Now merge the XML (inner) and outer (PictBridge) Deviceinfo. */
  306         memcpy (&newdi, outerdi, sizeof(PTPDeviceInfo));
  307 
  308         /* dup the strings */
  309         if (outerdi->VendorExtensionDesc)   C_MEM (newdi.VendorExtensionDesc = strdup (outerdi->VendorExtensionDesc));
  310         if (outerdi->Manufacturer)      C_MEM (newdi.Manufacturer = strdup (outerdi->Manufacturer));
  311         if (outerdi->Model)         C_MEM (newdi.Model = strdup (outerdi->Model));
  312         if (outerdi->DeviceVersion)     C_MEM (newdi.DeviceVersion = strdup (outerdi->DeviceVersion));
  313         if (outerdi->SerialNumber)      C_MEM (newdi.SerialNumber = strdup (outerdi->SerialNumber));
  314 
  315         /* Dup and merge the lists */
  316 #define DI_MERGE(x) \
  317         C_MEM (newdi.x = calloc(sizeof(outerdi->x[0]),(ndi.x##_len + outerdi->x##_len)));\
  318         for (i = 0; i < outerdi->x##_len ; i++)                     \
  319             newdi.x[i] = outerdi->x[i];                     \
  320         for (i = 0; i < ndi.x##_len ; i++)                      \
  321             newdi.x[i+outerdi->x##_len] = ndi.x[i];                 \
  322         newdi.x##_len = ndi.x##_len + outerdi->x##_len;
  323 
  324         DI_MERGE(OperationsSupported);
  325         DI_MERGE(EventsSupported);
  326         DI_MERGE(DevicePropertiesSupported);
  327         DI_MERGE(CaptureFormats);
  328         DI_MERGE(ImageFormats);
  329 
  330         /* libgphoto2 specific for usage in config trees */
  331         newdi.VendorExtensionID = PTP_VENDOR_GP_OLYMPUS;
  332 
  333         GP_LOG_D ("Dumping Olympus Deviceinfo");
  334 
  335 
  336         print_debug_deviceinfo (params, &newdi);
  337         ptp_free_DI (di);
  338         memcpy (di, &newdi, sizeof(newdi));
  339         return GP_OK;
  340     }
  341 
  342     /* for USB class matches on unknown cameras that were matches with PTP generic... */
  343     if (!a.usb_vendor && di->Manufacturer) {
  344         if (strstr (di->Manufacturer,"Canon"))
  345             a.usb_vendor = 0x4a9;
  346         if (strstr (di->Manufacturer,"Nikon"))
  347             a.usb_vendor = 0x4b0;
  348         if (strstr (di->Manufacturer,"FUJIFILM"))
  349             a.usb_vendor = 0x4cb;
  350     }
  351     /* Switch the PTP vendor, so that the vendor specific sets become available. */
  352     if (    (di->VendorExtensionID == PTP_VENDOR_MICROSOFT) &&
  353         di->Manufacturer
  354     ) {
  355         if (strstr (di->Manufacturer,"Canon"))
  356             di->VendorExtensionID = PTP_VENDOR_CANON;
  357         if (strstr (di->Manufacturer,"Nikon"))
  358             di->VendorExtensionID = PTP_VENDOR_NIKON;
  359     }
  360 
  361     /* Newer Canons say that they are MTP devices. Restore Canon vendor extid. */
  362     if (    (   (di->VendorExtensionID == PTP_VENDOR_MICROSOFT)  ||
  363             (di->VendorExtensionID == PTP_VENDOR_MTP)
  364         ) &&
  365         (   (camera->port->type == GP_PORT_USB) ||
  366             (camera->port->type == GP_PORT_PTPIP)
  367         ) &&
  368         (a.usb_vendor == 0x4a9)
  369     ) {
  370         /*camera->pl->bugs |= PTP_MTP;*/
  371         di->VendorExtensionID = PTP_VENDOR_CANON;
  372     }
  373 
  374     /* Newer Nikons (D40) say that they are MTP devices. Restore Nikon vendor extid. */
  375     if (    (   (di->VendorExtensionID == PTP_VENDOR_MICROSOFT) ||
  376             (di->VendorExtensionID == PTP_VENDOR_MTP)
  377         ) &&
  378         (   (camera->port->type == GP_PORT_USB) ||
  379             (camera->port->type == GP_PORT_PTPIP)
  380         ) &&
  381         (a.usb_vendor == 0x4b0)
  382     ) {
  383         /*camera->pl->bugs |= PTP_MTP;*/
  384         di->VendorExtensionID = PTP_VENDOR_NIKON;
  385     }
  386 
  387     /* Fuji S5 Pro mostly, make its vendor set available. */
  388     if (    (di->VendorExtensionID == PTP_VENDOR_MICROSOFT) &&
  389         (camera->port->type == GP_PORT_USB) &&
  390         (a.usb_vendor == 0x4cb) &&
  391         strstr(di->VendorExtensionDesc,"fujifilm.co.jp: 1.0;")
  392     ) {
  393         /*camera->pl->bugs |= PTP_MTP;*/
  394         di->VendorExtensionID = PTP_VENDOR_FUJI;
  395     }
  396 
  397     if (    di->Manufacturer && !strcmp(di->Manufacturer,"OLYMPUS") && !strncmp(di->Model,"E-M",3)  ) {
  398         GP_LOG_D ("Setting Olympus VendorExtensionID to PTP_VENDOR_GP_OLYMPUS_OMD");
  399         di->VendorExtensionID = PTP_VENDOR_GP_OLYMPUS_OMD;
  400     }
  401 
  402     if (di->VendorExtensionID == PTP_VENDOR_FUJI) {
  403         C_MEM (di->DevicePropertiesSupported = realloc(di->DevicePropertiesSupported,sizeof(di->DevicePropertiesSupported[0])*(di->DevicePropertiesSupported_len + 60)));
  404         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+0] = PTP_DPC_ExposureTime;
  405         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+1] = PTP_DPC_FNumber;
  406         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+2] = 0xd38c;    /* PC Mode */
  407         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+3] = 0xd171;    /* Focus control */
  408         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+4] = 0xd21c;    /* Needed for X-T2? */
  409         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+5] = 0xd347;    /* Focus Position */
  410         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+6] = PTP_DPC_FUJI_LensZoomPos;
  411         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+7] = 0xd242;
  412         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+8] = PTP_DPC_FUJI_LiveViewImageSize; /* xt3 confirmed */
  413         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+9] = 0xd168; /* video out on/off (unconfirmed) */
  414         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+10] = PTP_DPC_FUJI_LiveViewImageQuality; /* xt3 confirmed */
  415         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+11] = PTP_DPC_FUJI_ForceMode; /* on xt3 set by webcam app to 1 */
  416         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+12] = 0xd16e; /* seen on xt3 */
  417         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+13] = 0xd372; /* seen on xt3 */
  418         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+14] = 0xd020; /* seen on xt3 */
  419         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+15] = 0xd022; /* seen on xt3 */
  420         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+16] = 0xd023; /* seen on xt3 */
  421         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+17] = 0xd024; /* seen on xt3 */
  422         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+18] = 0xd025; /* seen on xt3 */
  423         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+19] = 0xd026; /* seen on xt3 */
  424         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+20] = 0xd027; /* seen on xt3 */
  425         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+21] = 0xd029; /* seen on xt3 */
  426         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+22] = 0xd16f; /* seen on xt3 */
  427         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+23] = 0xd02f; /* seen on xt3 */
  428         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+24] = 0xd395; /* seen on xt3 */
  429         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+25] = 0xd320; /* seen on xt3 */
  430         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+26] = 0xd321; /* seen on xt3 */
  431         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+27] = 0xd322; /* seen on xt3 */
  432         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+28] = 0xd323; /* seen on xt3 */
  433         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+29] = 0xd346; /* seen on xt3 */
  434         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+30] = 0xd34a; /* seen on xt3 */
  435         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+31] = 0xd34b; /* seen on xt3 */
  436         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+32] = 0xd34d; /* seen on xt3 */
  437         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+33] = 0xd351; /* seen on xt3 */
  438         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+34] = 0xd35e; /* seen on xt3 */
  439         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+35] = 0xd173; /* seen on xt3 */
  440         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+36] = 0xd365; /* seen on xt3 */
  441         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+37] = 0xd366; /* seen on xt3 */
  442         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+38] = 0xd374; /* seen on xt3 */
  443         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+39] = 0xd310; /* seen on xt3 */
  444         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+40] = 0xd359; /* seen on xt3 */
  445         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+41] = 0xd375; /* seen on xt3 */
  446         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+42] = 0xd376; /* seen on xt3 */
  447         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+43] = 0xd36e; /* seen on xt3 */
  448         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+44] = 0xd33f; /* seen on xt3 */
  449         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+45] = 0xd364; /* seen on xt3 */
  450         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+46] = 0xd34e; /* seen on xt3 */
  451         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+47] = 0xd02e; /* seen on xt3 */
  452         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+48] = 0xd36d; /* seen on xt3 */
  453         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+49] = 0xd38a; /* seen on xt3 */
  454         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+50] = 0xd36a; /* seen on xt3 */
  455         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+51] = 0xd36b; /* seen on xt3 */
  456         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+52] = 0xd36f; /* seen on xt3 */
  457         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+53] = 0xd370; /* seen on xt3 */
  458         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+54] = 0xd222; /* seen on xt3 */
  459         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+55] = 0xd223; /* seen on xt3 */
  460         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+56] = 0xd38c; /* seen on xt3 */
  461         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+57] = 0xd38d; /* seen on xt3 */
  462         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+58] = 0xd38e; /* seen on xt3 */
  463         di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+59] = 0xd17b; /* seen on xt3 */
  464         di->DevicePropertiesSupported_len += 60;
  465 
  466         if (ptp_operation_issupported(&camera->pl->params, PTP_OC_FUJI_GetDeviceInfo)) {
  467             uint16_t    *props;
  468             unsigned int    numprops;
  469 
  470             C_PTP (ptp_fuji_getdeviceinfo (params, &props, &numprops));
  471             free (di->DevicePropertiesSupported);
  472 
  473             di->DevicePropertiesSupported       = props;
  474             di->DevicePropertiesSupported_len   = numprops;
  475         }
  476 
  477     }
  478 
  479     /* Nikon DSLR hide its newer opcodes behind another vendor specific query,
  480      * do that and merge it into the generic PTP deviceinfo. */
  481     if (di->VendorExtensionID == PTP_VENDOR_NIKON) {
  482         unsigned int i;
  483         unsigned int nikond;
  484 
  485         /* Nikon V* and J* advertise the new Nikon stuff, but only do the generic
  486          * PTP capture. FIXME: could use flags. */
  487         if (params->deviceinfo.Model && (
  488             (params->deviceinfo.Model[0]=='J') ||
  489             (params->deviceinfo.Model[0]=='V') ||
  490             ((params->deviceinfo.Model[0]=='S') && strlen(params->deviceinfo.Model) < 3)    /* S1 - S2 currently */
  491                 /* but not S7000 */
  492             )
  493         ) {
  494             if (!NIKON_1(&camera->pl->params)) {
  495                 GP_LOG_E ("if camera is Nikon 1 series, camera should probably have flag NIKON_1 set. report that to the libgphoto2 project");
  496                 camera->pl->params.device_flags |= PTP_NIKON_1;
  497             }
  498             C_MEM (di->OperationsSupported = realloc(di->OperationsSupported,sizeof(di->OperationsSupported[0])*(di->OperationsSupported_len + 3)));
  499             /* Nikon J5 does not advertise the PTP_OC_NIKON_InitiateCaptureRecInMedia cmd ... gnh */
  500             /* logic: If we have one 0x920x command, we will probably have 0x9207 too. and getvendorpropcodes ... */
  501 
  502             /* Marcus note: GetVendorPropCodes crashes at least the V1, the J1 and J2.
  503              * but it works on the J3, J4...
  504              * V1: crashes protocol flow
  505              * J1: crashes protocol flow
  506              * J2: crashes protocol flow
  507              * J3: works
  508              * J4: works
  509              * J5: reports invalid opcode
  510              */
  511             if (    !ptp_operation_issupported(&camera->pl->params, PTP_OC_NIKON_InitiateCaptureRecInMedia) &&
  512                  ptp_operation_issupported(&camera->pl->params, PTP_OC_NIKON_StartLiveView)
  513             ) {
  514                 di->OperationsSupported[di->OperationsSupported_len+0] = PTP_OC_NIKON_InitiateCaptureRecInMedia;
  515                 di->OperationsSupported_len++;
  516             }
  517 
  518             if (ptp_operation_issupported(&camera->pl->params, PTP_OC_NIKON_InitiateCaptureRecInMedia)) {
  519                 di->OperationsSupported[di->OperationsSupported_len+0] = PTP_OC_NIKON_GetVendorPropCodes;
  520                 di->OperationsSupported_len++;
  521             }
  522             if (strcmp(params->deviceinfo.Model,"V1")) { /* the Nikon V1 does not like it */
  523                 di->OperationsSupported[di->OperationsSupported_len+0] = PTP_OC_NIKON_ChangeCameraMode;
  524                 di->OperationsSupported_len++;
  525             } else {
  526                 /* on V1 even the 90c7 getevents does not work https://github.com/gphoto/libgphoto2/issues/569 */
  527                 for (i=0;i<di->OperationsSupported_len;i++) {
  528                     if (di->OperationsSupported[i] == PTP_OC_NIKON_GetEvent) {
  529                         GP_LOG_D("On Nikon V1: disable NIKON_GetEvent as its unreliable");
  530                         di->OperationsSupported[i] = PTP_OC_GetDeviceInfo; /* overwrite */
  531                     }
  532                     if (di->OperationsSupported[i] == PTP_OC_NIKON_InitiateCaptureRecInSdram) {
  533                         GP_LOG_D("On Nikon V1: disable NIKON_InitiateCaptureRecInSdram as its unreliable");
  534                         di->OperationsSupported[i] = PTP_OC_InitiateCapture; /* overwrite */
  535                     }
  536                 }
  537             }
  538         }
  539         if (params->deviceinfo.Model && !strcmp(params->deviceinfo.Model,"COOLPIX A")) {
  540             /* The A also hides some commands from us ... */
  541             if (!ptp_operation_issupported(&camera->pl->params, PTP_OC_NIKON_GetVendorPropCodes)) {
  542                 C_MEM (di->OperationsSupported = realloc(di->OperationsSupported,sizeof(di->OperationsSupported[0])*(di->OperationsSupported_len + 10)));
  543                 di->OperationsSupported[di->OperationsSupported_len+0] = PTP_OC_NIKON_GetVendorPropCodes;
  544                 di->OperationsSupported[di->OperationsSupported_len+1]  = PTP_OC_NIKON_GetEvent;
  545                 di->OperationsSupported[di->OperationsSupported_len+2]  = PTP_OC_NIKON_AfDrive;
  546                 di->OperationsSupported[di->OperationsSupported_len+3]  = PTP_OC_NIKON_ChangeCameraMode;
  547                 di->OperationsSupported[di->OperationsSupported_len+4]  = PTP_OC_NIKON_DeviceReady;
  548                 di->OperationsSupported[di->OperationsSupported_len+5]  = PTP_OC_NIKON_StartLiveView;
  549                 di->OperationsSupported[di->OperationsSupported_len+6] = PTP_OC_NIKON_EndLiveView;
  550                 di->OperationsSupported[di->OperationsSupported_len+7] = PTP_OC_NIKON_GetLiveViewImg;
  551                 di->OperationsSupported[di->OperationsSupported_len+8] = PTP_OC_NIKON_ChangeAfArea;
  552                 di->OperationsSupported[di->OperationsSupported_len+9] = PTP_OC_NIKON_InitiateCaptureRecInMedia;
  553                 di->OperationsSupported_len += 10;
  554             }
  555         }
  556         if (params->deviceinfo.Model && (sscanf(params->deviceinfo.Model,"D%d", &nikond)))
  557         {
  558             if ((nikond >= 3000) && (nikond < 3199)) {
  559                 GP_LOG_D("The D3xxx series hides commands from us ... ");
  560                 /* Most commands we guessed do not work (anymore). One user searched for those, remove the ones we do not have.
  561                  * https://github.com/gphoto/libgphoto2/issues/140
  562                  */
  563                 if (!ptp_operation_issupported(&camera->pl->params, PTP_OC_NIKON_GetVendorPropCodes)) {
  564                     C_MEM (di->OperationsSupported = realloc(di->OperationsSupported,sizeof(di->OperationsSupported[0])*(di->OperationsSupported_len + 6)));
  565                     di->OperationsSupported[di->OperationsSupported_len+0]  = PTP_OC_NIKON_AfDrive;
  566                     di->OperationsSupported[di->OperationsSupported_len+1]  = PTP_OC_NIKON_DeviceReady;
  567                     di->OperationsSupported[di->OperationsSupported_len+2]  = PTP_OC_NIKON_GetPreviewImg;
  568                     di->OperationsSupported[di->OperationsSupported_len+3] = PTP_OC_NIKON_MfDrive;
  569                     di->OperationsSupported[di->OperationsSupported_len+4] = PTP_OC_NIKON_ChangeAfArea;
  570                     di->OperationsSupported[di->OperationsSupported_len+5] = PTP_OC_NIKON_AfDriveCancel;
  571                     di->OperationsSupported_len += 6;
  572                 }
  573             }
  574             if ((nikond >= 3200) && (nikond < 3299)) {
  575                 GP_LOG_D("The D3200 hides commands from us ... adding some D7100 ones");
  576                 if (!ptp_operation_issupported(&camera->pl->params, PTP_OC_NIKON_GetVendorPropCodes)) {
  577                     /* see https://github.com/gphoto/gphoto2/issues/331 and https://github.com/gphoto/gphoto2/issues/332 */
  578                     C_MEM (di->OperationsSupported = realloc(di->OperationsSupported,sizeof(di->OperationsSupported[0])*(di->OperationsSupported_len + 14)));
  579                     di->OperationsSupported[di->OperationsSupported_len+0]  = PTP_OC_NIKON_GetEvent;
  580                     di->OperationsSupported[di->OperationsSupported_len+1]  = PTP_OC_NIKON_InitiateCaptureRecInSdram;
  581                     di->OperationsSupported[di->OperationsSupported_len+2]  = PTP_OC_NIKON_AfDrive;
  582                     di->OperationsSupported[di->OperationsSupported_len+3]  = PTP_OC_NIKON_ChangeCameraMode;
  583                     di->OperationsSupported[di->OperationsSupported_len+4]  = PTP_OC_NIKON_DeviceReady;
  584                     di->OperationsSupported[di->OperationsSupported_len+5]  = PTP_OC_NIKON_AfCaptureSDRAM;
  585                     di->OperationsSupported[di->OperationsSupported_len+6]  = PTP_OC_NIKON_DelImageSDRAM;
  586 
  587                     di->OperationsSupported[di->OperationsSupported_len+7]  = PTP_OC_NIKON_GetPreviewImg;
  588                     di->OperationsSupported[di->OperationsSupported_len+8]  = PTP_OC_NIKON_StartLiveView;
  589                     di->OperationsSupported[di->OperationsSupported_len+9]  = PTP_OC_NIKON_EndLiveView;
  590                     di->OperationsSupported[di->OperationsSupported_len+10] = PTP_OC_NIKON_GetLiveViewImg;  /* confirmed works */
  591                     di->OperationsSupported[di->OperationsSupported_len+11] = PTP_OC_NIKON_ChangeAfArea;
  592                     di->OperationsSupported[di->OperationsSupported_len+12] = PTP_OC_NIKON_InitiateCaptureRecInMedia;   /* works to some degree */
  593                     di->OperationsSupported[di->OperationsSupported_len+13] = PTP_OC_NIKON_AfDriveCancel;
  594                     /* probably more */
  595                     di->OperationsSupported_len += 14;
  596 
  597                 }
  598             }
  599             if ((nikond >= 3300) && (nikond < 3999)) {
  600                 GP_LOG_D("The D3xxx series hides commands from us ... adding all D7100 ones");
  601                 if (!ptp_operation_issupported(&camera->pl->params, PTP_OC_NIKON_GetVendorPropCodes)) {
  602                     C_MEM (di->OperationsSupported = realloc(di->OperationsSupported,sizeof(di->OperationsSupported[0])*(di->OperationsSupported_len + 19)));
  603                     di->OperationsSupported[di->OperationsSupported_len+0]  = PTP_OC_NIKON_GetVendorPropCodes;
  604                     di->OperationsSupported[di->OperationsSupported_len+1]  = PTP_OC_NIKON_GetEvent;
  605                     di->OperationsSupported[di->OperationsSupported_len+2]  = PTP_OC_NIKON_InitiateCaptureRecInSdram;
  606                     di->OperationsSupported[di->OperationsSupported_len+3]  = PTP_OC_NIKON_AfDrive;
  607                     di->OperationsSupported[di->OperationsSupported_len+4]  = PTP_OC_NIKON_ChangeCameraMode;
  608                     di->OperationsSupported[di->OperationsSupported_len+5]  = PTP_OC_NIKON_DeviceReady;
  609                     di->OperationsSupported[di->OperationsSupported_len+6]  = PTP_OC_NIKON_AfCaptureSDRAM;
  610                     di->OperationsSupported[di->OperationsSupported_len+7]  = PTP_OC_NIKON_DelImageSDRAM;
  611 
  612                     di->OperationsSupported[di->OperationsSupported_len+8]  = PTP_OC_NIKON_GetPreviewImg;
  613                     di->OperationsSupported[di->OperationsSupported_len+9]  = PTP_OC_NIKON_StartLiveView;
  614                     di->OperationsSupported[di->OperationsSupported_len+10] = PTP_OC_NIKON_EndLiveView;
  615                     di->OperationsSupported[di->OperationsSupported_len+11] = PTP_OC_NIKON_GetLiveViewImg;
  616                     di->OperationsSupported[di->OperationsSupported_len+12] = PTP_OC_NIKON_MfDrive;
  617                     di->OperationsSupported[di->OperationsSupported_len+13] = PTP_OC_NIKON_ChangeAfArea;
  618                     di->OperationsSupported[di->OperationsSupported_len+14] = PTP_OC_NIKON_InitiateCaptureRecInMedia;
  619                     di->OperationsSupported[di->OperationsSupported_len+15] = PTP_OC_NIKON_AfDriveCancel;
  620                     di->OperationsSupported[di->OperationsSupported_len+16] = PTP_OC_NIKON_StartMovieRecInCard;
  621                     di->OperationsSupported[di->OperationsSupported_len+17] = PTP_OC_NIKON_EndMovieRec;
  622                     di->OperationsSupported[di->OperationsSupported_len+18] = PTP_OC_NIKON_TerminateCapture;
  623                     /* probably more */
  624                     di->OperationsSupported_len += 19;
  625 
  626                 }
  627             }
  628         }
  629 
  630         if (ptp_operation_issupported(&camera->pl->params, PTP_OC_NIKON_GetVendorPropCodes)) {
  631             uint16_t    *xprops;
  632             unsigned int    xsize;
  633 
  634             if (PTP_RC_OK == LOG_ON_PTP_E (ptp_nikon_get_vendorpropcodes (&camera->pl->params, &xprops, &xsize))) {
  635                 di->DevicePropertiesSupported = realloc(di->DevicePropertiesSupported,sizeof(di->DevicePropertiesSupported[0])*(di->DevicePropertiesSupported_len + xsize));
  636                 if (!di->DevicePropertiesSupported) {
  637                     free (xprops);
  638                     C_MEM (di->DevicePropertiesSupported);
  639                 }
  640                 for (i=0;i<xsize;i++)
  641                     di->DevicePropertiesSupported[i+di->DevicePropertiesSupported_len] = xprops[i];
  642                 di->DevicePropertiesSupported_len += xsize;
  643                 free (xprops);
  644             }
  645         }
  646 
  647         /* For nikon 1 j5, they have blanked this space */
  648         if (camera->pl->params.device_flags & PTP_NIKON_1) {
  649             for (i=0;i<di->DevicePropertiesSupported_len;i++)
  650                 if ((di->DevicePropertiesSupported[i] & 0xf000) == 0xf000)
  651                     break;
  652             /* The J5 so far goes up to 0xf01c */
  653 #define NIKON_1_ADDITIONAL_DEVPROPS 29
  654             if (i==di->DevicePropertiesSupported_len) {
  655                 di->DevicePropertiesSupported = realloc(di->DevicePropertiesSupported,sizeof(di->DevicePropertiesSupported[0])*(di->DevicePropertiesSupported_len + NIKON_1_ADDITIONAL_DEVPROPS+3));
  656                 if (!di->DevicePropertiesSupported) {
  657                     C_MEM (di->DevicePropertiesSupported);
  658                 }
  659                 for (i=0;i<NIKON_1_ADDITIONAL_DEVPROPS;i++)
  660                     di->DevicePropertiesSupported[i+di->DevicePropertiesSupported_len] = 0xf000 | i;
  661 
  662                 /* is returned by the J5, but readonly */
  663                 di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+NIKON_1_ADDITIONAL_DEVPROPS] = PTP_DPC_NIKON_ExposureTime;  // OKAY in J5
  664                 di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+NIKON_1_ADDITIONAL_DEVPROPS+1] = PTP_DPC_NIKON_LiveViewProhibitCondition;   // hack
  665                 di->DevicePropertiesSupported[di->DevicePropertiesSupported_len+NIKON_1_ADDITIONAL_DEVPROPS+2] = PTP_DPC_NIKON_LiveViewStatus;  // hack
  666 
  667                 di->DevicePropertiesSupported_len += NIKON_1_ADDITIONAL_DEVPROPS + 3;
  668             }
  669         }
  670 
  671 #if 0
  672         if (!ptp_operation_issupported(&camera->pl->params, 0x9207)) {
  673             C_MEM (di->OperationsSupported = realloc(di->OperationsSupported,sizeof(di->OperationsSupported[0])*(di->OperationsSupported_len + 2)));
  674             di->OperationsSupported[di->OperationsSupported_len+0] = PTP_OC_NIKON_InitiateCaptureRecInSdram;
  675             di->OperationsSupported[di->OperationsSupported_len+1] = PTP_OC_NIKON_AfCaptureSDRAM;
  676             di->OperationsSupported_len+=2;
  677         }
  678 #endif
  679     }
  680 
  681     /* Mostly for PTP/IP mode */
  682     if (di->VendorExtensionID == PTP_VENDOR_MTP && di->Manufacturer && !strcmp(di->Manufacturer,"Sony Corporation")) {
  683         di->VendorExtensionID = PTP_VENDOR_SONY;
  684     }
  685 
  686     /* Sony DSLR also hide its newer opcodes behind another vendor specific query,
  687      * do that and merge it into the generic PTP deviceinfo. */
  688     if (di->VendorExtensionID == PTP_VENDOR_SONY) {
  689         unsigned int i;
  690 
  691         if (ptp_operation_issupported(&camera->pl->params, PTP_OC_SONY_GetSDIOGetExtDeviceInfo)) {
  692             int opcodes = 0, propcodes = 0, events = 0, j,k,l;
  693             uint16_t    *xprops;
  694             unsigned int    xsize;
  695 
  696             C_PTP (ptp_sony_sdioconnect (&camera->pl->params, 1, 0, 0));
  697             C_PTP (ptp_sony_sdioconnect (&camera->pl->params, 2, 0, 0));
  698             C_PTP (ptp_sony_get_vendorpropcodes (&camera->pl->params, &xprops, &xsize));
  699 
  700             for (i=0;i<xsize;i++) {
  701                 switch (xprops[i] & 0x7000) {
  702                 case 0x1000: opcodes++; break;
  703                 case 0x4000: events++; break;
  704                 case 0x5000: propcodes++; break;
  705                 default:
  706                     GP_LOG_E ("ptp_sony_get_vendorpropcodes() unknown opcode %x", xprops[i]);
  707                     break;
  708                 }
  709             }
  710             C_MEM (di->DevicePropertiesSupported = realloc(di->DevicePropertiesSupported,sizeof(di->DevicePropertiesSupported[0])*(di->DevicePropertiesSupported_len + propcodes)));
  711             C_MEM (di->OperationsSupported       = realloc(di->OperationsSupported,      sizeof(di->OperationsSupported[0])*(di->OperationsSupported_len + opcodes)));
  712             C_MEM (di->EventsSupported           = realloc(di->EventsSupported,          sizeof(di->EventsSupported[0])*(di->EventsSupported_len + events)));
  713             j = 0; k = 0; l = 0;
  714             for (i=0;i<xsize;i++) {
  715                 GP_LOG_D ("sony code: %x", xprops[i]);
  716                 switch (xprops[i] & 0x7000) {
  717                 case 0x1000:
  718                     di->OperationsSupported[(k++)+di->OperationsSupported_len] = xprops[i];
  719                     break;
  720                 case 0x4000:
  721                     di->EventsSupported[(l++)+di->EventsSupported_len] = xprops[i];
  722                     break;
  723                 case 0x5000:
  724                     di->DevicePropertiesSupported[(j++)+di->DevicePropertiesSupported_len] = xprops[i];
  725                     break;
  726                 default:
  727                     break;
  728                 }
  729             }
  730             di->DevicePropertiesSupported_len += propcodes;
  731             di->EventsSupported_len += events;
  732             di->OperationsSupported_len += opcodes;
  733             free (xprops);
  734             C_PTP (ptp_sony_sdioconnect (&camera->pl->params, 3, 0, 0));
  735 
  736             /* remember for sony zv-1 hack */
  737             params->starttime = time_now();
  738         }
  739         /* Sony QX */
  740         if (ptp_operation_issupported(&camera->pl->params, PTP_OC_SONY_QX_Connect)) {
  741             int opcodes = 0, propcodes = 0, events = 0, j,k,l;
  742             uint16_t    *xprops;
  743             unsigned int    xsize;
  744 
  745             C_PTP (ptp_sony_qx_connect (&camera->pl->params, 1, 0xda01, 0xda01));
  746             C_PTP (ptp_sony_qx_connect (&camera->pl->params, 2, 0xda01, 0xda01));
  747 
  748             C_PTP (ptp_sony_qx_get_vendorpropcodes (&camera->pl->params, &xprops, &xsize));
  749 
  750             for (i=0;i<xsize;i++) {
  751                 switch (xprops[i] & 0x7000) {
  752                 case 0x1000: opcodes++; break;
  753                 case 0x4000: events++; break;
  754                 case 0x5000: propcodes++; break;
  755                 default:
  756                     GP_LOG_E ("ptp_qx_sony_get_vendorpropcodes() unknown opcode %x", xprops[i]);
  757                     break;
  758                 }
  759             }
  760             C_MEM (di->DevicePropertiesSupported = realloc(di->DevicePropertiesSupported,sizeof(di->DevicePropertiesSupported[0])*(di->DevicePropertiesSupported_len + propcodes)));
  761             C_MEM (di->OperationsSupported       = realloc(di->OperationsSupported,      sizeof(di->OperationsSupported[0])*(di->OperationsSupported_len + opcodes)));
  762             C_MEM (di->EventsSupported           = realloc(di->EventsSupported,          sizeof(di->EventsSupported[0])*(di->EventsSupported_len + events)));
  763             j = 0; k = 0; l = 0;
  764             for (i=0;i<xsize;i++) {
  765                 GP_LOG_D ("sony code: %x", xprops[i]);
  766                 switch (xprops[i] & 0x7000) {
  767                 case 0x1000:
  768                     di->OperationsSupported[(k++)+di->OperationsSupported_len] = xprops[i];
  769                     break;
  770                 case 0x4000:
  771                     di->EventsSupported[(l++)+di->EventsSupported_len] = xprops[i];
  772                     break;
  773                 case 0x5000:
  774                     di->DevicePropertiesSupported[(j++)+di->DevicePropertiesSupported_len] = xprops[i];
  775                     break;
  776                 default:
  777                     break;
  778                 }
  779             }
  780             di->DevicePropertiesSupported_len += propcodes;
  781             di->EventsSupported_len += events;
  782             di->OperationsSupported_len += opcodes;
  783             free (xprops);
  784             C_PTP (ptp_sony_qx_connect (&camera->pl->params, 3, 0xda01, 0xda01));
  785 
  786             C_PTP (ptp_sony_qx_getalldevicepropdesc (&camera->pl->params));
  787         }
  788     }
  789 #if 0 /* Marcus: not regular ptp properties, not queryable via getdevicepropertyvalue */
  790     if (di->VendorExtensionID == PTP_VENDOR_CANON) {
  791         if (ptp_operation_issupported(&camera->pl->params, PTP_OC_CANON_EOS_GetDeviceInfoEx)) {
  792             PTPCanonEOSDeviceInfo   eosdi;
  793             int i;
  794 
  795             C_PTP (ptp_canon_eos_getdeviceinfo (&camera->pl->params, &eosdi));
  796             C_MEM (di->DevicePropertiesSupported = realloc(di->DevicePropertiesSupported,sizeof(di->DevicePropertiesSupported[0])*(di->DevicePropertiesSupported_len + eosdi.DevicePropertiesSupported_len)));
  797             for (i=0;i<eosdi.DevicePropertiesSupported_len;i++)
  798                 di->DevicePropertiesSupported[i+di->DevicePropertiesSupported_len] = eosdi.DevicePropertiesSupported[i];
  799             di->DevicePropertiesSupported_len += eosdi.DevicePropertiesSupported_len;
  800         }
  801     }
  802 #endif
  803     return GP_OK;
  804 }
  805 
  806 static uint16_t
  807 nikon_wait_busy(PTPParams *params, int waitms, int timeout) {
  808     uint16_t    res;
  809     int     tries;
  810 
  811     /* wait either 1 second, or 50 tries */
  812     if (waitms)
  813         tries=timeout/waitms;
  814     else
  815         tries=50;
  816 
  817     do {
  818         res = ptp_nikon_device_ready(params);
  819                 if (    (res != PTP_RC_DeviceBusy) &&
  820                         (res != PTP_RC_NIKON_Bulb_Release_Busy)
  821                 ) {
  822             if (res == PTP_RC_NIKON_Silent_Release_Busy)    /* seems to mean something like "not relevant" ... will repeat forever */
  823                 return PTP_RC_OK;
  824             return res;
  825         }
  826         if (waitms) usleep(waitms*1000)/*wait a bit*/;
  827     } while (tries--);
  828     return res;
  829 }
  830 
  831 
  832 static struct {
  833     const char *model;
  834     unsigned short usb_vendor;
  835     unsigned short usb_product;
  836     unsigned long device_flags;
  837 } models[] = {
  838 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  839     /*
  840      * The very first PTP camera (with special firmware only), also
  841      * called "PTP Prototype", may report non PTP interface class
  842      */
  843     {"Kodak:DC240 (PTP mode)",  0x040a, 0x0121, 0},
  844     /*
  845      * Old DC-4800 firmware reported custom interface class, so we have
  846      * to detect it by product/vendor IDs
  847      */
  848     {"Kodak:DC4800", 0x040a, 0x0160, 0},
  849     /* Below other camers known to be detected by interface class */
  850 
  851     {"Kodak:DX3900", 0x040a, 0x0170, 0},
  852     {"Kodak:MC3",    0x040a, 0x0400, 0},
  853     /* reported by Ken Moffat */
  854     {"Kodak:Z7590",  0x040a, 0x0403, 0},
  855     {"Kodak:DX3500", 0x040a, 0x0500, 0},
  856     {"Kodak:DX3600", 0x040a, 0x0510, 0},
  857     {"Kodak:DX3215", 0x040a, 0x0525, 0},
  858     {"Kodak:DX3700", 0x040a, 0x0530, 0},
  859     {"Kodak:CX4230", 0x040a, 0x0535, 0},
  860     {"Kodak:LS420",  0x040a, 0x0540, 0},
  861     {"Kodak:DX4900", 0x040a, 0x0550, 0},
  862     {"Kodak:DX4330", 0x040a, 0x0555, 0},
  863     {"Kodak:CX4200", 0x040a, 0x0560, 0},
  864     {"Kodak:CX4210", 0x040a, 0x0560, 0},
  865     {"Kodak:LS743",  0x040a, 0x0565, 0},
  866     /* both above with different product IDs
  867        normal/retail versions of the same model */
  868     {"Kodak:CX4300", 0x040a, 0x0566, 0},
  869     {"Kodak:CX4310", 0x040a, 0x0566, 0},
  870     {"Kodak:LS753",  0x040a, 0x0567, 0},
  871     {"Kodak:LS443",  0x040a, 0x0568, 0},
  872     {"Kodak:LS663",  0x040a, 0x0569, 0},
  873     {"Kodak:DX6340", 0x040a, 0x0570, 0},
  874     {"Kodak:CX6330", 0x040a, 0x0571, 0},
  875     {"Kodak:DX6440", 0x040a, 0x0572, 0},
  876     {"Kodak:CX6230", 0x040a, 0x0573, 0},
  877     {"Kodak:CX6200", 0x040a, 0x0574, 0},
  878     {"Kodak:DX6490", 0x040a, 0x0575, 0},
  879     {"Kodak:DX4530", 0x040a, 0x0576, 0},
  880     {"Kodak:DX7630", 0x040a, 0x0577, 0},
  881     {"Kodak:CX7300", 0x040a, 0x0578, 0},
  882     {"Kodak:CX7310", 0x040a, 0x0578, 0},
  883     {"Kodak:CX7220", 0x040a, 0x0579, 0},
  884     {"Kodak:CX7330", 0x040a, 0x057a, 0},
  885     {"Kodak:CX7430", 0x040a, 0x057b, 0},
  886     {"Kodak:CX7530", 0x040a, 0x057c, 0},
  887     {"Kodak:DX7440", 0x040a, 0x057d, 0},
  888     /* c300 Pau Rodriguez-Estivill <prodrigestivill@yahoo.es> */
  889     {"Kodak:C300",   0x040a, 0x057e, 0},
  890     {"Kodak:DX7590", 0x040a, 0x057f, 0},
  891     {"Kodak:Z730",   0x040a, 0x0580, 0},
  892     {"Kodak:CX6445", 0x040a, 0x0584, 0},
  893     /* Francesco Del Prete <italyanker@gmail.com> */
  894     {"Kodak:M893 IS",0x040a, 0x0585, 0},
  895     {"Kodak:CX7525", 0x040a, 0x0586, 0},
  896     /* a sf bugreporter */
  897     {"Kodak:Z700",   0x040a, 0x0587, 0},
  898     /* EasyShare Z740, Benjamin Mesing <bensmail@gmx.net> */
  899     {"Kodak:Z740",   0x040a, 0x0588, 0},
  900     /* EasyShare C360, Guilherme de S. Pastore via Debian */
  901     {"Kodak:C360",   0x040a, 0x0589, 0},
  902     /* Giulio Salani <ilfunambolo@gmail.com> */
  903     {"Kodak:C310",   0x040a, 0x058a, 0},
  904     /* Brandon Sharitt */
  905     {"Kodak:C330",   0x040a, 0x058c, 0},
  906     /* c340 Maurizio Daniele <hayabusa@portalis.it> */
  907     {"Kodak:C340",   0x040a, 0x058d, 0},
  908     {"Kodak:V530",   0x040a, 0x058e, 0},
  909     /* v550 Jon Burgess <jburgess@uklinux.net> */
  910     {"Kodak:V550",   0x040a, 0x058f, 0},
  911     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=1618878&group_id=8874 */
  912     {"Kodak:V570",   0x040a, 0x0591, 0},
  913     {"Kodak:P850",   0x040a, 0x0592, 0},
  914     {"Kodak:P880",   0x040a, 0x0593, 0},
  915     /* Илья Розановский <rozanovskii.ilia@gmail.com> */
  916     {"Kodak:Z8612 IS",0x040a, 0x0595, 0},
  917     /* https://launchpad.net/distros/ubuntu/+source/libgphoto2/+bug/67532 */
  918     {"Kodak:C530",   0x040a, 0x059a, 0},
  919     /* Ivan Baldo, http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=387998 */
  920     {"Kodak:CD33",   0x040a, 0x059c, 0},
  921     /* https://sourceforge.net/tracker/?func=detail&atid=208874&aid=1565144&group_id=8874 */
  922     {"Kodak:Z612",   0x040a, 0x059d, 0},
  923     /* David D. Huff Jr. <David.Huff@computer-critters.com> */
  924     {"Kodak:Z650",   0x040a, 0x059e, 0},
  925     /* Sonja Krause-Harder */
  926     {"Kodak:M753",   0x040a, 0x059f, 0},
  927     /* irc reporter */
  928     {"Kodak:V603",   0x040a, 0x05a0, 0},
  929     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1547142&group_id=8874&atid=358874 */
  930     {"Kodak:C533",   0x040a, 0x05a2, 0},
  931     /* Marc Santhoff <M.Santhoff@t-online.de> */
  932     {"Kodak:C643",   0x040a, 0x05a7, 0},
  933     /* Eric Kibbee <eric@kibbee.ca> */
  934     {"Kodak:C875",   0x040a, 0x05a9, 0},
  935     /* https://launchpad.net/bugs/64146 */
  936     {"Kodak:C433",   0x040a, 0x05aa, 0},
  937     /* https://launchpad.net/bugs/64146 */
  938     {"Kodak:V705",   0x040a, 0x05ab, 0},
  939     /* https://launchpad.net/bugs/67532 */
  940     {"Kodak:V610",   0x040a, 0x05ac, 0},
  941     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1861193&group_id=8874&atid=358874 */
  942     {"Kodak:M883",   0x040a, 0x05ad, 0},
  943     /* from Thomas <tomtechguy@gmail.com> */
  944     {"Kodak:C743",   0x040a, 0x05ae, 0},
  945     /* via IRC */
  946     {"Kodak:C653",   0x040a, 0x05af, 0},
  947     /* "William L. Thomson Jr." <wlt@obsidian-studios.com> */
  948     {"Kodak:Z710",   0x040a, 0x05b3, 0},
  949     /* Nicolas Brodu <nicolas.brodu@free.fr> */
  950     {"Kodak:Z712 IS",0x040a, 0x05b4, 0},
  951     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1904224&group_id=8874&atid=358874 */
  952     {"Kodak:Z812 IS",0x040a, 0x05b5, 0},
  953     /* */
  954     {"Kodak:C613",   0x040a, 0x05b7, 0},
  955     /* msp@debian.org https://bugs.kde.org/show_bug.cgi?id=190795 */
  956     {"Kodak:V803",   0x040a, 0x05b8, 0},
  957     /* via IRC */
  958     {"Kodak:C633",   0x040a, 0x05ba, 0},
  959     /* https://bugs.launchpad.net/bugs/203402 */
  960     {"Kodak:ZD710",  0x040a, 0x05c0, 0},
  961     /* https://bugs.launchpad.net/ubuntu/+source/libgphoto2/+bug/385432 */
  962     {"Kodak:M863",   0x040a, 0x05c1, 0},
  963     /* Peter F Bradshaw <pfb@exadios.com> */
  964     {"Kodak:C813",   0x040a, 0x05c3, 0},
  965     /* reported by Christian Le Corre <lecorrec@gmail.com> */
  966     {"Kodak:C913",   0x040a, 0x05c6, 0},
  967     /* IRC reporter */
  968     {"Kodak:Z950",   0x040a, 0x05cd, 0},
  969     /* reported by Jim Nelson <jim@yorba.org> */
  970     {"Kodak:M1063",  0x040a, 0x05ce, 0},
  971     /* http://sourceforge.net/tracker/index.php?func=detail&aid=2889451&group_id=8874&atid=358874 */
  972     {"Kodak:Z915",   0x040a, 0x05cf, 0},
  973     /* l.w.winter@web.de */
  974     {"Kodak:M531",   0x040a, 0x0600, 0},
  975     /* rschweikert@novell.com */
  976     {"Kodak:C183",   0x040a, 0x060b, 0},
  977     /* Oleh Malyi <astroclubzp@gmail.com> */
  978     {"Kodak:Z990",   0x040a, 0x0613, 0},
  979     /* ra4veiV6@lavabit.com */
  980     {"Kodak:C1530",  0x040a, 0x0617, 0},
  981 
  982     /* HP PTP cameras */
  983 #if 0
  984     /* 0x4002 seems to be the mass storage ID, which various forums suggest. -Marcus */
  985     {"HP:PhotoSmart ... ",       0x03f0, 0x4002, 0},
  986 #endif
  987     {"HP:PhotoSmart 812 (PTP mode)", 0x03f0, 0x4202, 0},
  988     {"HP:PhotoSmart 850 (PTP mode)", 0x03f0, 0x4302, 0},
  989     /* HP PhotoSmart 935: T. Kaproncai, 25 Jul 2003*/
  990     {"HP:PhotoSmart 935 (PTP mode)", 0x03f0, 0x4402, 0},
  991     /* HP:PhotoSmart 945: T. Jelbert, 2004/03/29    */
  992     {"HP:PhotoSmart 945 (PTP mode)", 0x03f0, 0x4502, 0},
  993     {"HP:PhotoSmart C500 (PTP mode)", 0x03f0, 0x6002, 0},
  994     {"HP:PhotoSmart 318 (PTP mode)", 0x03f0, 0x6302, 0},
  995     {"HP:PhotoSmart 612 (PTP mode)", 0x03f0, 0x6302, 0},
  996     {"HP:PhotoSmart 715 (PTP mode)", 0x03f0, 0x6402, 0},
  997     {"HP:PhotoSmart 120 (PTP mode)", 0x03f0, 0x6502, 0},
  998     {"HP:PhotoSmart 320 (PTP mode)", 0x03f0, 0x6602, 0},
  999     {"HP:PhotoSmart 720 (PTP mode)", 0x03f0, 0x6702, 0},
 1000     {"HP:PhotoSmart 620 (PTP mode)", 0x03f0, 0x6802, 0},
 1001     {"HP:PhotoSmart 735 (PTP mode)", 0x03f0, 0x6a02, 0},
 1002     {"HP:PhotoSmart 707 (PTP mode)", 0x03f0, 0x6b02, 0},
 1003     {"HP:PhotoSmart 733 (PTP mode)", 0x03f0, 0x6c02, 0},
 1004     {"HP:PhotoSmart 607 (PTP mode)", 0x03f0, 0x6d02, 0},
 1005     {"HP:PhotoSmart 507 (PTP mode)", 0x03f0, 0x6e02, 0},
 1006         {"HP:PhotoSmart 635 (PTP mode)", 0x03f0, 0x7102, 0},
 1007     /* report from Federico Prat Villar <fprat@lsi.uji.es> */
 1008     {"HP:PhotoSmart 43x (PTP mode)", 0x03f0, 0x7202, 0},
 1009     {"HP:PhotoSmart M307 (PTP mode)", 0x03f0, 0x7302, 0},
 1010     {"HP:PhotoSmart 407 (PTP mode)",  0x03f0, 0x7402, 0},
 1011     {"HP:PhotoSmart M22 (PTP mode)",  0x03f0, 0x7502, 0},
 1012     {"HP:PhotoSmart 717 (PTP mode)",  0x03f0, 0x7602, 0},
 1013     {"HP:PhotoSmart 817 (PTP mode)",  0x03f0, 0x7702, 0},
 1014     {"HP:PhotoSmart 417 (PTP mode)",  0x03f0, 0x7802, 0},
 1015     {"HP:PhotoSmart 517 (PTP mode)",  0x03f0, 0x7902, 0},
 1016     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1365941&group_id=8874&atid=108874 */
 1017     {"HP:PhotoSmart M415 (PTP mode)", 0x03f0, 0x7a02, 0},
 1018     /* irc contact, YGingras */
 1019     {"HP:PhotoSmart M23 (PTP mode)",  0x03f0, 0x7b02, 0},
 1020     {"HP:PhotoSmart 217 (PTP mode)",  0x03f0, 0x7c02, 0},
 1021     /* irc contact */
 1022     {"HP:PhotoSmart 317 (PTP mode)",  0x03f0, 0x7d02, 0},
 1023     {"HP:PhotoSmart 818 (PTP mode)",  0x03f0, 0x7e02, 0},
 1024     /* Robin <diilbert.atlantis@gmail.com> */
 1025     {"HP:PhotoSmart M425 (PTP mode)", 0x03f0, 0x8002, 0},
 1026     {"HP:PhotoSmart M525 (PTP mode)", 0x03f0, 0x8102, 0},
 1027     {"HP:PhotoSmart M527 (PTP mode)", 0x03f0, 0x8202, 0},
 1028     {"HP:PhotoSmart M725 (PTP mode)", 0x03f0, 0x8402, 0},
 1029     {"HP:PhotoSmart M727 (PTP mode)", 0x03f0, 0x8502, 0},
 1030     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1584447&group_id=8874&atid=358874 */
 1031     {"HP:PhotoSmart R927 (PTP mode)", 0x03f0, 0x8702, 0},
 1032     /* R967 - Far Jump <far.jmp@gmail.com> */
 1033     {"HP:PhotoSmart R967 (PTP mode)", 0x03f0, 0x8802, 0},
 1034     {"HP:PhotoSmart E327 (PTP mode)", 0x03f0, 0x8b02, 0},
 1035     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=1589879&group_id=8874  */
 1036     {"HP:PhotoSmart E427 (PTP mode)", 0x03f0, 0x8c02, 0},
 1037     /* Martin Laberge <mlsoft@videotron.ca> */
 1038     {"HP:PhotoSmart M737 (PTP mode)", 0x03f0, 0x9602, 0},
 1039     /* https://bugs.launchpad.net/bugs/178916 */
 1040     {"HP:PhotoSmart R742 (PTP mode)", 0x03f0, 0x9702, 0},
 1041     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1814147&group_id=8874&atid=358874 */
 1042     {"HP:PhotoSmart M547 (PTP mode)", 0x03f0, 0x9b02, 0},
 1043 
 1044     /* Most Sony PTP cameras use the same product/vendor IDs. */
 1045     {"Sony:PTP",                  0x054c, 0x004e, 0},
 1046     {"Sony:DSC-H1 (PTP mode)",    0x054c, 0x004e, 0},
 1047     {"Sony:DSC-H2 (PTP mode)",    0x054c, 0x004e, 0},
 1048     {"Sony:DSC-H5 (PTP mode)",    0x054c, 0x004e, 0},
 1049     {"Sony:DSC-N2 (PTP mode)",    0x054c, 0x004e, 0},
 1050     {"Sony:DSC-P5 (PTP mode)",    0x054c, 0x004e, 0},
 1051     {"Sony:DSC-P10 (PTP mode)",   0x054c, 0x004e, 0},
 1052     {"Sony:DSC-F707V (PTP mode)", 0x054c, 0x004e, 0},
 1053     {"Sony:DSC-F717 (PTP mode)",  0x054c, 0x004e, 0},
 1054     {"Sony:DSC-F828 (PTP mode)",  0x054c, 0x004e, 0},
 1055     {"Sony:DSC-P30 (PTP mode)",   0x054c, 0x004e, 0},
 1056     /* P32 reported on May 1st by Justin Alexander <justin (at) harshangel.com> */
 1057     {"Sony:DSC-P31 (PTP mode)",   0x054c, 0x004e, 0},
 1058     {"Sony:DSC-P32 (PTP mode)",   0x054c, 0x004e, 0},
 1059     {"Sony:DSC-P41 (PTP mode)",   0x054c, 0x004e, 0},
 1060     {"Sony:DSC-P43 (PTP mode)",   0x054c, 0x004e, 0},
 1061     {"Sony:DSC-P50 (PTP mode)",   0x054c, 0x004e, 0},
 1062     {"Sony:DSC-P51 (PTP mode)",   0x054c, 0x004e, 0},
 1063     {"Sony:DSC-P52 (PTP mode)",   0x054c, 0x004e, 0},
 1064     {"Sony:DSC-P71 (PTP mode)",   0x054c, 0x004e, 0},
 1065     {"Sony:DSC-P72 (PTP mode)",   0x054c, 0x004e, 0},
 1066     {"Sony:DSC-P73 (PTP mode)",   0x054c, 0x004e, 0},
 1067     {"Sony:DSC-P92 (PTP mode)",   0x054c, 0x004e, 0},
 1068     {"Sony:DSC-P93 (PTP mode)",   0x054c, 0x004e, 0},
 1069     {"Sony:DSC-P100 (PTP mode)",  0x054c, 0x004e, 0},
 1070     {"Sony:DSC-P120 (PTP mode)",  0x054c, 0x004e, 0},
 1071     {"Sony:DSC-P200 (PTP mode)",  0x054c, 0x004e, 0},
 1072     {"Sony:DSC-R1 (PTP mode)",    0x054c, 0x004e, 0},
 1073     {"Sony:DSC-S40 (PTP mode)",   0x054c, 0x004e, 0},
 1074     {"Sony:DSC-S60 (PTP mode)",   0x054c, 0x004e, 0},
 1075     {"Sony:DSC-S75 (PTP mode)",   0x054c, 0x004e, 0},
 1076     {"Sony:DSC-S85 (PTP mode)",   0x054c, 0x004e, 0},
 1077     {"Sony:DSC-T1 (PTP mode)",    0x054c, 0x004e, 0},
 1078     {"Sony:DSC-T3 (PTP mode)",    0x054c, 0x004e, 0},
 1079     {"Sony:DSC-T10 (PTP mode)",   0x054c, 0x004e, 0},
 1080     {"Sony:DSC-U20 (PTP mode)",   0x054c, 0x004e, 0},
 1081     {"Sony:DSC-V1 (PTP mode)",    0x054c, 0x004e, 0},
 1082     {"Sony:DSC-W1 (PTP mode)",    0x054c, 0x004e, 0},
 1083     {"Sony:DSC-W12 (PTP mode)",   0x054c, 0x004e, 0},
 1084     {"Sony:DSC-W35 (PTP mode)",   0x054c, 0x004e, 0},
 1085     {"Sony:DSC-W55 (PTP mode)",   0x054c, 0x004e, 0},
 1086     {"Sony:MVC-CD300 (PTP mode)", 0x054c, 0x004e, 0},
 1087     {"Sony:MVC-CD500 (PTP mode)", 0x054c, 0x004e, 0},
 1088     {"Sony:DSC-U10 (PTP mode)",   0x054c, 0x004e, 0},
 1089     /* "Riccardo (C10uD)" <c10ud.dev@gmail.com> */
 1090     {"Sony:DSC-S730 (PTP mode)",  0x054c, 0x0296, 0},
 1091     {"Sony:DSC-S780 (PTP mode)",  0x054c, 0x0296, 0},
 1092     /* Fernando Santoro <fernando.lopezjr@gmail.com> */
 1093     {"Sony:DSC-A100 (PTP mode)",  0x054c, 0x02c0, 0},
 1094     /* Sam Tseng <samtz1223@gmail.com> */
 1095     /* this seems not to have a separate control mode id, see https://github.com/gphoto/libgphoto2/issues/288 */
 1096     {"Sony:DSC-A900 (PTP mode)",  0x054c, 0x02e7, PTP_CAP},
 1097     /* new id?! Reported by Ruediger Oertel. */
 1098     {"Sony:DSC-W200 (PTP mode)",  0x054c, 0x02f8, 0},
 1099     /* Martin Vala <vala.martin@gmail.com> */
 1100     {"Sony:SLT-A350 (PTP mode)",   0x054c, 0x0321, 0},
 1101     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1946931&group_id=8874&atid=308874 */
 1102     {"Sony:DSC-W130 (PTP mode)",  0x054c, 0x0343, 0},
 1103     /* https://sourceforge.net/p/gphoto/support-requests/115/ */
 1104     {"Sony:DSC-HX5V (PTP mode)",  0x054c, 0x0491, 0},
 1105     /* tux droid <gnutuxdroid@gmail.com> */
 1106     {"Sony:SLT-A55 (PTP mode)",   0x054c, 0x04a3, 0},
 1107     /* em33kay@gmail.com */
 1108     {"Sony:NEX5 (PTP mode)",      0x054c, 0x04a5, 0},
 1109     /* http://sourceforge.net/tracker/?func=detail&atid=358874&aid=3515558&group_id=8874 */
 1110     {"Sony:SLT-A35 (PTP mode)",   0x054c, 0x04a7, 0},
 1111     /* t.ludewig@gmail.com */
 1112     {"Sony:DSC-RX100 (PTP mode)", 0x054c, 0x052a, 0},
 1113     /* Stuart Nettleton <snettlet@gmail.com> */
 1114     {"Sony:DSC-RX1 (PTP mode)",   0x054c, 0x052b, 0},
 1115     /* Maptz <m13.maptz@gmail.com> */
 1116     {"Sony:DSC-W510 (PTP mode)",  0x054c, 0x053c, 0},
 1117     /* Rudi */
 1118     {"Sony:DSC-HX100V (PTP mode)",0x054c, 0x0543, 0},
 1119     /* t.ludewig@gmail.com */
 1120     {"Sony:SLT-A65V (PTP mode)",  0x054c, 0x0574, 0},
 1121     /* Irina Iakovleva <irina.bunger@gmail.com> */
 1122     {"Sony:SLT-A77V (PTP mode)",  0x054c, 0x0577, 0},
 1123     /* Jose Velez <jvelez00@gmail.com> */
 1124     {"Sony:NEX-7 (PTP mode)",     0x054c, 0x057d, 0},
 1125 
 1126     /* https://sourceforge.net/p/libmtp/bugs/1459/ */
 1127     {"Sony:HDR-PJ260VE (PTP mode)",0x054c, 0x0603, 0},
 1128 
 1129     /* Jean-Christophe Clavier <jcclavier@free.fr> */
 1130     {"Sony:DSC-HX20V (PTP mode)", 0x054c, 0x061c, 0},
 1131     /* t.ludewig@gmail.com */
 1132     {"Sony:DSC-HX200V (PTP mode)",0x054c, 0x061f, 0},
 1133 
 1134     /* https://sourceforge.net/p/gphoto/feature-requests/424/ */
 1135     {"Sony:SLT-A57",          0x054c, 0x0669, 0},
 1136 
 1137     /* Abhishek Anand <ajaxor1@gmail.com> */
 1138     {"Sony:SLT-A37",          0x054c, 0x0669, 0},
 1139 
 1140     /* https://sourceforge.net/p/gphoto/feature-requests/480/ */
 1141     {"Sony:NEX-5R",           0x054c, 0x066f, 0},
 1142 
 1143     /* Mike Breeuwer <info@mikebreeuwer.com> */
 1144     {"Sony:SLT-A99v",         0x054c, 0x0675, 0},
 1145 
 1146     /* Ramon Carlos Garcia Bruna <ramongarciabruna@gmail.com> */
 1147     {"Sony:NEX-6",                0x054c, 0x0678, 0},
 1148 
 1149     /* t.ludewig@gmail.com */
 1150     {"Sony:DSC-HX300 (PTP mode)", 0x054c, 0x06ee, 0},
 1151 
 1152     /* t.ludewig@gmail.com */
 1153     {"Sony:NEX-3N (PTP mode)",    0x054c, 0x072f, 0},
 1154 
 1155     /* Thorsten Ludewig <t.ludewig@gmail.com> */
 1156     {"Sony:SLT-A58",          0x054c, 0x0736, 0},
 1157     /* Marcus Meissner */
 1158     {"Sony:SLT-A58 (Control)",    0x054c, 0x0737, PTP_CAP},
 1159 
 1160     /* Thorsten Ludewig <t.ludewig@gmail.com> */
 1161     {"Sony:DSC-RX100M2",          0x054c, 0x074b, 0},
 1162     /* Thorsten Ludewig <t.ludewig@gmail.com> */
 1163     {"Sony:Alpha-A3000",          0x054c, 0x074e, 0},
 1164 
 1165     /* bertrand.chambon@free.fr */
 1166     {"Sony:Alpha-A68 (MTP)",      0x054c, 0x0779, 0},
 1167     /* https://github.com/gphoto/libgphoto2/issues/70 */
 1168     {"Sony:Alpha-A6300 (MTP)",    0x054c, 0x077a, 0},
 1169 
 1170     /* https://github.com/gphoto/libgphoto2/issues/190 */
 1171     {"Sony:Alpha-A6500",          0x054c, 0x0784, 0},
 1172 
 1173     /* bertrand.chambon@free.fr */
 1174     {"Sony:Alpha-A68 (Control)",  0x054c, 0x079b, PTP_CAP|PTP_CAP_PREVIEW},
 1175 
 1176     /* https://github.com/gphoto/libgphoto2/issues/70 */
 1177     {"Sony:Alpha-A6300 (Control)",0x054c, 0x079c, PTP_CAP|PTP_CAP_PREVIEW},
 1178 
 1179     /* Anja Stock at SUSE */
 1180     {"Sony:DSC-RX10M3 (Control)",   0x054c, 0x079d, PTP_CAP|PTP_CAP_PREVIEW},
 1181 
 1182     /* Elijah Parker <mail@timelapseplus.com> */
 1183     {"Sony:Alpha-A99 M2 (Control)", 0x054c, 0x079e, PTP_CAP|PTP_CAP_PREVIEW},
 1184 
 1185     /* Elijah Parker <mail@timelapseplus.com> */
 1186     {"Sony:DSC-RX100V (Control)", 0x054c, 0x07a3, PTP_CAP},
 1187     /* hanes442@icloud.com */
 1188     {"Sony:DSC-RX100M5 (Control)",0x054c, 0x07a3, PTP_CAP},
 1189 
 1190 
 1191     /* Elijah Parker <mail@timelapseplus.com> */
 1192     /* https://github.com/gphoto/libgphoto2/issues/190 */
 1193     {"Sony:Alpha-A6500 (Control)", 0x054c, 0x07a4, PTP_CAP|PTP_CAP_PREVIEW},
 1194 
 1195     /* Elijah Parker <mail@timelapseplus.com> */
 1196     /* https://sourceforge.net/p/gphoto/support-requests/127/ */
 1197     {"Sony:Alpha-A5000 (Control)", 0x054c, 0x07c6, PTP_CAP},
 1198 
 1199     /* jackden@gmail.com */
 1200     {"Sony:DSC-RX100M6 (MTP)",  0x054c, 0x0830, 0},
 1201 
 1202     /* https://sourceforge.net/p/libmtp/support-requests/246/ */
 1203     {"Sony:DSC-HX400V (MTP)",      0x054c, 0x08ac, 0},
 1204 
 1205     /* https://sourceforge.net/p/libmtp/bugs/1310/ */
 1206     {"Sony:DSC-HX60V (MTP)",      0x054c, 0x08ad, 0},
 1207 
 1208     /* https://github.com/gphoto/libgphoto2/issues/355 */
 1209     {"Sony:DSC-WX350 (MTP)",      0x054c, 0x08b0, 0},
 1210 
 1211     /* Sascha Peilicke at SUSE */
 1212     {"Sony:Alpha-A6000 (MTP)",    0x054c, 0x08b7, 0},
 1213 
 1214     /* https://sourceforge.net/p/gphoto/feature-requests/456/ */
 1215     {"Sony:Alpha-A7S (MTP)",      0x054c, 0x08e2, 0},
 1216 
 1217     /* David Farrier <farrier@iglou.com> */
 1218     {"Sony:RX100M3 (MTP)",        0x054c, 0x08e3, 0},
 1219 
 1220     /* Markus Oertel */
 1221     {"Sony:Alpha-A5100 (MTP)",    0x054c, 0x08e7, 0},
 1222 
 1223     /* Andre Crone, andre@elysia.nl */
 1224     {"Sony:Alpha-A7 (Control)",   0x054c, 0x094c, PTP_CAP},
 1225 
 1226     /* https://sourceforge.net/p/gphoto/feature-requests/442/ */
 1227     /* no preview: https://github.com/gphoto/gphoto2/issues/106#issuecomment-381424159 */
 1228     {"Sony:Alpha-A7r (Control)",  0x054c, 0x094d, PTP_CAP},
 1229 
 1230     /* preview was confirmed not to work. */
 1231     {"Sony:Alpha-A6000 (Control)",  0x054c, 0x094e, PTP_CAP},
 1232 
 1233     /* Nick Clarke <nick.clarke@gmail.com> */
 1234     {"Sony:Alpha-A77 M2 (Control)", 0x054c, 0x0953, PTP_CAP|PTP_CAP_PREVIEW},
 1235 
 1236     /* http://sourceforge.net/p/gphoto/feature-requests/456/ */
 1237     {"Sony:Alpha-A7S (Control)",    0x054c, 0x0954, PTP_CAP|PTP_CAP_PREVIEW},
 1238 
 1239     /* Markus Oertel */
 1240     /* Preview confirmed by Adrian Schroeter, preview might need the firmware getting updated */
 1241     {"Sony:Alpha-A5100 (Control)",  0x054c, 0x0957, PTP_CAP|PTP_CAP_PREVIEW},
 1242 
 1243     /* https://github.com/gphoto/libgphoto2/issues/343  */
 1244     {"Sony:Alpha-A7III (Control)",  0x054c, 0x096f, PTP_CAP|PTP_CAP_PREVIEW},
 1245 
 1246     /* Adrian Schroeter */
 1247     {"Sony:ILCE-7R M2 (MTP)",           0x054c, 0x09e7, 0},
 1248 
 1249     /* https://sourceforge.net/p/gphoto/feature-requests/472/ */
 1250     {"Sony:DSC-HX90V (MTP)",            0x054c, 0x09e8, 0},
 1251 
 1252     /* titan232@gmail.com */
 1253     {"Sony:ILCE-7M2 (Control)",         0x054c, 0x0a6a, PTP_CAP|PTP_CAP_PREVIEW},
 1254 
 1255     /* Andre Crone, andre@elysia.nl */
 1256     {"Sony:Alpha-A7r II (Control)",     0x054c, 0x0a6b, PTP_CAP|PTP_CAP_PREVIEW},
 1257 
 1258     /* Andre Crone <andre@elysia.nl> */
 1259     {"Sony:DSC-RX100M4",                0x054c, 0x0a6d, PTP_CAP|PTP_CAP_PREVIEW},
 1260 
 1261     /* Andre Crone <andre@elysia.nl>, adjusted */
 1262     {"Sony:Alpha-A7S II (Control)",     0x054c,0x0a71, PTP_CAP|PTP_CAP_PREVIEW},
 1263 
 1264     /* brandonlampert@gmail.com */
 1265     {"Sony:DSC-QX30U",          0x054c,0x0a77, PTP_CAP_PREVIEW},
 1266 
 1267     /* Demo7up <demo7up@gmail.com> */
 1268     {"Sony:UMC-R10C",           0x054c,0x0a79, 0},
 1269 
 1270     {"Sony:DSC-RX0 (MTP)",          0x054c, 0x0bfd, 0},
 1271 
 1272     /* https://github.com/gphoto/libgphoto2/issues/230 */
 1273     {"Sony:Alpha-A7R III (MTP mode)",   0x054c,0x0c00, 0},
 1274 
 1275     /* https://github.com/gphoto/libgphoto2/issues/343 */
 1276     {"Sony:Alpha-A7 III (MTP mode)",    0x054c,0x0c03, 0},
 1277 
 1278     /* andreas@harth.org */
 1279     {"Sony:ZV-1",               0x054c,0x0c1b, 0},
 1280 
 1281     /* Elijah Parker, mail@timelapseplus.com */
 1282     {"Sony:Alpha-A9 (Control)",         0x054c, 0x0c2a, PTP_CAP|PTP_CAP_PREVIEW},
 1283 
 1284     /* Richard Brown at SUSE */
 1285     {"Sony:Alpha-RX10M4 (Control)",     0x054c,0x0c2f, PTP_CAP|PTP_CAP_PREVIEW},
 1286 
 1287     {"Sony:DSC-RX0 (PC Control)",       0x054c, 0x0c32, PTP_CAP|PTP_CAP_PREVIEW},
 1288 
 1289     /* Elijah Parker, mail@timelapseplus.com */
 1290     /* https://github.com/gphoto/libgphoto2/issues/230 */
 1291     {"Sony:Alpha-A7r III (PC Control)", 0x054c, 0x0c33, PTP_CAP|PTP_CAP_PREVIEW}, /* FIXME: crosscheck */
 1292     {"Sony:Alpha-A7 III (PC Control)",  0x054c, 0x0c34, PTP_CAP|PTP_CAP_PREVIEW}, /* FIXME: crosscheck */
 1293 
 1294     /* jackden@gmail.com */
 1295     {"Sony:DSC-RX100M6 (PC Control)",   0x054c, 0x0c38, PTP_CAP|PTP_CAP_PREVIEW},
 1296 
 1297     /* andreas@harth.org */
 1298     {"Sony:ZV-1 (PC Control)",      0x054c, 0x0c44, PTP_CAP|PTP_CAP_PREVIEW},
 1299 
 1300     /* https://github.com/gphoto/libgphoto2/issues/419 */
 1301     {"Sony:DSC RX0 II (PC Control)",    0x054c, 0x0ca6, PTP_CAP|PTP_CAP_PREVIEW},
 1302     /* orbital sailor <gamerdude1080@hotmail.com> */
 1303     {"Sony:ILCE-6400 (PC Control)",     0x054c, 0x0caa, PTP_CAP|PTP_CAP_PREVIEW},
 1304     /* Elias Asikainen <elias.asikainen@sulzerschmid.ch> */
 1305     {"Sony:DSC-RX100M7 (PC Control)",   0x054c, 0x0cae, PTP_CAP|PTP_CAP_PREVIEW},
 1306     /* Mikael Ståldal <mikael@staldal.nu> */
 1307     {"Sony:DSC-RX100M5A (MTP)",     0x054c, 0x0cb1, 0},
 1308     {"Sony:DSC-RX100M5A (PC Control)",  0x054c, 0x0cb2, PTP_CAP|PTP_CAP_PREVIEW},
 1309 
 1310     /* Elijah Parker, mail@timelapseplus.com */
 1311     {"Sony:DSC-A7r IV (Control)",       0x054c, 0x0ccc, PTP_CAP|PTP_CAP_PREVIEW},
 1312     {"Sony:DSC-A7S III (Control)",      0x054c, 0x0d18, PTP_CAP|PTP_CAP_PREVIEW},
 1313 
 1314 
 1315     /* Nikon Coolpix 2500: M. Meissner, 05 Oct 2003 */
 1316     {"Nikon:Coolpix 2500 (PTP mode)", 0x04b0, 0x0109, 0},
 1317     /* Nikon Coolpix 5700: A. Tanenbaum, 29 Oct 2002 */
 1318     /* no capture complete: https://sourceforge.net/tracker/index.php?func=detail&aid=3018517&group_id=8874&atid=108874 */
 1319     {"Nikon:Coolpix 5700 (PTP mode)", 0x04b0, 0x010d, PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1320     /* Nikon Coolpix 4500: T. Kaproncai, 22 Aug 2003 */
 1321     {"Nikon:Coolpix 4500 (PTP mode)", 0x04b0, 0x010b, 0},
 1322     /* Nikon Coolpix 4300: Marco Rodriguez, 10 dic 2002 */
 1323     {"Nikon:Coolpix 4300 (PTP mode)", 0x04b0, 0x010f, 0},
 1324     /* Nikon Coolpix 3500: M. Meissner, 07 May 2003 */
 1325     {"Nikon:Coolpix 3500 (PTP mode)", 0x04b0, 0x0111, 0},
 1326     /* Nikon Coolpix 885: S. Anderson, 19 nov 2002 */
 1327     {"Nikon:Coolpix 885 (PTP mode)",  0x04b0, 0x0112, 0},
 1328     /* Nikon Coolpix 5000, Firmware v1.7 or later */
 1329     {"Nikon:Coolpix 5000 (PTP mode)", 0x04b0, 0x0113, PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1330     /* Nikon Coolpix 3100 */
 1331     {"Nikon:Coolpix 3100 (PTP mode)", 0x04b0, 0x0115, 0},
 1332     /* Nikon Coolpix 2100 */
 1333     {"Nikon:Coolpix 2100 (PTP mode)", 0x04b0, 0x0117, 0},
 1334     /* Nikon Coolpix 5400: T. Kaproncai, 25 Jul 2003 */
 1335     {"Nikon:Coolpix 5400 (PTP mode)", 0x04b0, 0x0119, PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1336     /* Nikon Coolpix 3700: T. Ehlers, 18 Jan 2004 */
 1337     {"Nikon:Coolpix 3700 (PTP mode)", 0x04b0, 0x011d, PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1338     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2110825&group_id=8874&atid=108874 */
 1339     {"Nikon:Coolpix 8700 (PTP mode)", 0x04b0, 0x011f, 0},
 1340     /* Nikon Coolpix 3200 */
 1341     {"Nikon:Coolpix 3200 (PTP mode)", 0x04b0, 0x0121, 0},
 1342     /* Nikon Coolpix 2200 */
 1343     {"Nikon:Coolpix 2200 (PTP mode)", 0x04b0, 0x0122, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1344 
 1345     /* Jonathan Marten <jonathanmarten@users.sf.net>
 1346      * https://sourceforge.net/p/gphoto/bugs/968/ */
 1347     {"Nikon:Coolpix 2200v1.1 (PTP mode)", 0x04b0, 0x0123, PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1348 
 1349     /* Harry Reisenleiter <harrylr@earthlink.net> */
 1350     {"Nikon:Coolpix 8800 (PTP mode)", 0x04b0, 0x0127, PTP_CAP},
 1351     /* Nikon Coolpix 4800 */
 1352     {"Nikon:Coolpix 4800 (PTP mode)", 0x04b0, 0x0129, 0},
 1353     /* Nikon Coolpix SQ: M. Holzbauer, 07 Jul 2003 */
 1354     /* and https://github.com/gphoto/libgphoto2/issues/29 */
 1355     {"Nikon:Coolpix 4100 (PTP mode)", 0x04b0, 0x012d, PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1356     /* Nikon Coolpix 5600: Andy Shevchenko, 11 Aug 2005 */
 1357     {"Nikon:Coolpix 5600 (PTP mode)", 0x04b0, 0x012e, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1358     /* 4600: Martin Klaffenboeck <martin.klaffenboeck@gmx.at> */
 1359     {"Nikon:Coolpix 4600 (PTP mode)", 0x04b0, 0x0130, 0},
 1360     /* 4600: Roberto Costa <roberto.costa@ensta.org>, 22 Oct 2006 */
 1361     {"Nikon:Coolpix 4600a (PTP mode)", 0x04b0, 0x0131,PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1362     {"Nikon:Coolpix 5900 (PTP mode)", 0x04b0, 0x0135, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1363     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1846012&group_id=8874&atid=358874 */
 1364     {"Nikon:Coolpix 7900 (PTP mode)", 0x04b0, 0x0137, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1365     /* Egil Kvaleberg: USB says "NIKON DSC E7600-PTP" */
 1366     {"Nikon:Coolpix 7600 (PTP mode)", 0x04b0, 0x0139, PTP_CAP},
 1367 
 1368     {"Nikon:Coolpix P1 (PTP mode)",   0x04b0, 0x0140, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1369     /* Marcus Meissner */
 1370     {"Nikon:Coolpix P2 (PTP mode)",   0x04b0, 0x0142, PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1371     /* Richard SCHNEIDER <Richard.SCHNEIDER@tilak.at> */
 1372     {"Nikon:Coolpix S4 (PTP mode)",   0x04b0, 0x0144, 0},
 1373     /* Lowe, John Michael <jomlowe@iupui.edu> */
 1374     {"Nikon:Coolpix S2 (PTP mode)",   0x04b0, 0x014e, 0},
 1375     {"Nikon:Coolpix S6 (PTP mode)",   0x04b0, 0x014e, 0},
 1376     /* http://sourceforge.net/tracker/index.php?func=detail&aid=3114250&group_id=8874&atid=358874 */
 1377     {"Nikon:Coolpix S7c (PTP mode)",  0x04b0, 0x0157, 0},
 1378     /* Ole Aamot <ole@gnome.org> */
 1379     {"Nikon:Coolpix P5000 (PTP mode)",0x04b0, 0x015b, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1380     /* Peter Pregler <Peter_Pregler@email.com> */
 1381     {"Nikon:Coolpix S500 (PTP mode)", 0x04b0, 0x015d, 0},
 1382     {"Nikon:Coolpix L12 (PTP mode)",  0x04b0, 0x015f, PTP_CAP},
 1383     /* Marius Groeger <marius.groeger@web.de> */
 1384     {"Nikon:Coolpix S200 (PTP mode)", 0x04b0, 0x0161, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1385     /* Submitted on IRC by kallepersson */
 1386     {"Nikon:Coolpix P5100 (PTP mode)", 0x04b0, 0x0163, 0},
 1387     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2589245&group_id=8874&atid=108874 */
 1388     {"Nikon:Coolpix P50 (PTP mode)",  0x04b0, 0x0169, 0},
 1389     /* Clodoaldo <clodoaldo.pinto.neto@gmail.com> via
 1390          * https://bugs.kde.org/show_bug.cgi?id=315268 */
 1391     {"Nikon:Coolpix P80 (PTP mode)",  0x04b0, 0x016b, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1392 
 1393     /* TJ <wxtofly@gmail.com> */
 1394     {"Nikon:Coolpix P80 v1.1 (PTP mode)",  0x04b0, 0x016c, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1395 
 1396     /* http://sourceforge.net/tracker/index.php?func=detail&aid=2951663&group_id=8874&atid=358874 */
 1397     {"Nikon:Coolpix P6000 (PTP mode)",0x04b0, 0x016f, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1398     /*   http://bugs.debian.org/520752 */
 1399     {"Nikon:Coolpix S60 (PTP mode)",  0x04b0, 0x0171, 0},
 1400     /* Mike Strickland <livinwell@georgianatives.net> */
 1401     {"Nikon:Coolpix P90 (PTP mode)",  0x04b0, 0x0173, 0},
 1402     /* https://github.com/gphoto/gphoto2/issues/214 */
 1403     {"Nikon:Coolpix L100 (PTP mode)", 0x04b0, 0x0174, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1404     /* Christoph Muehlmann <c.muehlmann@nagnag.de> */
 1405     {"Nikon:Coolpix S220 (PTP mode)", 0x04b0, 0x0177, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1406     /* */
 1407     {"Nikon:Coolpix S225 (PTP mode)", 0x04b0, 0x0178, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1408 
 1409     /* Ryan Nestor <ryan@monadnock.org> */
 1410     {"Nikon:Coolpix P100 (PTP mode)", 0x04b0, 0x017d, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1411     /* Štěpán Němec <stepnem@gmail.com> */
 1412     {"Nikon:Coolpix P7000 (PTP mode)",0x04b0, 0x017f, PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1413 
 1414     /* http://sourceforge.net/tracker/index.php?func=detail&aid=3019787&group_id=8874&atid=358874 */
 1415     /* probably no need for nikon_broken_Cap as it worked without this flag for the user */
 1416     {"Nikon:Coolpix L110 (PTP mode)", 0x04b0, 0x017e, PTP_CAP},
 1417 
 1418     /* miguel@rozsas.eng.br */
 1419     {"Nikon:Coolpix P500 (PTP mode)", 0x04b0, 0x0184, PTP_CAP},
 1420     /* Graeme Wyatt <graeme.wyatt@nookawarra.com> */
 1421     {"Nikon:Coolpix L120 (PTP mode)", 0x04b0, 0x0185, PTP_CAP},
 1422     /* Kévin Ottens <ervin@ipsquad.net> */
 1423     {"Nikon:Coolpix S9100 (PTP mode)",0x04b0, 0x0186, PTP_CAP},
 1424 
 1425     /* johnnolan@comcast.net */
 1426     {"Nikon:Coolpix AW100 (PTP mode)",0x04b0, 0x0188, PTP_CAP},
 1427 
 1428     /* Dale Pontius <DEPontius@edgehp.net> */
 1429     {"Nikon:Coolpix P7100 (PTP mode)",0x04b0, 0x018b, PTP_CAP},
 1430 
 1431     /* "Dr. Ing. Dieter Jurzitza" <dieter.jurzitza@t-online.de> */
 1432     {"Nikon:Coolpix 9400  (PTP mode)",0x04b0, 0x0191, PTP_CAP},
 1433 
 1434     /* t.ludewig@gmail.com */
 1435     {"Nikon:Coolpix L820  (PTP mode)",0x04b0, 0x0192, PTP_CAP},
 1436     /* https://sourceforge.net/p/gphoto/feature-requests/429/ */
 1437     {"Nikon:Coolpix S9500 (PTP mode)",0x04b0, 0x0193, PTP_CAP},
 1438 
 1439     /* LeChuck <ofernandez84@gmail.com> */
 1440     {"Nikon:Coolpix AW110 (PTP mode)",0x04b0, 0x0194, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1441 
 1442     /* https://github.com/gphoto/libgphoto2/issues/116 */
 1443     {"Nikon:Coolpix AW130 (PTP mode)",0x04b0, 0x0198, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1444 
 1445     /* https://github.com/gphoto/libgphoto2/issues/150 */
 1446     {"Nikon:Coolpix P900 (PTP mode)", 0x04b0, 0x019c, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1447 
 1448     /* https://github.com/gphoto/libgphoto2/issues/141 */
 1449     {"Nikon:Coolpix A900 (PTP mode)", 0x04b0, 0x019e, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1450 
 1451     /* https://github.com/gphoto/libgphoto2/issues/138 */
 1452     {"Nikon:KeyMission 360 (PTP mode)",0x04b0, 0x019f, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1453 
 1454     {"Nikon:Coolpix SQ (PTP mode)",   0x04b0, 0x0202, 0},
 1455     /* lars marowski bree, 16.8.2004 */
 1456     {"Nikon:Coolpix 4200 (PTP mode)", 0x04b0, 0x0204, 0},
 1457     /* Nikon Coolpix 5200: Andy Shevchenko, 18 Jul 2005 */
 1458     {"Nikon:Coolpix 5200 (PTP mode)", 0x04b0, 0x0206, 0},
 1459     /* https://launchpad.net/bugs/63473 */
 1460     {"Nikon:Coolpix L1 (PTP mode)",   0x04b0, 0x0208, 0},
 1461     {"Nikon:Coolpix P4 (PTP mode)",   0x04b0, 0x020c, PTP_CAP},
 1462     /* Bo Masser <bo@massers.se> */
 1463     {"Nikon:Coolpix S620 (PTP mode)", 0x04b0, 0x021c, 0},
 1464     {"Nikon:Coolpix S6000 (PTP mode)",0x04b0, 0x021e, 0},
 1465     /* http://sourceforge.net/tracker/index.php?func=detail&aid=3135935&group_id=8874&atid=358874 */
 1466     {"Nikon:Coolpix S8000 (PTP mode)",0x04b0, 0x021f, 0},
 1467     /* Aleksej Serdjukov <deletesoftware@yandex.ru> */
 1468     {"Nikon:Coolpix S5100 (PTP mode)",0x04b0, 0x0220, 0},
 1469     /* wlady.cs@gmail.com */
 1470     {"Nikon:Coolpix P300 (PTP mode)", 0x04b0, 0x0221, 0},
 1471     /* t.ludewig@gmail.com */
 1472     {"Nikon:Coolpix S8200",           0x04b0, 0x0222, 0},
 1473     {"Nikon:Coolpix P510 (PTP mode)", 0x04b0, 0x0223, 0},
 1474     /* Bernhard Schiffner <bernhard@schiffner-limbach.de> */
 1475     {"Nikon:Coolpix P7700 (PTP mode)",0x04b0, 0x0225, 0},
 1476 
 1477     /* t.ludewig@gmail.com */
 1478     /* N CP A seems capture capable, but does not list vendor commands */
 1479     /* Reports 0x400d aka CaptureComplete event ... but has no
 1480      * vendor commands? yeah right ... */
 1481     /* It might be similar to the 1? lets try ... Marcus 20140706 */
 1482     {"Nikon:Coolpix A (PTP mode)",    0x04b0, 0x0226, PTP_CAP|PTP_NIKON_1}, /* PTP_CAP */
 1483 
 1484     /* Jonas Stein <news@jonasstein.de> */
 1485     {"Nikon:Coolpix P330 (PTP mode)", 0x04b0, 0x0227, PTP_CAP},
 1486 
 1487     /* Malcolm Lee <mallee@mallee45.ukfsn.org> */
 1488     {"Nikon:Coolpix P7800 (PTP mode)", 0x04b0, 0x0229, 0},
 1489 
 1490     /* t.ludewig@gmail.com */
 1491     /* Also reports 0x400d aka CaptureComplete event ... but has no
 1492      * vendor commands? yeah right... */
 1493     {"Nikon:Coolpix P520 (PTP mode)", 0x04b0, 0x0228, 0}, /* PTP_CAP */
 1494 
 1495     /* checamon <checamon@gmail.com> */
 1496     {"Nikon:Coolpix B700 (PTP mode)", 0x04b0, 0x0231, PTP_CAP|PTP_CAP_PREVIEW},
 1497 
 1498     /* https://github.com/gphoto/libgphoto2/issues/477 */
 1499     {"Nikon:Coolpix P1000 (PTP mode)",0x04b0, 0x0232, PTP_CAP/*|PTP_CAP_PREVIEW*/},
 1500 
 1501     /* Nikon Coolpix 2000 */
 1502     {"Nikon:Coolpix 2000 (PTP mode)", 0x04b0, 0x0302, 0},
 1503     /* From IRC reporter. */
 1504     {"Nikon:Coolpix L4 (PTP mode)",   0x04b0, 0x0305, 0},
 1505     /* from Magnus Larsson */
 1506     {"Nikon:Coolpix L11 (PTP mode)",  0x04b0, 0x0309, 0},
 1507     /* From IRC reporter. */
 1508     {"Nikon:Coolpix L10 (PTP mode)",  0x04b0, 0x030b, 0},
 1509     /* Philippe ENTZMANN <philippe@phec.net> */
 1510     {"Nikon:Coolpix P60 (PTP mode)",  0x04b0, 0x0311, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1511     /* Stas Timokhin <st@ngs.ru> */
 1512     {"Nikon:Coolpix L16 (PTP mode)",  0x04b0, 0x0315, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1513     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2977303&group_id=8874&atid=358874 */
 1514     {"Nikon:Coolpix L20 (PTP mode)",  0x04b0, 0x0317, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1515     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2947644&group_id=8874&atid=108874 */
 1516     {"Nikon:Coolpix L19 (PTP mode)",  0x04b0, 0x0318, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1517     /* IRC reporter */
 1518     {"Nikon:Coolpix S3000 (PTP mode)",0x04b0, 0x031b, PTP_CAP},
 1519     /* christian.moll@tudor.lu */
 1520     {"Nikon:Coolpix S3100 (PTP mode)",0x04b0, 0x0320, PTP_CAP},
 1521     /* Teemu rytilahti of KDE */
 1522     {"Nikon:Coolpix S2500 (PTP mode)",0x04b0, 0x0321, PTP_CAP},
 1523     /* Fabio <ctrlaltca@gmail.com> */
 1524     {"Nikon:Coolpix L23 (PTP mode)",  0x04b0, 0x0324, PTP_CAP},
 1525     /* Novell bugzilla 852551 */
 1526     {"Nikon:Coolpix S4300 (PTP mode)",0x04b0, 0x0329, PTP_CAP/*?*/},
 1527     /* "M.-A. DARCHE" <ma.darche@cynode.org> . gets capturecomplete events nicely */
 1528     {"Nikon:Coolpix S3300 (PTP mode)",0x04b0, 0x032a, PTP_CAP},
 1529     /* Mdasoh Kyaeppd at IRC */
 1530     {"Nikon:Coolpix S6300 (PTP mode)",0x04b0, 0x032c, PTP_CAP},
 1531     /* sakax <sakamotox@gmail.com> */
 1532     {"Nikon:Coolpix S2600 (PTP mode)",0x04b0, 0x032d, PTP_CAP|PTP_NIKON_BROKEN_CAP},
 1533 
 1534     /* dougvj@gmail.com */
 1535     {"Nikon:Coolpix L810  (PTP mode)",0x04b0, 0x032f, PTP_CAP},
 1536 
 1537     /* Borja Latorre <borja.latorre@csic.es> */
 1538     {"Nikon:Coolpix S3200",       0x04b0, 0x0334, PTP_CAP},
 1539 
 1540 
 1541     /* t.ludewig@gmail.com */
 1542     {"Nikon:Coolpix S01",         0x04b0, 0x0337, PTP_CAP},
 1543 
 1544     /* https://sourceforge.net/p/gphoto/bugs/971/ */
 1545     {"Nikon:Coolpix S2700",       0x04b0, 0x033f, PTP_CAP},
 1546 
 1547     /* Jeremy Harkcom <jeremy@harkcom.co.uk> */
 1548     {"Nikon:Coolpix L27",         0x04b0, 0x0343, PTP_CAP},
 1549 
 1550     /* t.ludewig@gmail.com */
 1551     {"Nikon:Coolpix S02",         0x04b0, 0x0346, PTP_CAP},
 1552 
 1553     /* t.ludewig@gmail.com */
 1554     /* seems not to report events? but has full liveview caps_ */
 1555     {"Nikon:Coolpix S9700",       0x04b0, 0x034b, PTP_CAP|PTP_CAP_PREVIEW|PTP_NIKON_BROKEN_CAP},
 1556 
 1557     /* David Shawcross <david@sitevisuals.com> */
 1558     {"Nikon:Coolpix S6800",       0x04b0, 0x0350, PTP_CAP},
 1559 
 1560     /* Tomasz Lis <mefistotelis@gmail.com> */
 1561     {"Nikon:Coolpix S3600",       0x04b0, 0x0353, PTP_CAP},
 1562 
 1563     /* Laurence Praties <laurence.praties@i-abra.com> */
 1564     {"Nikon:Coolpix L840",        0x04b0, 0x035a, PTP_CAP|PTP_NO_CAPTURE_COMPLETE},
 1565 
 1566     /* David Shawcross <david@sitevisuals.com> */
 1567     {"Nikon:Coolpix S3700",       0x04b0, 0x035c, PTP_CAP},
 1568 
 1569     /* David Shawcross <david@sitevisuals.com> */
 1570     {"Nikon:Coolpix S2900",       0x04b0, 0x035e, PTP_CAP},
 1571 
 1572     /* https://sourceforge.net/p/libmtp/bugs/1743/ */
 1573     {"Nikon:Coolpix L340",        0x04b0, 0x0361, PTP_CAP},
 1574 
 1575     /* Krystal Puga <krystalvp@gmail.com> */
 1576     {"Nikon:KeyMission 170",      0x04b0, 0x0364, PTP_CAP},
 1577 
 1578     /* Nikon D100 has a PTP mode: westin 2002.10.16 */
 1579     {"Nikon:DSC D100 (PTP mode)",     0x04b0, 0x0402, 0},
 1580     /* D2H SLR in PTP mode from Steve Drew <stevedrew@gmail.com> */
 1581     {"Nikon:D2H SLR (PTP mode)",      0x04b0, 0x0404, 0},
 1582     {"Nikon:DSC D70 (PTP mode)",      0x04b0, 0x0406, PTP_CAP},
 1583     /* Justin Case <justin_case@gmx.net> */
 1584     {"Nikon:D2X SLR (PTP mode)",      0x04b0, 0x0408, PTP_CAP},
 1585     /* Niclas Gustafsson (nulleman @ sf) */
 1586     {"Nikon:D50 (PTP mode)",          0x04b0, 0x040a, PTP_CAP}, /* no hidden props */
 1587     /* Didier Gasser-Morlay <didiergm@gmail.com> */
 1588     {"Nikon:D2Hs (PTP mode)",     0x04b0, 0x040c, PTP_CAP},
 1589     {"Nikon:DSC D70s (PTP mode)",     0x04b0, 0x040e, PTP_CAP},
 1590     /* Jana Jaeger <jjaeger.suse.de> */
 1591     {"Nikon:DSC D200 (PTP mode)",     0x04b0, 0x0410, PTP_CAP},
 1592     /* Christian Deckelmann @ SUSE */
 1593     {"Nikon:DSC D80 (PTP mode)",      0x04b0, 0x0412, PTP_CAP},
 1594     /* Huy Hoang <hoang027@umn.edu> */
 1595     {"Nikon:DSC D40 (PTP mode)",      0x04b0, 0x0414, PTP_CAP},
 1596     /* Mark de Ruijter <mark@ridersoft.net> */
 1597     {"Nikon:DSC D2Xs (PTP mode)",     0x04b0, 0x0416, PTP_CAP},
 1598     /* Luca Gervasi <luca.gervasi@gmail.com> */
 1599     {"Nikon:DSC D40x (PTP mode)",     0x04b0, 0x0418, PTP_CAP},
 1600     /* Andreas Jaeger <aj@suse.de>.
 1601      * Marcus: MTP Proplist does not return objectsizes ... useless. */
 1602     {"Nikon:DSC D300 (PTP mode)",     0x04b0, 0x041a, PTP_CAP},
 1603     /* Pat Shanahan, http://sourceforge.net/tracker/index.php?func=detail&aid=1924511&group_id=8874&atid=358874 */
 1604     {"Nikon:D3 (PTP mode)",       0x04b0, 0x041c, PTP_CAP},
 1605     /* irc reporter Benjamin Schindler */
 1606     {"Nikon:DSC D60 (PTP mode)",      0x04b0, 0x041e, PTP_CAP},
 1607 
 1608     /* pbj304 pbj@ecs.soton.ac.uk */
 1609     {"Nikon:DSC D3x (PTP mode)",      0x04b0, 0x0420, PTP_CAP|PTP_CAP_PREVIEW},
 1610 
 1611     /* Will Stephenson at SUSE and wstephenson@flickr */
 1612     {"Nikon:DSC D90 (PTP mode)",      0x04b0, 0x0421, PTP_CAP|PTP_CAP_PREVIEW},
 1613     /* Borrowed D700 by deckel / marcus at SUSE */
 1614     {"Nikon:DSC D700 (PTP mode)",     0x04b0, 0x0422, PTP_CAP|PTP_CAP_PREVIEW},
 1615     /* Stephan Barth at SUSE */
 1616     {"Nikon:DSC D5000 (PTP mode)",    0x04b0, 0x0423, PTP_CAP|PTP_CAP_PREVIEW},
 1617     /* IRC reporter */
 1618     {"Nikon:DSC D3000 (PTP mode)",    0x04b0, 0x0424, PTP_CAP},
 1619     /* Andreas Dielacher <andreas.dielacher@gmail.com> */
 1620     {"Nikon:DSC D300s (PTP mode)",    0x04b0, 0x0425, PTP_CAP|PTP_CAP_PREVIEW},
 1621     /* Matthias Blaicher <blaicher@googlemail.com> */
 1622     {"Nikon:DSC D3s (PTP mode)",      0x04b0, 0x0426, PTP_CAP|PTP_CAP_PREVIEW},
 1623     /* SWPLinux IRC reporter... does not have liveview -lowend model. */
 1624     {"Nikon:DSC D3100 (PTP mode)",    0x04b0, 0x0427, PTP_CAP},
 1625     /* http://sourceforge.net/tracker/?func=detail&atid=358874&aid=3140014&group_id=8874 */
 1626     {"Nikon:DSC D7000 (PTP mode)",    0x04b0, 0x0428, PTP_CAP|PTP_CAP_PREVIEW},
 1627 
 1628     /* IRC Reporter popolon */
 1629     {"Nikon:DSC D5100 (PTP mode)",    0x04b0, 0x0429, PTP_CAP|PTP_CAP_PREVIEW},
 1630 
 1631     /* "François G." <francois@webcampak.com> */
 1632     {"Nikon:DSC D800",            0x04b0, 0x042a, PTP_CAP|PTP_CAP_PREVIEW},
 1633 
 1634     /* Christian Deckelmann of Xerox */
 1635     {"Nikon:DSC D4",              0x04b0, 0x042b, PTP_CAP|PTP_CAP_PREVIEW},
 1636 
 1637     /* Lihuijun <lihuiplus@hotmail.com> */
 1638     {"Nikon:DSC D3200",           0x04b0, 0x042c, PTP_CAP|PTP_CAP_PREVIEW},
 1639 
 1640     /* t.ludewig@gmail.com */
 1641     {"Nikon:DSC D600",            0x04b0, 0x042d, PTP_CAP|PTP_CAP_PREVIEW},
 1642     /* Roderick Stewart <roderick.stewart@gmail.com> */
 1643     {"Nikon:DSC D800E",               0x04b0, 0x042e, PTP_CAP|PTP_CAP_PREVIEW},
 1644     /* Simeon Pilgrim <simeon.pilgrim@gmail.com> */
 1645     {"Nikon:DSC D5200",               0x04b0, 0x042f, PTP_CAP|PTP_CAP_PREVIEW},
 1646 
 1647     /* t.ludewig@gmail.com */
 1648     {"Nikon:DSC D7100",               0x04b0, 0x0430, PTP_CAP|PTP_CAP_PREVIEW},
 1649 
 1650     /* Kirill Bogdanenk <kirill.bogdanenko@gmail.com> via kde bug 336523 */
 1651     {"Nikon:DSC D5300",               0x04b0, 0x0431, PTP_CAP|PTP_CAP_PREVIEW},
 1652 
 1653     /* Andre Crone <andre@elysia.nl> */
 1654     {"Nikon:DSC Df",                  0x04b0, 0x0432, PTP_CAP|PTP_CAP_PREVIEW},
 1655 
 1656     /* https://sourceforge.net/p/gphoto/feature-requests/449/ */
 1657     {"Nikon:DSC D3300",               0x04b0, 0x0433, PTP_CAP|PTP_CAP_PREVIEW},
 1658 
 1659     /* Andre Crone <andre@elysia.nl> */
 1660     {"Nikon:DSC D610",                0x04b0, 0x0434, PTP_CAP|PTP_CAP_PREVIEW},
 1661 
 1662     /* Andre Crone <andre@elysia.nl> */
 1663     {"Nikon:DSC D4s",         0x04b0, 0x0435, PTP_CAP|PTP_CAP_PREVIEW},
 1664 
 1665     /* Jeremie FROLI <jfroli@webmail.alten.fr> */
 1666     {"Nikon:DSC D810",                0x04b0, 0x0436, PTP_CAP|PTP_CAP_PREVIEW},
 1667 
 1668     /*Jürgen Blumenschein <blumenschein@huntington-info.eu> */
 1669     {"Nikon:DSC D750",                0x04b0, 0x0437, PTP_CAP|PTP_CAP_PREVIEW},
 1670 
 1671     /* Jeffrey Wilson <colgs3b@gmail.com> */
 1672     {"Nikon:DSC D5500",       0x04b0, 0x0438, PTP_CAP|PTP_CAP_PREVIEW},
 1673 
 1674     /* https://github.com/gphoto/libgphoto2/issues/83 */
 1675     {"Nikon:DSC D7200",       0x04b0, 0x0439, PTP_CAP|PTP_CAP_PREVIEW},
 1676 
 1677     /* Laurent Zylberman <l.zylberman@graphix-images.com> */
 1678     {"Nikon:DSC D5",          0x04b0, 0x043a, PTP_CAP|PTP_CAP_PREVIEW},
 1679 
 1680     /* Andre Crone <andre@elysia.nl> */
 1681     {"Nikon:DSC D810A",               0x04b0, 0x043b, PTP_CAP|PTP_CAP_PREVIEW},
 1682 
 1683     /* bob@360degreeviews.com */
 1684     {"Nikon:DSC D500",                0x04b0, 0x043c, PTP_CAP|PTP_CAP_PREVIEW},
 1685 
 1686     /* Chris P <cpeace@gmail.com> */
 1687     {"Nikon:DSC D3400",               0x04b0, 0x043d, PTP_CAP|PTP_CAP_PREVIEW},
 1688 
 1689     /* Phil Stephenson <filstephenson@gmail.com> */
 1690     {"Nikon:DSC D5600",               0x04b0, 0x043f, PTP_CAP|PTP_CAP_PREVIEW},
 1691 
 1692     /* Satoshi Kubota */
 1693     {"Nikon:DSC D7500",               0x04b0, 0x0440, PTP_CAP|PTP_CAP_PREVIEW},
 1694 
 1695     /* Andre Crone <visuals@elysia.nl> */
 1696     {"Nikon:DSC D850",                0x04b0, 0x0441, PTP_CAP|PTP_CAP_PREVIEW},
 1697 
 1698     /* Horshack ?? <horshack@live.com> */
 1699     {"Nikon:Z7",                      0x04b0, 0x0442, PTP_CAP|PTP_CAP_PREVIEW},
 1700 
 1701     /* Marcus Meissner */
 1702     {"Nikon:Z6",                      0x04b0, 0x0443, PTP_CAP|PTP_CAP_PREVIEW},
 1703 
 1704     /* Daniel Baertschi <daniel@avisec.ch> */
 1705     {"Nikon:Z50",                     0x04b0, 0x0444, PTP_CAP|PTP_CAP_PREVIEW},
 1706 
 1707     /* Schreiber, Steve via Gphoto-devel */
 1708     {"Nikon:DSC D3500",       0x04b0, 0x0445, PTP_CAP|PTP_CAP_PREVIEW},
 1709 
 1710     /* timelapse-VIEW */
 1711     {"Nikon:DSC D780",        0x04b0, 0x0446, PTP_CAP|PTP_CAP_PREVIEW},
 1712 
 1713     /* Thomas Schaad */
 1714     {"Nikon:Z5",                      0x04b0, 0x0448, PTP_CAP|PTP_CAP_PREVIEW},
 1715 
 1716     /* Fahrion <fahrion.2600@gmail.com> */
 1717     {"Nikon:Z7_2",                    0x04b0, 0x044b, PTP_CAP|PTP_CAP_PREVIEW},
 1718 
 1719     /* Thomas Schaad <tom@avisec.ch> */
 1720     {"Nikon:Z6_2",                    0x04b0, 0x044c, PTP_CAP|PTP_CAP_PREVIEW},
 1721 
 1722     /* http://sourceforge.net/tracker/?func=detail&aid=3536904&group_id=8874&atid=108874 */
 1723     /* https://github.com/gphoto/libgphoto2/issues/569 */
 1724     {"Nikon:V1",              0x04b0, 0x0601, PTP_CAP|PTP_NIKON_1},
 1725     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=3556403&group_id=8874 */
 1726     {"Nikon:J1",              0x04b0, 0x0602, PTP_CAP|PTP_NIKON_1},
 1727     /* https://bugzilla.novell.com/show_bug.cgi?id=814622 Martin Caj at SUSE */
 1728     {"Nikon:J2",              0x04b0, 0x0603, PTP_CAP|PTP_NIKON_1},
 1729     /* https://sourceforge.net/p/gphoto/feature-requests/432/ */
 1730     {"Nikon:V2",              0x04b0, 0x0604, PTP_CAP|PTP_NIKON_1},
 1731     /* Ralph Schindler <ralph@ralphschindler.com> */
 1732     {"Nikon:J3",              0x04b0, 0x0605, PTP_CAP|PTP_NIKON_1},
 1733     /* Markus Karlhuber <markus.karlhuber@gmail.com> */
 1734     {"Nikon:S1",              0x04b0, 0x0606, PTP_CAP|PTP_NIKON_1},
 1735     /* Tarjei Husøy <git@thusoy.com> */
 1736     {"Nikon:S2",              0x04b0, 0x0608, PTP_CAP|PTP_NIKON_1},
 1737     /* Raj Kumar <raj@archive.org> */
 1738     {"Nikon:J4",              0x04b0, 0x0609, PTP_CAP|PTP_NIKON_1},
 1739     /* Alexander Smith <a.smith@precisionhawk.com> */
 1740     {"Nikon:V3",              0x04b0, 0x060a, PTP_CAP|PTP_NIKON_1},
 1741 
 1742     /* Wolfgang Goetz <Wolfgang.ztoeG@web.de> */
 1743     {"Nikon:J5",              0x04b0, 0x060b, PTP_CAP|PTP_NIKON_1},
 1744 
 1745 #if 0
 1746     /* Thomas Luzat <thomas.luzat@gmx.net> */
 1747     /* this was reported as not working, mass storage only:
 1748      * http://sourceforge.net/tracker/index.php?func=detail&aid=1847471&group_id=8874&atid=108874
 1749     {"Panasonic:DMC-FZ20 (alternate id)", 0x04da, 0x2372, 0},
 1750     */
 1751     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1350226&group_id=8874&atid=208874 */
 1752     {"Panasonic:DMC-LZ2",             0x04da, 0x2372, 0},
 1753     /* https://sourceforge.net/tracker/index.php?func=detail&aid=1405541&group_id=8874&atid=358874 */
 1754     {"Panasonic:DMC-LC1",             0x04da, 0x2372, 0},
 1755     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1275100&group_id=8874&atid=358874 */
 1756     {"Panasonic:Lumix FZ5",           0x04da, 0x2372, 0},
 1757 #endif
 1758 
 1759     /* so the GX8 reports the same USB ids as others, but has capture support. See debuglog. */
 1760     {"Panasonic:DMC-GX8",             0x04da, 0x2374, PTP_CAP|PTP_CAP_PREVIEW},
 1761     {"Panasonic:DMC-FZ20",            0x04da, 0x2374, 0},
 1762     {"Panasonic:DMC-FZ45",            0x04da, 0x2374, 0},
 1763     {"Panasonic:DMC-FZ38",            0x04da, 0x2374, 0},
 1764     {"Panasonic:DMC-FZ50",            0x04da, 0x2374, 0},
 1765     {"Panasonic:DMC-LS2",             0x04da, 0x2374, 0},
 1766     /* from Tomas Herrdin <tomas.herrdin@swipnet.se> */
 1767     {"Panasonic:DMC-LS3",             0x04da, 0x2374, 0},
 1768     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2070864&group_id=8874&atid=358874 */
 1769     {"Panasonic:DMC-TZ15",        0x04da, 0x2374, 0},
 1770     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=2950529&group_id=8874 */
 1771     {"Panasonic:DMC-FS62",        0x04da, 0x2374, 0},
 1772     {"Panasonic:DMC-TZ18",        0x04da, 0x2374, 0},
 1773     /* Jean Ribière <jean.ribiere@orange.fr> */
 1774     {"Panasonic:DMC-TZ8",         0x04da, 0x2374, 0},
 1775     {"Panasonic:DMC-LX7",         0x04da, 0x2374, 0},
 1776     /* Constantin B <klochto@gmail.com> */
 1777     {"Panasonic:DMC-GF1",             0x04da, 0x2374, 0},
 1778 
 1779     {"Panasonic:DC-GH5",          0x04da, 0x2382, PTP_CAP|PTP_CAP_PREVIEW},
 1780 
 1781 
 1782     /* Søren Krarup Olesen <sko@acoustics.aau.dk> */
 1783     {"Leica:D-LUX 2",         0x04da, 0x2375, 0},
 1784     /* Graham White <g.graham.white@gmail.com> */
 1785     {"Leica:SL",              0x04da, 0x2041, 0},
 1786 
 1787     /* http://callendor.zongo.be/wiki/OlympusMju500 */
 1788     {"Olympus:mju 500",               0x07b4, 0x0113, 0},
 1789 
 1790         /* Olympus wrap test code */
 1791     {"Olympus:E series (Control)",    0x07b4, 0x0110, PTP_OLYMPUS_XML},
 1792 
 1793 #if 0 /* talks PTP via SCSI vendor command backchannel, like above. */
 1794     {"Olympus:E-410 (UMS 2 mode)",    0x07b4, 0x0118, 0}, /* not XML wrapped */
 1795 #endif
 1796 
 1797     /* From VICTOR <viaaurea@yahoo.es> */
 1798     {"Olympus:C-350Z",                0x07b4, 0x0114, 0},
 1799     {"Olympus:D-560Z",                0x07b4, 0x0114, 0},
 1800     {"Olympus:X-250",                 0x07b4, 0x0114, 0},
 1801     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1349900&group_id=8874&atid=108874 */
 1802     {"Olympus:C-310Z",                0x07b4, 0x0114, 0},
 1803     {"Olympus:D-540Z",                0x07b4, 0x0114, 0},
 1804     {"Olympus:X-100",                 0x07b4, 0x0114, 0},
 1805     /* https://sourceforge.net/tracker/index.php?func=detail&aid=1442115&group_id=8874&atid=358874 */
 1806     {"Olympus:C-55Z",                 0x07b4, 0x0114, 0},
 1807     {"Olympus:C-5500Z",               0x07b4, 0x0114, 0},
 1808 
 1809     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=1272944&group_id=8874 */
 1810     {"Olympus:IR-300",                0x07b4, 0x0114, 0},
 1811 
 1812     /* Marcus */
 1813     {"Olympus:FE4000",                0x07b4, 0x0116, 0},
 1814     {"Olympus:X920",                  0x07b4, 0x0116, 0},
 1815     {"Olympus:X925",                  0x07b4, 0x0116, 0},
 1816     {"Olympus:VR360",                 0x07b4, 0x0116, 0},
 1817 
 1818     /* Jonas Rani Hatem <jr@hatem.be> */
 1819     {"Olympus:TG-620",                0x07b4, 0x0125, 0},
 1820 
 1821     /* t.ludewig@gmail.com */
 1822     {"Olympus:SP-720UZ",          0x07b4, 0x012f, 0},
 1823     {"Olympus:E-PL5",         0x07b4, 0x012f, 0},
 1824     /* Rafał Bryndza <abigor82@gmail.com> */
 1825     {"Olympus:E-M5",          0x07b4, 0x012f, 0},
 1826     /* Richard Wonka <richard.wonka@gmail.com> */
 1827     {"Olympus:E-M5 Mark II",      0x07b4, 0x0130, PTP_CAP|PTP_CAP_PREVIEW},
 1828     /* same id also on E-M1 */
 1829     {"Olympus:E-M1 Mark II",      0x07b4, 0x0130, PTP_CAP|PTP_CAP_PREVIEW},
 1830     {"Olympus:E-M1",          0x07b4, 0x0130, PTP_CAP|PTP_CAP_PREVIEW},
 1831 
 1832     /* from timelapse-VIEW */
 1833     {"Olympus:E-M1 MII",          0x07b4, 0x0135, PTP_CAP|PTP_CAP_PREVIEW},
 1834 
 1835     /* IRC report */
 1836     {"Casio:EX-Z120",                 0x07cf, 0x1042, 0},
 1837     /* Andrej Semen (at suse) */
 1838     {"Casio:EX-S770",                 0x07cf, 0x1049, 0},
 1839     /* https://launchpad.net/bugs/64146 */
 1840     {"Casio:EX-Z700",                 0x07cf, 0x104c, 0},
 1841     /* IRC Reporter */
 1842     {"Casio:EX-Z65",                  0x07cf, 0x104d, 0},
 1843 
 1844     /* Juan Carlos Bretal Fernandez <juanc.bretal@gmail.com> */
 1845     {"Casio:EX-ZR700",                0x07cf, 0x117a, 0},
 1846 
 1847     /* (at least some) newer Canon cameras can be switched between
 1848      * PTP and "normal" (i.e. Canon) mode
 1849      * Canon PS G3: A. Marinichev, 20 nov 2002
 1850      */
 1851     {"Canon:PowerShot S45 (PTP mode)",      0x04a9, 0x306d, PTPBUG_DELETE_SENDS_EVENT},
 1852         /* 0x306c is S45 in normal (canon) mode */
 1853     {"Canon:PowerShot G3 (PTP mode)",       0x04a9, 0x306f, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1854         /* 0x306e is G3 in normal (canon) mode */
 1855     {"Canon:PowerShot S230 (PTP mode)",     0x04a9, 0x3071, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1856         /* 0x3070 is S230 in normal (canon) mode */
 1857     {"Canon:Digital IXUS v3 (PTP mode)",    0x04a9, 0x3071, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1858         /* it's the same as S230 */
 1859 
 1860     {"Canon:Digital IXUS II (PTP mode)",    0x04a9, 0x3072, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1861     {"Canon:PowerShot SD100 (PTP mode)",    0x04a9, 0x3072, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1862     {"Canon:PowerShot A70 (PTP)",           0x04a9, 0x3073, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1863     {"Canon:PowerShot A60 (PTP)",           0x04a9, 0x3074, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1864         /* IXUS 400 has the same PID in both modes, Till Kamppeter */
 1865     {"Canon:Digital IXUS 400 (PTP mode)",   0x04a9, 0x3075, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1866     {"Canon:PowerShot S400 (PTP mode)", 0x04a9, 0x3075, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1867     {"Canon:PowerShot A300 (PTP mode)",     0x04a9, 0x3076, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1868     {"Canon:PowerShot S50 (PTP mode)",      0x04a9, 0x3077, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1869     {"Canon:PowerShot G5 (PTP mode)",       0x04a9, 0x3085, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1870     {"Canon:Elura 50 (PTP mode)",           0x04a9, 0x3087, PTPBUG_DELETE_SENDS_EVENT},
 1871     {"Canon:MVX3i (PTP mode)",              0x04a9, 0x308d, PTPBUG_DELETE_SENDS_EVENT},
 1872         /* 0x3084 is the EOS 300D/Digital Rebel in normal (canon) mode */
 1873     {"Canon:EOS 300D (PTP mode)",           0x04a9, 0x3099, 0},
 1874     {"Canon:EOS Digital Rebel (PTP mode)",  0x04a9, 0x3099, 0},
 1875     {"Canon:EOS Kiss Digital (PTP mode)",   0x04a9, 0x3099, 0},
 1876     {"Canon:PowerShot A80 (PTP)",           0x04a9, 0x309a, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1877     {"Canon:Digital IXUS i (PTP mode)",     0x04a9, 0x309b, PTPBUG_DELETE_SENDS_EVENT},
 1878     {"Canon:PowerShot S1 IS (PTP mode)",    0x04a9, 0x309c, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1879     {"Canon:MV750i (PTP mode)",         0x04a9, 0x30a0, PTPBUG_DELETE_SENDS_EVENT},
 1880     /* Canon Elura 65, provolone on #gphoto on 2006-12-17 */
 1881     {"Canon:Elura 65 (PTP mode)",           0x04a9, 0x30a5, PTPBUG_DELETE_SENDS_EVENT},
 1882     {"Canon:Powershot S70 (PTP mode)",      0x04a9, 0x30b1, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1883     {"Canon:Powershot S60 (PTP mode)",      0x04a9, 0x30b2, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1884     {"Canon:Powershot G6 (PTP mode)",       0x04a9, 0x30b3, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1885     {"Canon:Digital IXUS 500 (PTP mode)",   0x04a9, 0x30b4, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1886     {"Canon:PowerShot S500 (PTP mode)",     0x04a9, 0x30b4, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1887     {"Canon:PowerShot A75 (PTP mode)",      0x04a9, 0x30b5, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1888     {"Canon:PowerShot SD110 (PTP mode)",    0x04a9, 0x30b6, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1889     {"Canon:Digital IXUS IIs (PTP mode)",   0x04a9, 0x30b6, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1890     {"Canon:PowerShot A400 (PTP mode)",     0x04a9, 0x30b7, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1891     {"Canon:PowerShot A310 (PTP mode)",     0x04a9, 0x30b8, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1892     {"Canon:PowerShot A85 (PTP mode)",      0x04a9, 0x30b9, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1893     {"Canon:Digital IXUS 430 (PTP mode)",   0x04a9, 0x30ba, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1894     {"Canon:PowerShot S410 (PTP mode)",     0x04a9, 0x30ba, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1895     {"Canon:PowerShot A95 (PTP mode)",      0x04a9, 0x30bb, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1896     {"Canon:EOS 10D (PTP mode)",        0x04a9, 0x30bc, PTPBUG_DELETE_SENDS_EVENT},
 1897     {"Canon:Digital IXUS 40 (PTP mode)",    0x04a9, 0x30bf, PTPBUG_DELETE_SENDS_EVENT},
 1898 #if 0
 1899     /* the 30c0 id cannot remote capture, use normal mode. */
 1900     {"Canon:PowerShot SD200 (PTP mode)",    0x04a9, 0x30c0, PTPBUG_DELETE_SENDS_EVENT},
 1901     {"Canon:Digital IXUS 30 (PTP mode)",    0x04a9, 0x30c0, PTPBUG_DELETE_SENDS_EVENT},
 1902 #endif
 1903     {"Canon:PowerShot A520 (PTP mode)",     0x04a9, 0x30c1, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1904     {"Canon:PowerShot A510 (PTP mode)",     0x04a9, 0x30c2, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1905     {"Canon:EOS 1D Mark II (PTP mode)",     0x04a9, 0x30ea, 0},
 1906     {"Canon:EOS 20D (PTP mode)",            0x04a9, 0x30ec, 0},
 1907     /* 30ef is the ID in explicit PTP mode.
 1908      * 30ee is the ID with the camera in Canon mode, but the camera reacts to
 1909      * PTP commands according to:
 1910      * https://sourceforge.net/tracker/?func=detail&atid=108874&aid=1394326&group_id=8874
 1911      * They need to have different names.
 1912      */
 1913     {"Canon:EOS 350D (PTP mode)",           0x04a9, 0x30ee, 0},
 1914     {"Canon:EOS 350D",                      0x04a9, 0x30ef, 0},
 1915     {"Canon:PowerShot S2 IS (PTP mode)",    0x04a9, 0x30f0, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1916     {"Canon:PowerShot SD430 (PTP mode)",    0x04a9, 0x30f1, PTPBUG_DELETE_SENDS_EVENT},
 1917     {"Canon:Digital IXUS Wireless (PTP mode)",0x04a9, 0x30f1, PTPBUG_DELETE_SENDS_EVENT},
 1918     {"Canon:Digital IXUS 700 (PTP mode)",   0x04a9, 0x30f2, PTPBUG_DELETE_SENDS_EVENT},
 1919     {"Canon:PowerShot SD500 (PTP mode)",    0x04a9, 0x30f2, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1920     /* reported by Gilles Dartiguelongue <dartigug@esiee.fr> */
 1921     {"Canon:Digital IXUS iZ (PTP mode)",    0x04a9, 0x30f4, PTPBUG_DELETE_SENDS_EVENT},
 1922     /* A340, Andreas Stempfhuber <andi@afulinux.de> */
 1923     {"Canon:PowerShot A430 (PTP mode)",     0x04a9, 0x30f8, PTPBUG_DELETE_SENDS_EVENT},
 1924     /* Conan Colx, A410, gphoto-Feature Requests-1342538 */
 1925     {"Canon:PowerShot A410 (PTP mode)",     0x04a9, 0x30f9, PTPBUG_DELETE_SENDS_EVENT},
 1926     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1411976&group_id=8874&atid=358874 */
 1927     {"Canon:PowerShot S80 (PTP mode)",      0x04a9, 0x30fa, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1928     /* A620, Tom Roelz */
 1929     {"Canon:PowerShot A620 (PTP mode)",     0x04a9, 0x30fc, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1930     /* A610, Andriy Kulchytskyy <whoops@ukrtop.com> */
 1931     {"Canon:PowerShot A610 (PTP mode)",     0x04a9, 0x30fd, PTPBUG_DELETE_SENDS_EVENT},
 1932     /* Irc Reporter */
 1933     {"Canon:PowerShot SD630 (PTP mode)",    0x04a9, 0x30fe, PTPBUG_DELETE_SENDS_EVENT},
 1934     {"Canon:Digital IXUS 65 (PTP mode)",    0x04a9, 0x30fe, PTPBUG_DELETE_SENDS_EVENT},
 1935     /* Rob Lensen <rob@bsdfreaks.nl> */
 1936     {"Canon:Digital IXUS 55 (PTP mode)",    0x04a9, 0x30ff, 0},
 1937     {"Canon:PowerShot SD450 (PTP mode)",    0x04a9, 0x30ff, 0},
 1938     {"Canon:Optura 600 (PTP mode)",         0x04a9, 0x3105, 0},
 1939     /* Jeff Mock <jeff@mock.com> */
 1940     {"Canon:EOS 5D (PTP mode)",             0x04a9, 0x3102, 0},
 1941     /* Nick Richards <nick@nedrichards.com> */
 1942     {"Canon:Digital IXUS 50 (PTP mode)",    0x04a9, 0x310e, PTPBUG_DELETE_SENDS_EVENT},
 1943     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1640547&group_id=8874&atid=358874 */
 1944     {"Canon:PowerShot A420 (PTP mode)",     0x04a9, 0x310f, PTPBUG_DELETE_SENDS_EVENT},
 1945     /* Some Canon 400D do not have the infamous PTP bug, but some do.
 1946      * see http://bugs.kde.org/show_bug.cgi?id=141577 -Marcus */
 1947     {"Canon:EOS 400D (PTP mode)",           0x04a9, 0x3110, PTP_CAP},
 1948     {"Canon:EOS Digital Rebel XTi (PTP mode)", 0x04a9, 0x3110, PTP_CAP},
 1949     {"Canon:EOS Kiss Digital X (PTP mode)", 0x04a9, 0x3110, PTP_CAP},
 1950     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=1456391&group_id=8874 */
 1951     {"Canon:EOS 30D (PTP mode)",            0x04a9, 0x3113, PTP_CAP},
 1952     {"Canon:Digital IXUS 900Ti (PTP mode)", 0x04a9, 0x3115, 0},
 1953     {"Canon:PowerShot SD900 (PTP mode)",    0x04a9, 0x3115, 0},
 1954     {"Canon:Digital IXUS 750 (PTP mode)",   0x04a9, 0x3116, PTPBUG_DELETE_SENDS_EVENT},
 1955     {"Canon:PowerShot A700 (PTP mode)",     0x04a9, 0x3117, PTPBUG_DELETE_SENDS_EVENT},
 1956     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1498577&group_id=8874&atid=358874 */
 1957     {"Canon:PowerShot SD700 (PTP mode)",    0x04a9, 0x3119, PTPBUG_DELETE_SENDS_EVENT},
 1958     {"Canon:Digital IXUS 800 (PTP mode)",   0x04a9, 0x3119, PTPBUG_DELETE_SENDS_EVENT},
 1959     /* Gert Vervoort <gert.vervoort@hccnet.nl> */
 1960     {"Canon:PowerShot S3 IS (PTP mode)",    0x04a9, 0x311a, PTP_CAP|PTP_CAP_PREVIEW},
 1961     /* David Goodenough <david.goodenough at linkchoose.co.uk> */
 1962     {"Canon:PowerShot A540 (PTP mode)",     0x04a9, 0x311b, PTPBUG_DELETE_SENDS_EVENT},
 1963     /* Irc reporter */
 1964     {"Canon:Digital IXUS 60 (PTP mode)",    0x04a9, 0x311c, PTPBUG_DELETE_SENDS_EVENT},
 1965     {"Canon:PowerShot SD600 (PTP mode)",    0x04a9, 0x311c, PTPBUG_DELETE_SENDS_EVENT},
 1966     /* Harald Dunkel <harald.dunkel@t-online.de> */
 1967     {"Canon:PowerShot G7 (PTP mode)",   0x04a9, 0x3125, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1968     /* Ales Kozumplik <kozumplik@gmail.com> */
 1969     {"Canon:PowerShot A530 (PTP mode)",     0x04a9, 0x3126, PTPBUG_DELETE_SENDS_EVENT},
 1970     /* Jerome Vizcaino <vizcaino_jerome@yahoo.fr> */
 1971     {"Canon:Digital IXUS 850 IS (PTP mode)",0x04a9, 0x3136, PTPBUG_DELETE_SENDS_EVENT},
 1972     /* https://launchpad.net/bugs/64146 */
 1973     {"Canon:PowerShot SD40 (PTP mode)", 0x04a9, 0x3137, PTPBUG_DELETE_SENDS_EVENT},
 1974     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1565043&group_id=8874&atid=358874 */
 1975     {"Canon:PowerShot A710 IS (PTP mode)",  0x04a9, 0x3138, PTPBUG_DELETE_SENDS_EVENT},
 1976     /* Thomas Roelz at SUSE, MTP proplist does not work (hangs) */
 1977     {"Canon:PowerShot A640 (PTP mode)",     0x04a9, 0x3139, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 1978     {"Canon:PowerShot A630 (PTP mode)",     0x04a9, 0x313a, PTPBUG_DELETE_SENDS_EVENT},
 1979     /* Deti Fliegl.
 1980      * Marcus: supports MTP proplists, but these are 2 times slower than regular
 1981      * data retrieval. */
 1982     {"Canon:EOS 450D (PTP mode)",       0x04a9, 0x3145, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 1983     {"Canon:EOS Rebel XSi (PTP mode)",      0x04a9, 0x3145, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 1984     {"Canon:EOS Kiss X2 (PTP mode)",        0x04a9, 0x3145, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 1985     /* reported by Ferry Huberts */
 1986     {"Canon:EOS 40D (PTP mode)",        0x04a9, 0x3146, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 1987 
 1988     /* reported by: gphoto@lunkwill.org */
 1989     {"Canon:EOS 1D Mark III (PTP mode)",    0x04a9, 0x3147, PTP_CAP},
 1990 
 1991     {"Canon:PowerShot S5 IS (PTP mode)",    0x04a9, 0x3148, PTP_CAP|PTP_CAP_PREVIEW},
 1992     /* AlannY <alanny@starlink.ru> */
 1993     {"Canon:PowerShot A460 (PTP mode)", 0x04a9, 0x3149, PTP_CAP|PTP_CAP_PREVIEW},
 1994     /* Tobias Blaser <tblaser@gmx.ch> */
 1995     {"Canon:Digital IXUS 950 IS (PTP mode)",0x04a9, 0x314b, PTPBUG_DELETE_SENDS_EVENT},
 1996     /* https://bugs.launchpad.net/bugs/206627 */
 1997     {"Canon:PowerShot SD850 (PTP mode)",    0x04a9, 0x314b, PTPBUG_DELETE_SENDS_EVENT},
 1998     {"Canon:PowerShot A570 IS (PTP mode)",  0x04a9, 0x314c, PTPBUG_DELETE_SENDS_EVENT},
 1999     {"Canon:PowerShot A560 (PTP mode)",     0x04a9, 0x314d, PTPBUG_DELETE_SENDS_EVENT},
 2000     /* mailreport from sec@dschroeder.info */
 2001     {"Canon:Digital IXUS 75 (PTP mode)",    0x04a9, 0x314e, PTPBUG_DELETE_SENDS_EVENT},
 2002     {"Canon:PowerShot SD750 (PTP mode)",    0x04a9, 0x314e, PTPBUG_DELETE_SENDS_EVENT},
 2003     /* Marcus: MTP Proplist does not work at all here, it just hangs */
 2004     {"Canon:Digital IXUS 70 (PTP mode)",    0x04a9, 0x314f, PTPBUG_DELETE_SENDS_EVENT},
 2005     {"Canon:PowerShot SD1000 (PTP mode)",   0x04a9, 0x314f, PTPBUG_DELETE_SENDS_EVENT},
 2006     {"Canon:PowerShot A550 (PTP mode)",     0x04a9, 0x3150, PTPBUG_DELETE_SENDS_EVENT},
 2007     /* https://launchpad.net/bugs/64146 */
 2008     {"Canon:PowerShot A450 (PTP mode)",     0x04a9, 0x3155, PTPBUG_DELETE_SENDS_EVENT},
 2009     /* Harald Dunkel <harald.dunkel@t-online.de> */
 2010     {"Canon:PowerShot G9 (PTP mode)",       0x04a9, 0x315a, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 2011     /* Barrie Stott <zen146410@zen.co.uk> */
 2012     {"Canon:PowerShot A650IS (PTP mode)",   0x04a9, 0x315b, PTP_CAP|PTP_CAP_PREVIEW},
 2013     /* Roger Lynn <roger@rilynn.demon.co.uk> */
 2014     {"Canon:PowerShot A720 IS (PTP mode)",  0x04a9, 0x315d, PTPBUG_DELETE_SENDS_EVENT},
 2015     /* Mats Petersson <mats.petersson@ltu.se> */
 2016     {"Canon:Powershot SX100 IS (PTP mode)", 0x04a9, 0x315e, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 2017     /* "[AvataR]" <public.avatar@gmail.com> */
 2018     {"Canon:Digital IXUS 960 IS (PTP mode)",0x04a9, 0x315f, PTPBUG_DELETE_SENDS_EVENT},
 2019     /* Ruben Vandamme <vandamme.ruben@belgacom.net> */
 2020     {"Canon:Digital IXUS 860 IS",       0x04a9, 0x3160, PTPBUG_DELETE_SENDS_EVENT},
 2021 
 2022     /* Christian P. Schmidt" <schmidt@digadd.de> */
 2023     {"Canon:Digital IXUS 970 IS",       0x04a9, 0x3173, PTPBUG_DELETE_SENDS_EVENT},
 2024 
 2025     /* Martin Lasarsch at SUSE. MTP_PROPLIST returns just 0 entries */
 2026     {"Canon:Digital IXUS 90 IS",        0x04a9, 0x3174, PTPBUG_DELETE_SENDS_EVENT},
 2027     /* Daniel Moyne <daniel.moyne@free.fr> */
 2028     {"Canon:Powershot SD790 IS",        0x04a9, 0x3174, PTPBUG_DELETE_SENDS_EVENT},
 2029 
 2030     /* https://sourceforge.net/tracker/?func=detail&aid=2722422&group_id=8874&atid=358874 */
 2031     {"Canon:Digital IXUS 85 IS",        0x04a9, 0x3174, PTPBUG_DELETE_SENDS_EVENT},
 2032 
 2033     /* Theodore Kilgore <kilgota@banach.math.auburn.edu> */
 2034     {"Canon:PowerShot SD770 IS",        0x04a9, 0x3175, PTPBUG_DELETE_SENDS_EVENT},
 2035 
 2036     /* Olaf Hering at SUSE */
 2037     {"Canon:PowerShot A590 IS",     0x04a9, 0x3176, PTPBUG_DELETE_SENDS_EVENT},
 2038 
 2039     /* Dmitriy Khanzhin <jinn@altlinux.org> */
 2040     {"Canon:PowerShot A580",        0x04a9, 0x3177, PTPBUG_DELETE_SENDS_EVENT},
 2041 
 2042     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2602638&group_id=8874&atid=108874 */
 2043     {"Canon:PowerShot A470",        0x04a9, 0x317a, PTPBUG_DELETE_SENDS_EVENT},
 2044     /* Michael Plucik <michaelplucik@googlemail.com> */
 2045     {"Canon:EOS 1000D",         0x04a9, 0x317b, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 2046 
 2047     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=1910010&group_id=8874 */
 2048     {"Canon:Digital IXUS 80 IS",        0x04a9, 0x3184, PTPBUG_DELETE_SENDS_EVENT},
 2049     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2391422&group_id=8874&atid=358874 */
 2050     {"Canon:Powershot SD1100 IS",       0x04a9, 0x3184, PTPBUG_DELETE_SENDS_EVENT},
 2051     /* Hubert Mercier <hubert.mercier@unilim.fr> */
 2052     {"Canon:PowerShot SX10 IS",     0x04a9, 0x318d, PTPBUG_DELETE_SENDS_EVENT},
 2053 
 2054     /* Novell Bugzilla 852551, Dean Martin <deano_ferrari@hotmail.com> */
 2055     {"Canon:PowerShot A1000 IS",        0x04a9, 0x318e, PTPBUG_DELETE_SENDS_EVENT},
 2056 
 2057     /* Paul Tinsley */
 2058     {"Canon:PowerShot G10",         0x04a9, 0x318f, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 2059 
 2060     /* Nikolay Rysev <nrysev@gmail.com> */
 2061     {"Canon:PowerShot A2000 IS",        0x04a9, 0x3191, PTPBUG_DELETE_SENDS_EVENT},
 2062     /* Chris Rodley <chris@takeabreak.co.nz> */
 2063     {"Canon:PowerShot SX110 IS",        0x04a9, 0x3192, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 2064 
 2065     /* Kurt Garloff at SUSE */
 2066     {"Canon:Digital IXUS 980 IS",       0x04a9, 0x3193, PTPBUG_DELETE_SENDS_EVENT},
 2067     {"Canon:PowerShot SD990",       0x04a9, 0x3193, PTPBUG_DELETE_SENDS_EVENT},
 2068     {"Canon:IXY 3000 IS",           0x04a9, 0x3193, PTPBUG_DELETE_SENDS_EVENT},
 2069 
 2070     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2750875&group_id=8874&atid=358874 */
 2071     {"Canon:PowerShot SD880 IS",        0x04a9, 0x3196, PTPBUG_DELETE_SENDS_EVENT},
 2072 
 2073     /* IRC Reporter */
 2074     {"Canon:EOS 5D Mark II",        0x04a9, 0x3199, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 2075     /* Thomas Tanner <thomas@tannerlab.com> */
 2076     {"Canon:EOS 7D",            0x04a9, 0x319a, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 2077     /* mitch <debianuser@mll.dissimulo.com> */
 2078     {"Canon:EOS 50D",           0x04a9, 0x319b, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 2079 
 2080     /* https://bugs.launchpad.net/ubuntu/+source/libgphoto2/+bug/569419 */
 2081     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2082     {"Canon:PowerShot D10",         0x04a9, 0x31bc, PTPBUG_DELETE_SENDS_EVENT},
 2083 
 2084     /* Carsten Grohmann <carstengrohmann@gmx.de> */
 2085     {"Canon:Digital IXUS 110 IS",       0x04a9, 0x31bd, PTPBUG_DELETE_SENDS_EVENT},
 2086 
 2087     /* Willy Tarreau <w@1wt.eu> */
 2088     {"Canon:PowerShot A2100 IS",        0x04a9, 0x31be, PTPBUG_DELETE_SENDS_EVENT},
 2089 
 2090     {"Canon:PowerShot A480",        0x04a9, 0x31bf, PTPBUG_DELETE_SENDS_EVENT},
 2091 
 2092     /* IRC Reporter */
 2093     {"Canon:PowerShot SX200 IS",        0x04a9, 0x31c0, 0},
 2094     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2789326&group_id=8874&atid=358874 */
 2095     {"Canon:Digital IXUS 990 IS",       0x04a9, 0x31c1, PTPBUG_DELETE_SENDS_EVENT},
 2096     /* Michael Ole Olsen <gnu@gmx.net> */
 2097     {"Canon:PowerShot SD970 IS",        0x04a9, 0x31c1, PTPBUG_DELETE_SENDS_EVENT},
 2098     /* https://sourceforge.net/tracker/?func=detail&aid=2769511&group_id=8874&atid=208874 */
 2099     /* Do not confuse with PowerShot SX100IS */
 2100     {"Canon:Digital IXUS 100 IS",           0x04a9, 0x31c2, PTPBUG_DELETE_SENDS_EVENT},
 2101     /* https://sourceforge.net/tracker/?func=detail&aid=2769511&group_id=8874&atid=208874 */
 2102     {"Canon:PowerShot SD780 IS",        0x04a9, 0x31c2, PTPBUG_DELETE_SENDS_EVENT},
 2103     /* Matthew Vernon <matthew@sel.cam.ac.uk> */
 2104     {"Canon:PowerShot A1100 IS",        0x04a9, 0x31c3, PTPBUG_DELETE_SENDS_EVENT},
 2105     /* Joshua Hoke <jdh@people.homeip.net> */
 2106     {"Canon:Powershot SD1200 IS",       0x04a9, 0x31c4, PTPBUG_DELETE_SENDS_EVENT},
 2107     /* RalfGesellensetter <rgx@gmx.de> */
 2108     {"Canon:Digital IXUS 95 IS",        0x04a9, 0x31c4, PTPBUG_DELETE_SENDS_EVENT},
 2109     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2796275&group_id=8874&atid=358874 */
 2110     {"Canon:EOS 500D",          0x04a9, 0x31cf, PTP_CAP|PTP_CAP_PREVIEW},
 2111     {"Canon:EOS Rebel T1i",         0x04a9, 0x31cf, PTP_CAP|PTP_CAP_PREVIEW},
 2112     {"Canon:EOS Kiss X3",           0x04a9, 0x31cf, PTP_CAP|PTP_CAP_PREVIEW},
 2113 
 2114     /* Peter Lawrence <peter@pjlcentral.com> */
 2115     {"Canon:EOS 1D Mark IV",        0x04a9, 0x31d0, PTP_CAP|PTP_CAP_PREVIEW},
 2116 
 2117     /* From: Franck GIRARDIN - OPTOCONCEPT <fgirardin@optoconcept.com> */
 2118     {"Canon:PowerShot G11",         0x04a9, 0x31df, 0},
 2119 
 2120     /* The Wanderer <wanderer@fastmail.fm> */
 2121     {"Canon:PowerShot SX120 IS",        0x04a9, 0x31e0, PTPBUG_DELETE_SENDS_EVENT},
 2122     /* via libmtp */
 2123     {"Canon:PowerShot SX20 IS",     0x04a9, 0x31e4, PTPBUG_DELETE_SENDS_EVENT},
 2124     /* http://sourceforge.net/tracker/index.php?func=detail&aid=2918540&group_id=8874&atid=358874 */
 2125     {"Canon:IXY 220 IS",            0x04a9, 0x31e6, PTPBUG_DELETE_SENDS_EVENT},
 2126     {"Canon:Digital IXUS 120 IS",       0x04a9, 0x31e6, PTPBUG_DELETE_SENDS_EVENT},
 2127     {"Canon:PowerShot SD940 IS",        0x04a9, 0x31e6, PTPBUG_DELETE_SENDS_EVENT},
 2128     /* IRC reporter */
 2129     {"Canon:EOS 550D",          0x04a9, 0x31ea, PTP_CAP|PTP_CAP_PREVIEW},
 2130     /* Mauricio Pasquier Juan <mauricio@pasquierjuan.com.ar> */
 2131     {"Canon:Rebel T2i",         0x04a9, 0x31ea, PTP_CAP|PTP_CAP_PREVIEW},
 2132 
 2133     /* Andrés Farfán <nafraf@linuxmail.org> */
 2134     {"Canon:Powershot A495",        0x04a9, 0x31ef, PTPBUG_DELETE_SENDS_EVENT},
 2135 
 2136     /* ErVito on IRC */
 2137     {"Canon:PowerShot A3100 IS",        0x04a9, 0x31f1, PTPBUG_DELETE_SENDS_EVENT},
 2138 
 2139     {"Canon:PowerShot A3000 IS",        0x04a9, 0x31f2, PTPBUG_DELETE_SENDS_EVENT},
 2140     {"Canon:Digital IXUS 130",      0x04a9, 0x31f3, PTPBUG_DELETE_SENDS_EVENT},
 2141     /* Mark Voorhies <mvoorhie@yahoo.com> */
 2142     {"Canon:PowerShot SD1300 IS",       0x04a9, 0x31f4, PTPBUG_DELETE_SENDS_EVENT},
 2143     /* Juergen Weigert */
 2144     {"Canon:PowerShot SX210 IS",        0x04a9, 0x31f6, PTPBUG_DELETE_SENDS_EVENT},
 2145     /* name correct? https://bugs.launchpad.net/ubuntu/+source/gvfs/+bug/1296275?comments=all */
 2146     {"Canon:Digital IXUS 300 HS",       0x04a9, 0x31f7, PTPBUG_DELETE_SENDS_EVENT},
 2147     /* via email */
 2148     {"Canon:PowerShot G12",         0x04a9, 0x320f, PTPBUG_DELETE_SENDS_EVENT},
 2149     /* http://sourceforge.net/tracker/index.php?func=detail&aid=3153412&group_id=8874&atid=358874 */
 2150     {"Canon:PowerShot SX130 IS",        0x04a9, 0x3211, PTPBUG_DELETE_SENDS_EVENT},
 2151     /* novell bugzilla 871944 */
 2152     {"Canon:PowerShot S95",         0x04a9, 0x3212, PTPBUG_DELETE_SENDS_EVENT},
 2153     /* IRC Reporter */
 2154     {"Canon:EOS 60D",           0x04a9, 0x3215, PTP_CAP|PTP_CAP_PREVIEW},
 2155     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=3312353&group_id=8874 */
 2156     {"Canon:EOS 1100D",         0x04a9, 0x3217, PTP_CAP|PTP_CAP_PREVIEW},
 2157     {"Canon:Rebel T3",          0x04a9, 0x3217, PTP_CAP|PTP_CAP_PREVIEW},
 2158     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=3310995&group_id=8874 */
 2159     {"Canon:EOS 600D",          0x04a9, 0x3218, PTP_CAP|PTP_CAP_PREVIEW},
 2160     /* us alias from Andre Crone <andre@elysia.nl> */
 2161     {"Canon:Rebel T3i",         0x04a9, 0x3218, PTP_CAP|PTP_CAP_PREVIEW},
 2162 
 2163     /* Brian L Murphy <brian.l.murphy@gmail.com> */
 2164     {"Canon:EOS 1D X",          0x04a9, 0x3219, PTP_CAP|PTP_CAP_PREVIEW},
 2165 
 2166     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2167     {"Canon:IXUS 310IS",            0x04a9, 0x3225, PTPBUG_DELETE_SENDS_EVENT},
 2168 
 2169     /* analemma88@gmail.com */
 2170     {"Canon:PowerShot A800",        0x04a9, 0x3226, PTPBUG_DELETE_SENDS_EVENT},
 2171 
 2172     /* Juha Pesonen <juha.e.pesonen@gmail.com> */
 2173     {"Canon:PowerShot SX230HS",     0x04a9, 0x3228, PTPBUG_DELETE_SENDS_EVENT},
 2174 
 2175     /* Andrés Farfán <nafraf@linuxmail.org> */
 2176     {"Canon:PowerShot A2200",       0x04a9, 0x322a, PTPBUG_DELETE_SENDS_EVENT},
 2177 
 2178     /* http://sourceforge.net/tracker/?func=detail&atid=358874&aid=3572477&group_id=8874 */
 2179     {"Canon:PowerShot SX220HS",     0x04a9, 0x322c, PTPBUG_DELETE_SENDS_EVENT},
 2180 
 2181     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2182     {"Canon:PowerShot G1 X",        0x04a9, 0x3233, PTPBUG_DELETE_SENDS_EVENT},
 2183     /* Dean Martin <deano_ferrari@hotmail.com>, Novell Bugzilla 852551 */
 2184     {"Canon:PowerShot SX150 IS",        0x04a9, 0x3234, PTPBUG_DELETE_SENDS_EVENT},
 2185 
 2186     /* IRC reporter */
 2187     {"Canon:PowerShot S100",        0x04a9, 0x3236, PTPBUG_DELETE_SENDS_EVENT},
 2188     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2189     {"Canon:PowerShot SX40HS",      0x04a9, 0x3238, PTPBUG_DELETE_SENDS_EVENT},
 2190     /* Axel Waggershauser <awagger@web.de> */
 2191     {"Canon:EOS 5D Mark III",       0x04a9, 0x323a, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 2192     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2193     {"Canon:EOS 650D",          0x04a9, 0x323b, PTP_CAP|PTP_CAP_PREVIEW},
 2194     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2195     {"Canon:Rebel T4i",         0x04a9, 0x323b, PTP_CAP|PTP_CAP_PREVIEW},
 2196 
 2197     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2198     {"Canon:EOS M",             0x04a9, 0x323d, 0/*PTP_CAP|PTP_CAP_PREVIEW ... might be unknown opcodes -Marcus */},
 2199     /* via https://bugs.kde.org/show_bug.cgi?id=311393 */
 2200     {"Canon:PowerShot A1300IS",     0x04a9, 0x323e, PTPBUG_DELETE_SENDS_EVENT},
 2201     /* https://forums.opensuse.org/showthread.php/493692-canon-usb-camera-a810-not-detected */
 2202     {"Canon:PowerShot A810",        0x04a9, 0x323f, PTPBUG_DELETE_SENDS_EVENT},
 2203 
 2204     /* Giulio Fidente <gfidente@gmail.com> */
 2205     {"Canon:IXUS 125HS",            0x04a9, 0x3241, PTPBUG_DELETE_SENDS_EVENT},
 2206     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2207     {"Canon:PowerShot A4000IS",     0x04a9, 0x3243, PTPBUG_DELETE_SENDS_EVENT},
 2208     /* Peter Ivanyi <ipeter88@gmail.com> */
 2209     {"Canon:PowerShot SX260HS",     0x04a9, 0x3244, PTPBUG_DELETE_SENDS_EVENT},
 2210     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2211     {"Canon:PowerShot SX240HS",     0x04a9, 0x3245, PTPBUG_DELETE_SENDS_EVENT},
 2212     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2213     {"Canon:PowerShot A2400IS",     0x04a9, 0x3249, PTPBUG_DELETE_SENDS_EVENT},
 2214     /* Coro Fe <corofecoro@gmail.com> */
 2215     {"Canon:PowerShot A2300IS",     0x04a9, 0x324a, PTPBUG_DELETE_SENDS_EVENT},
 2216 
 2217     /* "François G." <francois@webcampak.com> */
 2218     {"Canon:EOS 6D",            0x04a9, 0x3250, PTP_CAP|PTP_CAP_PREVIEW},
 2219     /* Andre Crone <andre@elysia.nl> */
 2220     {"Canon:EOS 1D C",          0x04a9, 0x3252, PTP_CAP|PTP_CAP_PREVIEW},
 2221     /* Thorsten Ludewig <t.ludewig@gmail.com> */
 2222     {"Canon:EOS 70D",           0x04a9, 0x3253, PTP_CAP|PTP_CAP_PREVIEW},
 2223 
 2224     /* Thorsten Ludewig <t.ludewig@gmail.com> */
 2225     {"Canon:PowerShot G15",         0x04a9, 0x3258, PTPBUG_DELETE_SENDS_EVENT},
 2226 
 2227     /* Andrés Farfán <nafraf@linuxmail.org> */
 2228     {"Canon:PowerShot SX160IS",     0x04a9, 0x325a, PTPBUG_DELETE_SENDS_EVENT},
 2229 
 2230     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2231     {"Canon:PowerShot S110 (PTP Mode)", 0x04a9, 0x325b, PTPBUG_DELETE_SENDS_EVENT},
 2232     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2233     {"Canon:PowerShot SX500IS",     0x04a9, 0x325c, PTPBUG_DELETE_SENDS_EVENT},
 2234 
 2235     /* Andrés Farfán <nafraf@linuxmail.org> */
 2236     {"Canon:PowerShot SX280HS",     0x04a9, 0x325f, PTPBUG_DELETE_SENDS_EVENT},
 2237 
 2238     /* Marcus Meissner */
 2239     {"Canon:PowerShot A3500IS",     0x04a9, 0x3261, PTPBUG_DELETE_SENDS_EVENT},
 2240 
 2241     /* Canon Powershot A2600 */
 2242     {"Canon:PowerShot A2600",       0x04a9, 0x3262, PTPBUG_DELETE_SENDS_EVENT},
 2243 
 2244     /* Andrés Farfán <nafraf@linuxmail.org> */
 2245     {"Canon:PowerShot A1400",       0x04a9, 0x3264, PTPBUG_DELETE_SENDS_EVENT},
 2246     /* https://bugs.launchpad.net/ubuntu/+source/gvfs/+bug/1296275?comments=all  */
 2247     {"Canon:Digital IXUS 255HS",        0x04a9, 0x3268, PTPBUG_DELETE_SENDS_EVENT},
 2248 
 2249     /* t.ludewig@gmail.com */
 2250     {"Canon:EOS 7D MarkII",         0x04a9, 0x326f, PTP_CAP|PTP_CAP_PREVIEW},
 2251 
 2252     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2253     {"Canon:EOS 100D",          0x04a9, 0x3270, PTP_CAP|PTP_CAP_PREVIEW},
 2254 
 2255     /* Ronny Kalusniok <ladiko@gmail.com> */
 2256     {"Canon:PowerShot A2500",       0x04a9, 0x3271, PTPBUG_DELETE_SENDS_EVENT},
 2257 
 2258     /* "T. Ludewig" <t.ludewig@gmail.com> */
 2259     {"Canon:EOS 700D",          0x04a9, 0x3272, PTP_CAP|PTP_CAP_PREVIEW},
 2260 
 2261     /* Alexey Kryukov <amkryukov@gmail.com> */
 2262     {"Canon:EOS M2",            0x04a9, 0x3273, PTP_CAP|PTP_CAP_PREVIEW},
 2263 
 2264     /* Harald Krause <haraldkrause@gmx.com> */
 2265     {"Canon:PowerShot G16",         0x04a9, 0x3274, 0},
 2266 
 2267     /* From: Gerwin Voorsluijs <g.m.voorsluijs@online.nl> */
 2268     {"Canon:PowerShot S120",        0x04a9, 0x3275, PTPBUG_DELETE_SENDS_EVENT},
 2269 
 2270     /* Andrés Farfán <nafraf@linuxmail.org> */
 2271     {"Canon:PowerShot SX170 IS",        0x04a9, 0x3276, PTPBUG_DELETE_SENDS_EVENT},
 2272 
 2273     /* Andrés Farfán <nafraf@linuxmail.org> */
 2274     {"Canon:PowerShot SX510 HS",        0x04a9, 0x3277, PTPBUG_DELETE_SENDS_EVENT},
 2275 
 2276     /* thinkgareth <thinkgareth@users.sf.net> */
 2277     {"Canon:EOS 1200D",         0x04a9, 0x327f, PTP_CAP|PTP_CAP_PREVIEW},
 2278 
 2279     /* Iain Paton <ipaton0@gmail.com> */
 2280     {"Canon:EOS 760D",          0x04a9, 0x3280, PTP_CAP|PTP_CAP_PREVIEW},
 2281 
 2282     /* https://github.com/gphoto/libgphoto2/issues/92 */
 2283     {"Canon:EOS 5D Mark IV",        0x04a9, 0x3281, PTP_CAP|PTP_CAP_PREVIEW|PTP_DONT_CLOSE_SESSION},
 2284 
 2285     /* Marcus parents  ... preview works a bit, capture on a full moon */
 2286     {"Canon:PowerShot SX600 HS",        0x04a9, 0x3286, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 2287 
 2288     /* https://sourceforge.net/p/gphoto/feature-requests/445/ */
 2289     {"Canon:PowerShot Elph135",     0x04a9, 0x3288, PTPBUG_DELETE_SENDS_EVENT},
 2290 
 2291     /* Reed Johnson <rmjohns1@gmail.com> */
 2292     {"Canon:PowerShot Elph340HS",       0x04a9, 0x3289, PTPBUG_DELETE_SENDS_EVENT},
 2293 
 2294     /* Jesper Pedersen <jesper.pedersen@comcast.net */
 2295     {"Canon:EOS 1D X MarkII",       0x04a9, 0x3292, PTP_CAP|PTP_CAP_PREVIEW},
 2296     /* https://github.com/gphoto/libgphoto2/issues/60 */
 2297     /* needs dont close session */
 2298     {"Canon:EOS 80D",           0x04a9, 0x3294, PTP_CAP|PTP_CAP_PREVIEW|PTP_DONT_CLOSE_SESSION},
 2299     /* Andre Crone <andre@elysia.nl */
 2300     {"Canon:EOS 5DS",           0x04a9, 0x3295, PTP_CAP|PTP_CAP_PREVIEW|PTP_DONT_CLOSE_SESSION},
 2301     /* Nykhedimus S <nykhedimus@gmail.com> */
 2302     {"Canon:EOS M3",            0x04a9, 0x3299, PTPBUG_DELETE_SENDS_EVENT|PTP_CAP|PTP_CAP_PREVIEW},
 2303     /* Shaul Badusa <shaulikoo@gmail.com> */
 2304     {"Canon:PowerShot SX60HS",      0x04a9, 0x329a, PTPBUG_DELETE_SENDS_EVENT},
 2305     /* pravsripad@gmail.com */
 2306     {"Canon:PowerShot SX520 HS",        0x04a9, 0x329b, PTPBUG_DELETE_SENDS_EVENT},
 2307 
 2308     /* sparkycoladev@gmail.com */
 2309     {"Canon:PowerShot G7 X",        0x04a9, 0x329d, PTP_CAP|PTP_CAP_PREVIEW|PTP_DONT_CLOSE_SESSION},
 2310 
 2311     /* Sascha Wolff <sascha.wolff1@gmail.com> */
 2312     {"Canon:PowerShot SX530 HS",        0x04a9, 0x329f, PTP_CAP|PTP_CAP_PREVIEW|PTP_DONT_CLOSE_SESSION},
 2313 
 2314     /* Marcus Meissner <marcus@jet.franken.de> */
 2315     {"Canon:EOS M10",           0x04a9, 0x32a0, PTP_CAP|PTP_CAP_PREVIEW},
 2316 
 2317     /* Johannes Goecke <jg-ml@web.de> */
 2318     {"Canon:EOS 750D",          0x04a9, 0x32a1, PTP_CAP|PTP_CAP_PREVIEW},
 2319 
 2320     /* Tomas.Linden@helsinki.fi */
 2321     {"Canon:PowerShot G3 X",        0x04a9, 0x32a8, PTP_CAP|PTP_CAP_PREVIEW},
 2322     /* Kiss Tamas <kisst@bgk.bme.hu> */
 2323     {"Canon:IXUS 165",          0x04a9, 0x32a9, PTPBUG_DELETE_SENDS_EVENT},
 2324 
 2325     /* Gong <elainegong2010@gmail.com> */
 2326     {"Canon:IXUS 160",          0x04a9, 0x32aa, PTPBUG_DELETE_SENDS_EVENT},
 2327 
 2328     /* Gerald Leung <gerald@geraldleung.ca> */
 2329     {"Canon:PowerShot ELPH 350 HS",     0x04a9, 0x32ab, PTPBUG_DELETE_SENDS_EVENT},
 2330 
 2331     /* Andre Crone <andre@elysia.nl */
 2332     {"Canon:EOS 5DS R",         0x04a9, 0x32af, PTP_CAP|PTP_CAP_PREVIEW|PTP_DONT_CLOSE_SESSION},
 2333 
 2334     /* Erwin.Segerer@gmx.de */
 2335     {"Canon:PowerShot G5X",         0x04a9, 0x32b3, PTP_CAP|PTP_CAP_PREVIEW},
 2336 
 2337     /* Barney Livingston <barney.livingston@lobsterpictures.tv> */
 2338     {"Canon:EOS 1300D",         0x04a9, 0x32b4, PTP_CAP|PTP_CAP_PREVIEW},
 2339     /* Rebel T6 is the same camera. Jasem Mutlaq <mutlaqja@ikarustech.com> */
 2340     {"Canon:EOS Rebel T6",      0x04a9, 0x32b4, PTP_CAP|PTP_CAP_PREVIEW},
 2341 
 2342     /* Jim Howard <jh.xsnrg@gmail.com> */
 2343     {"Canon:EOS M5",            0x04a9, 0x32bb, PTP_CAP|PTP_CAP_PREVIEW},
 2344 
 2345     /* Hubert F */
 2346     {"Canon:PowerShot G7 X Mark II",        0x04a9, 0x32bc, PTP_CAP|PTP_CAP_PREVIEW},
 2347 
 2348     /* https://github.com/gphoto/libgphoto2/issues/325 */
 2349     {"Canon:PowerShot SX540 HS",        0x04a9, 0x32be, PTP_CAP|PTP_CAP_PREVIEW},
 2350 
 2351     /* https://github.com/gphoto/libgphoto2/issues/84 */
 2352     {"Canon:Digital IXUS 180",      0x04a9, 0x32c0, PTP_CAP|PTP_CAP_PREVIEW},
 2353 
 2354     /* https://github.com/gphoto/libgphoto2/issues/316 */
 2355     {"Canon:SX 720HS",          0x04a9, 0x32c2, PTP_CAP|PTP_CAP_PREVIEW},
 2356 
 2357     /* Sagufta Kapadia <sagufta.kapadia@gmail.com> */
 2358     {"Canon:SX 620HS",          0x04a9, 0x32c3, PTP_CAP|PTP_CAP_PREVIEW},
 2359 
 2360     /* https://github.com/gphoto/libgphoto2/issues/235 */
 2361     {"Canon:EOS M6",            0x04a9, 0x32c5, PTP_CAP|PTP_CAP_PREVIEW},
 2362 
 2363     /* https://github.com/gphoto/libgphoto2/issues/379 */
 2364     {"Canon:PowerShot G9 X Mark II",    0x04a9, 0x32c7, PTP_CAP|PTP_CAP_PREVIEW},
 2365 
 2366     /* Viktors Berstis <gpjm@berstis.com> */
 2367     {"Canon:EOS Rebel T7i",         0x04a9, 0x32c9, PTP_CAP|PTP_CAP_PREVIEW},
 2368     /* https://github.com/gphoto/libgphoto2/issues/338 */
 2369     {"Canon:EOS 800D",          0x04a9, 0x32c9, PTP_CAP|PTP_CAP_PREVIEW},
 2370 
 2371     /* Thomas Schaaf <thomas.schaaf@komola.de> */
 2372     {"Canon:EOS 6d Mark II",        0x04a9, 0x32ca, PTP_CAP|PTP_CAP_PREVIEW},
 2373 
 2374     /* Daniel Muller, jednatel SourcePaint s.r.o. <dan@sourcepaint.cz> */
 2375     {"Canon:EOS 77D",           0x04a9, 0x32cb, PTP_CAP|PTP_CAP_PREVIEW},
 2376 
 2377     /* "Lacy Rhoades" <lacy@colordeaf.net> */
 2378     {"Canon:EOS 200D",                  0x04a9, 0x32cc, PTP_CAP|PTP_CAP_PREVIEW},
 2379 
 2380     /* Geza Lore <gezalore@gmail.com> */
 2381     {"Canon:EOS M100",                  0x04a9, 0x32d1, PTP_CAP|PTP_CAP_PREVIEW},
 2382 
 2383     /* https://github.com/gphoto/libgphoto2/issues/58 */
 2384     {"Canon:EOS M50",               0x04a9, 0x32d2, PTP_CAP|PTP_CAP_PREVIEW},
 2385 
 2386     /* Marcus Meissner */
 2387     {"Canon:Digital IXUS 185",              0x04a9, 0x32d4, 0},
 2388 
 2389     /* Slavko Kocjancic <eslavko@gmail.com> */
 2390     {"Canon:Digital PowerShot SX730HS", 0x04a9, 0x32d6, PTP_CAP|PTP_CAP_PREVIEW},
 2391 
 2392     /* Jasem Mutlaq <mutlaqja@ikarustech.com> */
 2393     {"Canon:EOS 4000D",         0x04a9, 0x32d9, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 2394 
 2395     /* Elijah Parker <mail@timelapseplus.com> */
 2396     {"Canon:EOS R",                 0x04a9, 0x32da, PTP_CAP|PTP_CAP_PREVIEW|PTP_DONT_CLOSE_SESSION},
 2397 
 2398     /* Christian Muehlhaeuser <muesli@gmail.com> */
 2399     {"Canon:EOS 2000D",         0x04a9, 0x32e1, PTP_CAP|PTP_CAP_PREVIEW|PTPBUG_DELETE_SENDS_EVENT},
 2400 
 2401     /* https://github.com/gphoto/gphoto2/issues/247, from logfile */
 2402     {"Canon:EOS 1500D",                 0x04a9, 0x32e1, PTP_CAP|PTP_CAP_PREVIEW|PTP_DONT_CLOSE_SESSION},
 2403 
 2404     /* from timelapse-VIEW */
 2405     {"Canon:EOS R2",                0x04a9, 0x32e2, PTP_CAP|PTP_CAP_PREVIEW|PTP_DONT_CLOSE_SESSION},
 2406 
 2407     /* https://github.com/gphoto/libgphoto2/issues/316 */
 2408     {"Canon:PowerShot SX740 HS",        0x04a9, 0x32e4, PTP_CAP|PTP_CAP_PREVIEW},
 2409 
 2410     /*Marc Wetli <wetli@egoshooting.com> */
 2411     {"Canon:EOS M6 Mark II",        0x04a9, 0x32e7, PTP_CAP|PTP_CAP_PREVIEW},
 2412 
 2413     /* id from timelapse-view */
 2414     {"Canon:EOS 1D X MarkIII",      0x04a9, 0x32e8, PTP_CAP|PTP_CAP_PREVIEW},
 2415 
 2416     /* Roland Förg <roland.foerg@arcor.de> */
 2417     {"Canon:EOS 250D",          0x04a9, 0x32e9, PTP_CAP|PTP_CAP_PREVIEW},
 2418 
 2419     /* Matthias <matthias@mail-s.eu> */
 2420     {"Canon:EOS 90D",           0x04a9, 0x32ea, PTP_CAP|PTP_CAP_PREVIEW},
 2421     /* https://github.com/gphoto/gphoto2/issues/347 */
 2422     {"Canon:PowerShot SX70 HS",     0x04a9, 0x32ee, PTP_CAP|PTP_CAP_PREVIEW},
 2423     /* https://github.com/gphoto/libgphoto2/issues/614 */
 2424     {"Canon:EOS M200",          0x04a9, 0x32ef, PTP_CAP|PTP_CAP_PREVIEW},
 2425     /* from timelapse-view */
 2426     {"Canon:EOS R5",            0x04a9, 0x32f4, PTP_CAP|PTP_CAP_PREVIEW},
 2427     /* Steve Rencontre <steve@rsn-tech.co.uk> */
 2428     {"Canon:EOS R6",            0x04a9, 0x32f5, PTP_CAP|PTP_CAP_PREVIEW},
 2429 
 2430     /* Konica-Minolta PTP cameras */
 2431     {"Konica-Minolta:DiMAGE A2 (PTP mode)",        0x132b, 0x0001, 0},
 2432     {"Konica-Minolta:DiMAGE Z2 (PictBridge mode)", 0x132b, 0x0007, 0},
 2433     {"Konica-Minolta:DiMAGE X21 (PictBridge mode)",0x132b, 0x0009, 0},
 2434     {"Konica-Minolta:DiMAGE Z3 (PictBridge mode)", 0x132b, 0x0018, 0},
 2435     {"Konica-Minolta:DiMAGE A200 (PictBridge mode)",0x132b, 0x0019, 0},
 2436     {"Konica-Minolta:DiMAGE Z5 (PictBridge mode)", 0x132b, 0x0022, 0},
 2437 
 2438     /* Fuji PTP cameras */
 2439     {"Fuji:FinePix S7000",          0x04cb, 0x0142, 0},
 2440     {"Fuji:FinePix A330",           0x04cb, 0x014a, 0},
 2441     /* Hans-Joachim Baader <hjb@pro-linux.de> */
 2442     {"Fuji:FinePix S9500",          0x04cb, 0x018f, 0},
 2443     {"Fuji:FinePix E900",           0x04cb, 0x0193, 0},
 2444     {"Fuji:FinePix F30",            0x04cb, 0x019b, 0},
 2445     /* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=1620750&group_id=8874 */
 2446     {"Fuji:FinePix S6500fd",        0x04cb, 0x01bf, 0},
 2447     /* https://launchpad.net/bugs/89743 */
 2448     {"Fuji:FinePix F20",            0x04cb, 0x01c0, 0},
 2449     /* launchpad 67532 */
 2450     {"Fuji:FinePix F31fd",          0x04cb, 0x01c1, 0},
 2451     /* http://sourceforge.net/tracker/?func=detail&atid=358874&aid=2881948&group_id=8874 */
 2452     {"Fuji:S5 Pro",                 0x04cb, 0x01c3, PTP_CAP},
 2453     {"Fuji:FinePix S5700",          0x04cb, 0x01c4, 0},
 2454     {"Fuji:FinePix F40fd",          0x04cb, 0x01c5, 0},
 2455     /* http://sourceforge.net/tracker/index.php?func=detail&aid=1800289&group_id=8874&atid=358874 */
 2456     {"Fuji:FinePix A820",           0x04cb, 0x01c6, 0},
 2457     /* Louis Byrne <louisbyrneca@hotmail.com> */
 2458     {"Fuji:FinePix A610",           0x04cb, 0x01d0, 0},
 2459     /* g4@catking.net */
 2460     {"Fuji:FinePix A800",           0x04cb, 0x01d2, 0},
 2461     /* Gerhard Schmidt <gerd@dg4fac.de> */
 2462     {"Fuji:FinePix A920",           0x04cb, 0x01d3, 0},
 2463     /* Teppo Jalava <tjjalava@gmail.com> */
 2464     {"Fuji:FinePix F50fd",          0x04cb, 0x01d4, 0},
 2465     /* IRC reporter */
 2466     {"Fuji:FinePix S5800",          0x04cb, 0x01d7, 0},
 2467     /* https://sourceforge.net/tracker/?func=detail&atid=108874&aid=1945259&group_id=8874 */
 2468     {"Fuji:FinePix Z100fd",         0x04cb, 0x01d8, 0},
 2469     /* http://sourceforge.net/tracker/index.php?func=detail&aid=2017171&group_id=8874&atid=358874 */
 2470     {"Fuji:FinePix S100fs",         0x04cb, 0x01db, 0},
 2471     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2772199&group_id=8874&atid=358874 */
 2472     {"Fuji:FinePix S1000fd",        0x04cb, 0x01dd, 0},
 2473     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2203316&group_id=8874&atid=358874 */
 2474     {"Fuji:FinePix F100fd",         0x04cb, 0x01e0, 0},
 2475     /*https://sourceforge.net/tracker/index.php?func=detail&aid=2820380&group_id=8874&atid=358874 */
 2476     {"Fuji:FinePix F200 EXR",       0x04cb, 0x01e4, 0},
 2477     /* https://sourceforge.net/tracker/index.php?func=detail&aid=2993118&group_id=8874&atid=358874  */
 2478     {"Fuji:FinePix F60fd",          0x04cb, 0x01e6, 0},
 2479     /* Gerhard Schmidt <gerd@dg4fac.de> */
 2480     {"Fuji:FinePix S2000HD",        0x04cb, 0x01e8, 0},
 2481     {"Fuji:FinePix S1500",          0x04cb, 0x01ef, 0},
 2482     /* http://sourceforge.net/tracker/index.php?func=detail&aid=3018889&group_id=8874&atid=358874 */
 2483     {"Fuji:FinePix F70 EXR",        0x04cb, 0x01fa, 0},
 2484     /* http://sourceforge.net/tracker/index.php?func=detail&aid=3111790&group_id=8874&atid=358874 */
 2485     {"Fuji:Fujifilm A220",          0x04cb, 0x01fe, 0},
 2486     /* NoOp <glgxg@sbcglobal.net> */
 2487     {"Fuji:FinePix S1800",          0x04cb, 0x0200, 0},
 2488     /* Luke Symes <allsymes@gmail.com> */
 2489     {"Fuji:FinePix Z35",            0x04cb, 0x0201, 0},
 2490     /* "Steven A. McIntosh" <mcintosh@cotterochan.co.uk> */
 2491     {"Fuji:FinePix S2500HD",        0x04cb, 0x0209, 0},
 2492     /* Erik Hahn <erik_hahn@gmx.de> */
 2493     {"Fuji:FinePix F80EXR",         0x04cb, 0x020e, 0},
 2494     /* salsaman <salsaman@gmail.com> */
 2495     {"Fuji:FinePix Z700EXR",        0x04cb, 0x020d, 0},
 2496     /* https://bugs.launchpad.net/ubuntu/+source/gvfs/+bug/1311953 */
 2497     {"Fuji:FinePix AV-150",         0x04cb, 0x021b, 0},
 2498     /* Gregor Voss <gregor.voss@gmx.de> */
 2499     {"Fuji:FinePix H20EXR",         0x04cb, 0x022d, 0},
 2500     /* https://bugs.launchpad.net/ubuntu/+source/gvfs/+bug/1296275?comments=all  */
 2501     {"Fuji:FinePix T200",           0x04cb, 0x0233, 0},
 2502     /* https://sourceforge.net/tracker/index.php?func=detail&aid=3556692&group_id=8874&atid=108874 */
 2503     {"Fuji:FinePix S2950",          0x04cb, 0x0240, 0},
 2504     /* https://sourceforge.net/p/gphoto/bugs/974/ */
 2505     {"Fuji:FinePix JX370",          0x04cb, 0x0250, 0},
 2506     /* Luis Arias <kaaloo@gmail.com> */
 2507     {"Fuji:FinePix X10",            0x04cb, 0x0263, 0},
 2508     /* t.ludewig@gmail.com */
 2509     {"Fuji:FinePix S4300",          0x04cb, 0x0265, 0},
 2510     /* t.ludewig@gmail.com */
 2511     {"Fuji:FinePix X-S1",           0x04cb, 0x026e, 0},
 2512     /* t.ludewig@gmail.com */
 2513     {"Fuji:FinePix HS30EXR",        0x04cb, 0x0271, 0},
 2514     /* Marcel Bonnet <marcelbonnet@gmail.com> */
 2515     {"Fuji:FinePix S2980",          0x04cb, 0x027d, 0},
 2516     /* Michael Martin <mischel88@web.de> */
 2517     {"Fuji:FinePix X-E1",           0x04cb, 0x0283, 0},
 2518     /* t.ludewig@gmail.com */
 2519     {"Fuji:FinePix XF1",            0x04cb, 0x0288, 0},
 2520     /* Steve Dahl <dahl@goshawk.com> */
 2521     {"Fuji:FinePix S4850",          0x04cb, 0x0298, 0},
 2522     /* Larry D. DeMaris" <demarisld@gmail.com> */
 2523     {"Fuji:FinePix SL1000",         0x04cb, 0x029c, 0},
 2524     /* t.ludewig@gmail.com */
 2525     {"Fuji:FinePix X20",            0x04cb, 0x02a6, 0},
 2526     /* https://sourceforge.net/p/libmtp/bugs/1040/ */
 2527     {"Fuji:Fujifilm X-E2",          0x04cb, 0x02b5, 0},
 2528     /* https://github.com/gphoto/libgphoto2/issues/283 */
 2529     {"Fuji:Fujifilm X-M1",          0x04cb, 0x02b6, 0},
 2530     /* luigiwriter2@gmail.com */
 2531     {"Fuji:FinePix S8600 ",         0x04cb, 0x02b9, 0},
 2532     /* https://github.com/gphoto/libgphoto2/issues/281 */
 2533     {"Fuji:Fujifilm X70",           0x04cb, 0x02ba, 0},
 2534     /* Vladimir K <enewsletters@inbox.ru>, https://github.com/gphoto/libgphoto2/issues/283 */
 2535     {"Fuji:Fujifilm X-T1",          0x04cb, 0x02bf, PTP_CAP|PTP_CAP_PREVIEW},
 2536     /* https://github.com/gphoto/libgphoto2/issues/281 */
 2537     {"Fuji:Fujifilm X30",           0x04cb, 0x02c1, 0},
 2538     /* https://sourceforge.net/p/gphoto/feature-requests/464/ */
 2539     {"Fuji:Fujifilm X-A2",          0x04cb, 0x02c6, 0},
 2540     /* https://github.com/gphoto/libgphoto2/issues/32 */
 2541     {"Fuji:Fujifilm X-T10",         0x04cb, 0x02c8, 0},
 2542     /* with new updated firmware 4.0, https://github.com/gphoto/libgphoto2/issues/220 */
 2543     {"Fuji:Fujifilm X-Pro2",        0x04cb, 0x02cb, PTP_CAP|PTP_CAP_PREVIEW},
 2544     /* with new updated firmware 1.1 */
 2545     {"Fuji:Fujifilm X-T2",          0x04cb, 0x02cd, PTP_CAP|PTP_CAP_PREVIEW},
 2546     /* https://github.com/gphoto/libgphoto2/issues/283 */
 2547     {"Fuji:Fujifilm X100F",         0x04cb, 0x02d1, 0},
 2548     /* https://github.com/gphoto/libgphoto2/issues/133 */
 2549     {"Fuji:GFX 50 S",           0x04cb, 0x02d3, PTP_CAP|PTP_CAP_PREVIEW},
 2550     /* https://github.com/gphoto/libgphoto2/issues/170 */
 2551     {"Fuji:Fujifilm X-T20",         0x04cb, 0x02d4, 0},
 2552     /* Рустем Валиев <rustvt@gmail.com> */
 2553     {"Fuji:Fujifilm X-A5",          0x04cb, 0x02d5, 0},
 2554     /* Daniel Queen <dqueen510@gmail.com> */
 2555     /* USB Raw Converter/Backup Restore mode, firmware version 1.20 or newer */
 2556     {"Fuji:Fujifilm X-E3",          0x04cb, 0x02d6, PTP_CAP|PTP_CAP_PREVIEW},
 2557     /* https://github.com/gphoto/libgphoto2/issues/283 */
 2558     {"Fuji:Fujifilm X-H1",          0x04cb, 0x02d7, PTP_CAP|PTP_CAP_PREVIEW},
 2559     /* Seth Cohen <forwardthinking.llc@gmail.com> */
 2560     {"Fuji:GFX 50 R",           0x04cb, 0x02dc, PTP_CAP|PTP_CAP_PREVIEW},
 2561     /* Stefan Weiberg at SUSE */
 2562     {"Fuji:Fujifilm X-T3",          0x04cb, 0x02dd, PTP_CAP|PTP_CAP_PREVIEW},
 2563     /* https://github.com/gphoto/gphoto2/issues/256 */
 2564     {"Fuji:Fujifilm GFX100",        0x04cb, 0x02de, PTP_CAP|PTP_CAP_PREVIEW},
 2565     /* Bruno Filho at SUSE (currently not working with cpature, but shows variables) */
 2566     /* so far looks like the low end X-T30 does not support tethering, https://www.dpreview.com/forums/thread/4451199 */
 2567     {"Fuji:Fujifilm X-T30",         0x04cb, 0x02e3, 0},
 2568     /* https://github.com/gphoto/libgphoto2/issues/505 */
 2569     {"Fuji:Fujifilm X-T4",          0x04cb, 0x02e6, PTP_CAP|PTP_CAP_PREVIEW},
 2570     /* https://github.com/gphoto/libgphoto2/issues/603 */
 2571     {"Fuji:Fujifilm X-S10",         0x04cb, 0x02ea, PTP_CAP_PREVIEW},   /* only webcam mode apparently */
 2572 
 2573     {"Ricoh:Caplio R5 (PTP mode)",          0x05ca, 0x0110, 0},
 2574     {"Ricoh:Caplio GX (PTP mode)",          0x05ca, 0x0325, 0},
 2575     {"Sea & Sea:5000G (PTP mode)",      0x05ca, 0x0327, 0},
 2576     /* Michael Steinhauser <mistr@online.de> */
 2577     {"Ricoh Caplio:R1v (PTP mode)",     0x05ca, 0x032b, 0},
 2578     {"Ricoh:Caplio R3 (PTP mode)",          0x05ca, 0x032f, 0},
 2579     /* Arthur Butler <arthurbutler@otters.ndo.co.uk> */
 2580     {"Ricoh:Caplio RR750 (PTP mode)",   0x05ca, 0x033d, 0},
 2581     /* Gerald Pfeifer at SUSE */
 2582     {"Sea & Sea:2G (PTP mode)",     0x05ca, 0x0353, 0},
 2583 
 2584     /* Marcus Meissner */
 2585     {"Ricoh:Theta m15 (PTP mode)",      0x05ca, 0x0365, 0},
 2586 
 2587     /* "Lacy Rhoades" <lacy@colordeaf.net> */
 2588     {"Ricoh:Theta S (PTP mode)",        0x05ca, 0x0366, 0},
 2589     {"Ricoh:Theta SC (PTP mode)",       0x05ca, 0x0367, 0},
 2590 
 2591     /* https://github.com/libmtp/libmtp/pull/68  */
 2592     {"Ricoh:Theta V (PTP mode)",        0x05ca, 0x0368, 0},
 2593     {"Ricoh:Theta Z1 (PTP mode)",       0x05ca, 0x036d, 0},
 2594 
 2595     /* Rollei dr5  */
 2596     {"Rollei:dr5 (PTP mode)",               0x05ca, 0x220f, 0},
 2597 
 2598     /* Ricoh Caplio GX 8 */
 2599     {"Ricoh:Caplio GX 8 (PTP mode)",        0x05ca, 0x032d, 0},
 2600 
 2601     /* Arda Kaan <ardakaan@gmail.com> */
 2602     {"Ricoh:WG-M2 (PTP mode)",          0x25fb, 0x210b, 0},
 2603 
 2604     /* Pentax cameras */
 2605     {"Pentax:Optio 43WR",                   0x0a17, 0x000d, 0},
 2606     /* Stephan Barth at SUSE */
 2607     {"Pentax:Optio W90",                    0x0a17, 0x00f7, 0},
 2608 
 2609     /* gphoto:feature-requests 452. yes, weird vendor. */
 2610     {"Pentax:K3 (PTP Mode)",        0x25fb, 0x0165, 0},
 2611     /* Keld Henningsen <drawsacircle@hotmail.com */
 2612     {"Pentax:K70 (PTP Mode)",       0x25fb, 0x017d, 0},
 2613 
 2614     {"Sanyo:VPC-C5 (PTP mode)",             0x0474, 0x0230, 0},
 2615     /* https://github.com/gphoto/libgphoto2/issues/497 */
 2616     {"Sanyo:VPC-FH1 (PTP mode)",            0x0474, 0x02e5, 0},
 2617 
 2618     /* from Mike Meyer <mwm@mired.org>. Does not support MTP. */
 2619     {"Apple:iPhone (PTP mode)",     0x05ac, 0x1290, 0},
 2620     /* IRC reporter adjusted info */
 2621     {"Apple:iPod Touch (PTP mode)",     0x05ac, 0x1291, 0},
 2622     /* irc reporter. MTP based. */
 2623     {"Apple:iPhone 3G (PTP mode)",      0x05ac, 0x1292, 0},
 2624     /* Marco Michna at SUSE */
 2625     {"Apple:iPod Touch 2G (PTP mode)",  0x05ac, 0x1293, 0},
 2626     /* Mark Lehrer <mark@knm.org> */
 2627     {"Apple:iPhone 3GS (PTP mode)",     0x05ac, 0x1294, 0},
 2628 
 2629     /* Rasmus P */
 2630     {"Apple:iPhone 4 (PTP mode)",       0x05ac, 0x1297, 0},
 2631 
 2632     {"Apple:iPod Touch 3rd Gen (PTP mode)", 0x05ac, 0x1299, 0},
 2633     {"Apple:iPad (PTP mode)",       0x05ac, 0x129a, 0},
 2634 
 2635     /* Don Cohen <don-sourceforge-xxzw@isis.cs3-inc.com> */
 2636     {"Apple:iPhone 4S (PTP mode)",      0x05ac, 0x12a0, 0},
 2637 
 2638     /* grinchdee@gmail.com */
 2639     {"Apple:iPhone 5 (PTP mode)",       0x05ac, 0x12a8, 0},
 2640 
 2641     /* chase.thunderstrike@gmail.com */
 2642     {"Apple:iPad Air",          0x05ac, 0x12ab, 0},
 2643 
 2644     /* https://sourceforge.net/tracker/index.php?func=detail&aid=1869653&group_id=158745&atid=809061 */
 2645     {"Pioneer:DVR-LX60D",           0x08e4, 0x0142, 0},
 2646 
 2647     /* https://sourceforge.net/tracker/index.php?func=detail&aid=1680029&group_id=8874&atid=108874 */
 2648     {"Nokia:N73",               0x0421, 0x0488, 0},
 2649 
 2650     /* gbakos@astro.princeton.edu */
 2651     {"Samsung:NX1",             0x04e8, 0x140c, 0},
 2652     /* IRC reporter */
 2653     {"Samsung:S5620",           0x04e8, 0x684a, 0},
 2654 
 2655     /* Israel Barrientos <jbarrien@gmail.com> */
 2656     {"Samsung:NX1000",          0x04e8, 0x1384, 0},
 2657 
 2658     /* This is a camera ... reported by TAN JIAN QI <JQTAN1@e.ntu.edu.sg */
 2659     {"Samsung:EK-GC100",            0x04e8, 0x6866, 0},
 2660 
 2661     /* 522903503@qq.com */
 2662     {"Sigma:fp",                0x1003, 0xc432, 0},
 2663 
 2664     /* Bernhard Wagner <me@bernhardwagner.net> */
 2665     {"Leica:M9",                0x1a98, 0x0002, PTP_CAP},
 2666 
 2667     /* Christopher Kao <christopherkao@icloud.com> */
 2668     {"Leica:SL (Typ 601)",          0x1a98, 0x2041, PTP_CAP|PTP_CAP_PREVIEW},
 2669 
 2670     /* https://github.com/gphoto/libgphoto2/issues/105 */
 2671     {"Parrot:Sequoia",          0x19cf, 0x5039, PTP_CAP},
 2672 
 2673     {"GoPro:HERO" ,             0x2672, 0x000c, 0},
 2674     {"GoPro:HERO4 Silver" ,         0x2672, 0x000d, 0 },
 2675 
 2676     /* https://sourceforge.net/p/gphoto/support-requests/130/ */
 2677     {"GoPro:HERO 4",            0x2672, 0x000e, 0},
 2678     /* Tomas Zigo <tomas.zigo@slovanet.sk> */
 2679     {"GoPro:HERO 3+",           0x2672, 0x0011, 0},
 2680     /* https://sourceforge.net/u/drzap/libmtp/ci/39841e9a15ed250a0121ae4a139b2a950a07f08c/ */
 2681     {"GoPro:HERO +",            0x2672, 0x0021, 0},
 2682     /* from libmtp */
 2683     {"GoPro:HERO5 Black",           0x2672, 0x0027, 0},
 2684     {"GoPro:HERO5 Session",         0x2672, 0x0029, 0},
 2685 
 2686     /* https://sourceforge.net/p/libmtp/feature-requests/239/ */
 2687     {"GoPro:HERO6 Black",           0x2672, 0x0037, 0},
 2688     /* Rasmus Larsson <larsson.rasmus@gmail.com> */
 2689     {"GoPro:HERO7 White",           0x2672, 0x0042, 0},
 2690     /* Marcus Meissner */
 2691     {"GoPro:HERO7 Silver",          0x2672, 0x0043, 0},
 2692     /* https://sourceforge.net/p/libmtp/feature-requests/284/ */
 2693     {"GoPro:HERO7 Black",           0x2672, 0x0047, 0},
 2694     /* https://sourceforge.net/p/libmtp/bugs/1858/ */
 2695     {"GoPro:HERO8 Black",           0x2672, 0x0049, 0},
 2696 #endif
 2697 };
 2698 
 2699 static struct {
 2700     const char *model;
 2701     unsigned long device_flags;
 2702 } ptpip_models[] = {
 2703     {"PTP/IP Camera"    , PTP_CAP|PTP_CAP_PREVIEW},
 2704     {"Ricoh Theta (WLAN)"   , PTP_CAP},
 2705     {"Nikon DSLR (WLAN)"    , PTP_CAP|PTP_CAP_PREVIEW},
 2706     {"Nikon 1 (WLAN)"   , PTP_CAP|PTP_CAP_PREVIEW},
 2707     {"Canon EOS (WLAN)" , PTP_CAP|PTP_CAP_PREVIEW},
 2708     {"Fuji X (WLAN)"    , PTP_CAP|PTP_CAP_PREVIEW},
 2709 };
 2710 
 2711 #include "device-flags.h"
 2712 static struct {
 2713     const char *vendor;
 2714     unsigned short usb_vendor;
 2715     const char *model;
 2716     unsigned short usb_product;
 2717     unsigned long flags;
 2718 } mtp_models[] = {
 2719 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 2720 #include "music-players.h"
 2721 #endif
 2722 };
 2723 
 2724 static struct {
 2725     uint16_t    format_code;
 2726     uint16_t    vendor_code;
 2727     const char *txt;
 2728 } object_formats[] = {
 2729     {PTP_OFC_Undefined,     0, "application/x-unknown"},
 2730     {PTP_OFC_Association,       0, "application/x-association"},
 2731     {PTP_OFC_Script,        0, "application/x-script"},
 2732     {PTP_OFC_Executable,        0, "application/octet-stream"},
 2733     {PTP_OFC_Text,          0, GP_MIME_TXT},
 2734     {PTP_OFC_HTML,          0, "text/html"},
 2735     {PTP_OFC_DPOF,          0, "text/plain"},
 2736     {PTP_OFC_AIFF,          0, "audio/x-aiff"},
 2737     {PTP_OFC_WAV,           0, GP_MIME_WAV},
 2738     {PTP_OFC_MP3,           0, "audio/mpeg"},
 2739     {PTP_OFC_AVI,           0, GP_MIME_AVI},
 2740     {PTP_OFC_MPEG,          0, "video/mpeg"},
 2741     {PTP_OFC_ASF,           0, "video/x-ms-asf"},
 2742     {PTP_OFC_QT,            0, "video/quicktime"},
 2743     {PTP_OFC_EXIF_JPEG,     0, GP_MIME_JPEG},
 2744     {PTP_OFC_TIFF_EP,       0, "image/x-tiffep"},
 2745     {PTP_OFC_FlashPix,      0, "image/x-flashpix"},
 2746     {PTP_OFC_BMP,           0, GP_MIME_BMP},
 2747     {PTP_OFC_CIFF,          0, "image/x-ciff"},
 2748     {PTP_OFC_Undefined_0x3806,  0, "application/x-unknown"},
 2749     {PTP_OFC_GIF,           0, "image/gif"},
 2750     {PTP_OFC_JFIF,          0, GP_MIME_JPEG},
 2751     {PTP_OFC_PCD,           0, "image/x-pcd"},
 2752     {PTP_OFC_PICT,          0, "image/x-pict"},
 2753     {PTP_OFC_PNG,           0, GP_MIME_PNG},
 2754     {PTP_OFC_Undefined_0x380C,  0, "application/x-unknown"},
 2755     {PTP_OFC_TIFF,          0, GP_MIME_TIFF},
 2756     {PTP_OFC_TIFF_IT,       0, "image/x-tiffit"},
 2757     {PTP_OFC_JP2,           0, "image/x-jpeg2000bff"},
 2758     {PTP_OFC_JPX,           0, "image/x-jpeg2000eff"},
 2759     {PTP_OFC_DNG,           0, "image/x-adobe-dng"},
 2760     {PTP_OFC_MTP_MP4,       0, "video/mp4"},
 2761 
 2762     {PTP_OFC_MTP_OGG,       PTP_VENDOR_MICROSOFT, "application/ogg"},
 2763     {PTP_OFC_MTP_FLAC,      PTP_VENDOR_MICROSOFT, "audio/x-flac"},
 2764     {PTP_OFC_MTP_MP2,       PTP_VENDOR_MICROSOFT, "video/mpeg"},
 2765     {PTP_OFC_MTP_M4A,       PTP_VENDOR_MICROSOFT, "audio/x-m4a"},
 2766     {PTP_OFC_MTP_3GP,       PTP_VENDOR_MICROSOFT, "audio/3gpp"},
 2767     {PTP_OFC_MTP_WMV,       PTP_VENDOR_MICROSOFT, "video/x-wmv"},
 2768     {PTP_OFC_MTP_WMA,       PTP_VENDOR_MICROSOFT, "audio/x-wma"},
 2769     {PTP_OFC_MTP_WMV,       PTP_VENDOR_MICROSOFT, "video/x-ms-wmv"},
 2770     {PTP_OFC_MTP_WMA,       PTP_VENDOR_MICROSOFT, "audio/x-ms-wma"},
 2771     {PTP_OFC_MTP_AAC,       PTP_VENDOR_MICROSOFT, "audio/MP4A-LATM"},
 2772     {PTP_OFC_MTP_XMLDocument,   PTP_VENDOR_MICROSOFT, "text/xml"},
 2773     {PTP_OFC_MTP_MSWordDocument,    PTP_VENDOR_MICROSOFT, "application/msword"},
 2774     {PTP_OFC_MTP_MSExcelSpreadsheetXLS, PTP_VENDOR_MICROSOFT, "vnd.ms-excel"},
 2775     {PTP_OFC_MTP_MSPowerpointPresentationPPT, PTP_VENDOR_MICROSOFT, "vnd.ms-powerpoint"},
 2776     {PTP_OFC_MTP_vCard2,        PTP_VENDOR_MICROSOFT, "text/directory"},
 2777     {PTP_OFC_MTP_vCard3,        PTP_VENDOR_MICROSOFT, "text/directory"},
 2778     {PTP_OFC_MTP_vCalendar1,    PTP_VENDOR_MICROSOFT, "text/calendar"},
 2779     {PTP_OFC_MTP_vCalendar2,    PTP_VENDOR_MICROSOFT, "text/calendar"},
 2780     {PTP_OFC_CANON_CRW,     PTP_VENDOR_CANON, "image/x-canon-cr2"},
 2781     {PTP_OFC_CANON_CRW3,        PTP_VENDOR_CANON, "image/x-canon-cr2"},
 2782     {PTP_OFC_CANON_CR3,     PTP_VENDOR_CANON, "image/x-canon-cr3"},
 2783     {PTP_OFC_CANON_MOV,     PTP_VENDOR_CANON, "video/quicktime"},
 2784     {PTP_OFC_CANON_CHDK_CRW,    PTP_VENDOR_CANON, "image/x-canon-cr2"},
 2785     {PTP_OFC_SONY_RAW,      PTP_VENDOR_SONY, "image/x-sony-arw"},
 2786     {0,             0, NULL}
 2787 };
 2788 
 2789 static int
 2790 set_mimetype (CameraFile *file, uint16_t vendorcode, uint16_t ofc)
 2791 {
 2792     int i;
 2793 
 2794     for (i = 0; object_formats[i].format_code; i++) {
 2795         if (object_formats[i].vendor_code && /* 0 means generic */
 2796             (object_formats[i].vendor_code != vendorcode))
 2797             continue;
 2798         if (object_formats[i].format_code != ofc)
 2799             continue;
 2800         return gp_file_set_mime_type (file, object_formats[i].txt);
 2801     }
 2802     GP_LOG_D ("Failed to find mime type for %04x", ofc);
 2803     return gp_file_set_mime_type (file, "application/x-unknown");
 2804 }
 2805 
 2806 static void
 2807 strcpy_mime(char * dest, uint16_t vendor_code, uint16_t ofc) {
 2808     int i;
 2809 
 2810     for (i = 0; object_formats[i].format_code; i++) {
 2811         if (object_formats[i].vendor_code && /* 0 means generic */
 2812             (object_formats[i].vendor_code != vendor_code))
 2813             continue;
 2814         if (object_formats[i].format_code == ofc) {
 2815             strcpy(dest, object_formats[i].txt);
 2816             return;
 2817         }
 2818     }
 2819     GP_LOG_D ("Failed to find mime type for %04x", ofc);
 2820     strcpy(dest, "application/x-unknown");
 2821 }
 2822 
 2823 static uint32_t
 2824 get_mimetype (Camera *camera, CameraFile *file, uint16_t vendor_code)
 2825 {
 2826     int i;
 2827     const char *mimetype;
 2828 
 2829     gp_file_get_mime_type (file, &mimetype);
 2830     for (i = 0; object_formats[i].format_code; i++) {
 2831         if (object_formats[i].vendor_code && /* 0 means generic */
 2832             (object_formats[i].vendor_code != vendor_code))
 2833             continue;
 2834         if (!strcmp(mimetype,object_formats[i].txt))
 2835             return (object_formats[i].format_code);
 2836     }
 2837     GP_LOG_D ("Failed to find mime type for %s", mimetype);
 2838     return (PTP_OFC_Undefined);
 2839 }
 2840 
 2841 static void
 2842 #ifdef __GNUC__
 2843 __attribute__((__format__(printf,2,0)))
 2844 #endif
 2845 ptp_debug_func (void *data, const char *format, va_list args)
 2846 {
 2847     gp_logv (GP_LOG_DEBUG, "ptp", format, args);
 2848 }
 2849 
 2850 static void
 2851 #ifdef __GNUC__
 2852 __attribute__((__format__(printf,2,0)))
 2853 #endif
 2854 ptp_error_func (void *data, const char *format, va_list args)
 2855 {
 2856     PTPData *ptp_data = data;
 2857     char buf[2048];
 2858 
 2859     vsnprintf (buf, sizeof (buf), format, args);
 2860     gp_context_error (ptp_data->context, "%s", buf);
 2861 }
 2862 
 2863 static int
 2864 is_mtp_capable(Camera *camera) {
 2865     PTPParams *params = &camera->pl->params;
 2866     if (params->deviceinfo.VendorExtensionID == PTP_VENDOR_MICROSOFT)
 2867         return 1;
 2868     /*
 2869     if (camera->pl->bugs & PTP_MTP)
 2870         return 1;
 2871     */
 2872     return 0;
 2873 }
 2874 
 2875 int
 2876 camera_abilities (CameraAbilitiesList *list)
 2877 {
 2878     unsigned int i;
 2879     CameraAbilities a;
 2880 
 2881     for (i = 0; i < sizeof(models)/sizeof(models[0]); i++) {
 2882         memset(&a, 0, sizeof(a));
 2883         strcpy (a.model, models[i].model);
 2884         a.status        = GP_DRIVER_STATUS_PRODUCTION;
 2885         a.port          = GP_PORT_USB;
 2886         a.speed[0]      = 0;
 2887         a.usb_vendor        = models[i].usb_vendor;
 2888         a.usb_product       = models[i].usb_product;
 2889         a.device_type       = GP_DEVICE_STILL_CAMERA;
 2890         a.operations        = GP_OPERATION_NONE;
 2891 
 2892         /* for now */
 2893         if (models[i].device_flags & PTP_OLYMPUS_XML)
 2894             a.status    = GP_DRIVER_STATUS_EXPERIMENTAL;
 2895 
 2896         if (models[i].device_flags & PTP_CAP) {
 2897             a.operations |= GP_OPERATION_CAPTURE_IMAGE | GP_OPERATION_CONFIG;
 2898 
 2899             /* Only Nikon *D* and *Z* cameras for now -Marcus */
 2900             if (    (models[i].usb_vendor == 0x4b0) &&
 2901                 (strchr(models[i].model,'D') || strchr(models[i].model,'Z'))
 2902             )
 2903                 a.operations |= GP_OPERATION_TRIGGER_CAPTURE;
 2904             /* Also enable trigger capture for EOS capture */
 2905             if (    (models[i].usb_vendor == 0x4a9) &&
 2906                 (strstr(models[i].model,"EOS") || strstr(models[i].model,"Rebel"))
 2907             )
 2908                 a.operations |= GP_OPERATION_TRIGGER_CAPTURE;
 2909             /* Sony Alpha are also trigger capture capable */
 2910             if (    models[i].usb_vendor == 0x54c)
 2911                 a.operations |= GP_OPERATION_TRIGGER_CAPTURE;
 2912 
 2913             /* Olympus test  trigger capture capable */
 2914             if (    models[i].usb_vendor == 0x7b4)
 2915                 a.operations |= GP_OPERATION_TRIGGER_CAPTURE;
 2916 #if 0
 2917             /* SX 100 IS ... works in sdram, not in card mode */
 2918             if (    (models[i].usb_vendor == 0x4a9) &&
 2919                 (models[i].usb_product == 0x315e)
 2920             )
 2921                 a.operations |= GP_OPERATION_TRIGGER_CAPTURE;
 2922 #endif
 2923         }
 2924         if (models[i].device_flags & PTP_CAP_PREVIEW)
 2925             a.operations |= GP_OPERATION_CAPTURE_PREVIEW;
 2926         a.file_operations   = GP_FILE_OPERATION_PREVIEW |
 2927                     GP_FILE_OPERATION_DELETE;
 2928         a.folder_operations = GP_FOLDER_OPERATION_PUT_FILE |
 2929                     GP_FOLDER_OPERATION_MAKE_DIR |
 2930                     GP_FOLDER_OPERATION_REMOVE_DIR;
 2931         CR (gp_abilities_list_append (list, a));
 2932     }
 2933     for (i = 0; i < sizeof(mtp_models)/sizeof(mtp_models[0]); i++) {
 2934         memset(&a, 0, sizeof(a));
 2935         sprintf (a.model, "%s:%s", mtp_models[i].vendor, mtp_models[i].model);
 2936         a.status        = GP_DRIVER_STATUS_PRODUCTION;
 2937         a.port          = GP_PORT_USB;
 2938         a.speed[0]      = 0;
 2939         a.usb_vendor        = mtp_models[i].usb_vendor;
 2940         a.usb_product       = mtp_models[i].usb_product;
 2941         a.operations        = GP_OPERATION_NONE;
 2942         a.device_type       = GP_DEVICE_AUDIO_PLAYER;
 2943         a.file_operations   = GP_FILE_OPERATION_DELETE;
 2944         a.folder_operations = GP_FOLDER_OPERATION_PUT_FILE |
 2945                     GP_FOLDER_OPERATION_MAKE_DIR |
 2946                     GP_FOLDER_OPERATION_REMOVE_DIR;
 2947         CR (gp_abilities_list_append (list, a));
 2948     }
 2949 
 2950     memset(&a, 0, sizeof(a));
 2951     strcpy(a.model, "USB PTP Class Camera");
 2952     a.status = GP_DRIVER_STATUS_TESTING;
 2953     a.port   = GP_PORT_USB;
 2954     a.speed[0] = 0;
 2955     a.usb_class = 6;
 2956     a.usb_subclass = 1;
 2957     a.usb_protocol = 1;
 2958     a.operations =  GP_OPERATION_CAPTURE_IMAGE | /*GP_OPERATION_TRIGGER_CAPTURE |*/
 2959                 GP_OPERATION_CAPTURE_PREVIEW |
 2960             GP_OPERATION_CONFIG;
 2961     a.file_operations   = GP_FILE_OPERATION_PREVIEW|
 2962                 GP_FILE_OPERATION_DELETE;
 2963     a.folder_operations = GP_FOLDER_OPERATION_PUT_FILE
 2964         | GP_FOLDER_OPERATION_MAKE_DIR |
 2965         GP_FOLDER_OPERATION_REMOVE_DIR;
 2966     a.device_type       = GP_DEVICE_STILL_CAMERA;
 2967     CR (gp_abilities_list_append (list, a));
 2968     memset(&a, 0, sizeof(a));
 2969     strcpy(a.model, "MTP Device");
 2970     a.status = GP_DRIVER_STATUS_TESTING;
 2971     a.port   = GP_PORT_USB;
 2972     a.speed[0] = 0;
 2973     a.usb_class = 666;
 2974     a.usb_subclass = -1;
 2975     a.usb_protocol = -1;
 2976     a.operations        = GP_OPERATION_NONE;
 2977     a.file_operations   = GP_FILE_OPERATION_DELETE;
 2978     a.folder_operations = GP_FOLDER_OPERATION_PUT_FILE
 2979         | GP_FOLDER_OPERATION_MAKE_DIR |
 2980         GP_FOLDER_OPERATION_REMOVE_DIR;
 2981     a.device_type       = GP_DEVICE_AUDIO_PLAYER;
 2982     CR (gp_abilities_list_append (list, a));
 2983 
 2984     for (i = 0; i < sizeof(ptpip_models)/sizeof(ptpip_models[0]); i++) {
 2985         memset(&a, 0, sizeof(a));
 2986         strcpy(a.model, ptpip_models[i].model);
 2987         a.status        = GP_DRIVER_STATUS_TESTING;
 2988         if (strstr(ptpip_models[i].model,"Fuji"))
 2989             a.status        = GP_DRIVER_STATUS_EXPERIMENTAL;
 2990         a.port          = GP_PORT_PTPIP;
 2991         a.operations        = GP_OPERATION_CONFIG;
 2992         if (ptpip_models[i].device_flags & PTP_CAP)
 2993             a.operations    |= GP_OPERATION_CAPTURE_IMAGE;
 2994         if (ptpip_models[i].device_flags & PTP_CAP_PREVIEW)
 2995             a.operations    |= GP_OPERATION_CAPTURE_PREVIEW;
 2996         a.file_operations   =   GP_FILE_OPERATION_PREVIEW   |
 2997                     GP_FILE_OPERATION_DELETE;
 2998         a.folder_operations =   GP_FOLDER_OPERATION_PUT_FILE    |
 2999                     GP_FOLDER_OPERATION_MAKE_DIR    |
 3000                     GP_FOLDER_OPERATION_REMOVE_DIR;
 3001         a.device_type       = GP_DEVICE_STILL_CAMERA;
 3002         CR (gp_abilities_list_append (list, a));
 3003     }
 3004 
 3005     return (GP_OK);
 3006 }
 3007 
 3008 int
 3009 camera_id (CameraText *id)
 3010 {
 3011     strcpy (id->text, "PTP");
 3012 
 3013     return (GP_OK);
 3014 }
 3015 
 3016 static int
 3017 camera_exit (Camera *camera, GPContext *context)
 3018 {
 3019     if (camera->pl!=NULL) {
 3020         PTPParams *params = &camera->pl->params;
 3021         PTPContainer event;
 3022         SET_CONTEXT_P(params, context);
 3023 
 3024         switch (params->deviceinfo.VendorExtensionID) {
 3025         case PTP_VENDOR_CANON:
 3026             /* Disable EOS capture now, also end viewfinder mode. */
 3027             if (params->eos_captureenabled) {
 3028                 if (camera->pl->checkevents) {
 3029                     PTPCanon_changes_entry entry;
 3030 
 3031                     ptp_check_eos_events (params);
 3032                     while (ptp_get_one_eos_event (params, &entry)) {
 3033                         GP_LOG_D ("missed EOS ptp type %d", entry.type);
 3034                         if (entry.type == PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN)
 3035                             free (entry.u.info);
 3036                     }
 3037                     camera->pl->checkevents = 0;
 3038                 }
 3039                 if (params->inliveview && ptp_operation_issupported(params, PTP_OC_CANON_EOS_TerminateViewfinder))
 3040                     ptp_canon_eos_end_viewfinder (params);
 3041                 camera_unprepare_capture (camera, context);
 3042             }
 3043             break;
 3044         case PTP_VENDOR_NIKON:
 3045             if (ptp_operation_issupported(params, PTP_OC_NIKON_EndLiveView))
 3046                 C_PTP (ptp_nikon_end_liveview (params));
 3047             params->inliveview = 0;
 3048 
 3049             /* get the Nikon out of control mode again */
 3050             if (params->controlmode && ptp_operation_issupported(params,PTP_OC_NIKON_ChangeCameraMode)) {
 3051                 ptp_nikon_changecameramode (params, 0);
 3052                 params->controlmode = 0;
 3053             }
 3054             break;
 3055         case PTP_VENDOR_SONY:
 3056 #if 0
 3057             /* if we call this, the camera shuts down on close in MTP mode */
 3058             if (ptp_operation_issupported(params, 0x9280)) {
 3059                 C_PTP (ptp_sony_9280(params, 0x4,0,5,0,0,0,0));
 3060             }
 3061 #endif
 3062             break;
 3063         case PTP_VENDOR_FUJI:
 3064             CR (camera_unprepare_capture (camera, context));
 3065             break;
 3066         case PTP_VENDOR_GP_OLYMPUS_OMD: {
 3067             PTPPropertyValue propval;
 3068 
 3069             propval.u16 = 0;
 3070             CR (ptp_setdevicepropvalue (params, 0xD052, &propval, PTP_DTC_UINT16));
 3071             break;
 3072         }
 3073         case PTP_VENDOR_GP_LEICA:
 3074             if (ptp_operation_issupported(params, PTP_OC_LEICA_LECloseSession)) {
 3075                 C_PTP (ptp_leica_leclosesession (params));
 3076             }
 3077             break;
 3078         }
 3079 
 3080         if (camera->pl->checkevents)
 3081             ptp_check_event (params);
 3082         while (ptp_get_one_event (params, &event))
 3083             GP_LOG_D ("missed ptp event 0x%x (param1=%x)", event.Code, event.Param1);
 3084 
 3085         /* 2016 EOS cameras do not like that and report 0x2005 on all following opcodes */
 3086         if (!DONT_CLOSE_SESSION(params)) {
 3087             /* close ptp session */
 3088             ptp_closesession (params);
 3089         }
 3090         ptp_free_params(params);
 3091 
 3092 #if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
 3093         /* close iconv converters */
 3094         if (params->cd_ucs2_to_locale != (iconv_t)-1) iconv_close(params->cd_ucs2_to_locale);
 3095         if (params->cd_locale_to_ucs2 != (iconv_t)-1) iconv_close(params->cd_locale_to_ucs2);
 3096 #endif
 3097 
 3098         free (params->data);
 3099         free (camera->pl); /* also frees params */
 3100         params = NULL;
 3101         camera->pl = NULL;
 3102     }
 3103     /* This code hangs USB 3 devices after the first bulk image transmission.
 3104          * For some unknown reason. */
 3105     if (0 && (camera->port!=NULL) && (camera->port->type == GP_PORT_USB)) {
 3106         /* clear halt */
 3107         gp_port_usb_clear_halt
 3108                 (camera->port, GP_PORT_USB_ENDPOINT_IN);
 3109         gp_port_usb_clear_halt
 3110                 (camera->port, GP_PORT_USB_ENDPOINT_OUT);
 3111         gp_port_usb_clear_halt
 3112                 (camera->port, GP_PORT_USB_ENDPOINT_INT);
 3113     }
 3114 #if defined(HAVE_LIBWS232) && defined(WIN32)
 3115     else if ((camera->port!=NULL) && camera->port->type != GP_PORT_PTPIP) {
 3116         WSACleanup();
 3117     }
 3118 #endif
 3119     return (GP_OK);
 3120 }
 3121 
 3122 static int
 3123 camera_about (Camera *camera, CameraText *text, GPContext *context)
 3124 {
 3125     /* Note that we are not a so called 'Licensed Implementation' of MTP
 3126      * ... (for a LI you need express approval from Microsoft etc.)
 3127      */
 3128     snprintf (text->text, sizeof(text->text),
 3129      _("PTP2 driver\n"
 3130        "(c) 2001-2005 by Mariusz Woloszyn <emsi@ipartners.pl>.\n"
 3131        "(c) 2003-%d by Marcus Meissner <marcus@jet.franken.de>.\n"
 3132        "This driver supports cameras that support PTP or PictBridge(tm), and\n"
 3133        "Media Players that support the Media Transfer Protocol (MTP).\n"
 3134        "\n"
 3135        "Enjoy!"), 2021);
 3136     return (GP_OK);
 3137 }
 3138 
 3139 static void debug_objectinfo(PTPParams *params, uint32_t oid, PTPObjectInfo *oi);
 3140 
 3141 /* Add new object to internal driver structures. issued when creating
 3142  * folder, uploading objects, or captured images.
 3143  */
 3144 static int
 3145 add_object (Camera *camera, uint32_t handle, GPContext *context)
 3146 {
 3147     PTPObject *ob;
 3148     PTPParams *params = &camera->pl->params;
 3149 
 3150     C_PTP (ptp_object_want (params, handle, 0, &ob));
 3151     return GP_OK;
 3152 }
 3153 
 3154 static int
 3155 camera_capture_stream_preview (Camera *camera, CameraFile *file, GPContext *context) {
 3156     PTPParams       *params = &camera->pl->params;
 3157     PTPPropertyValue    propval;
 3158     PTPStreamInfo       sinfo;
 3159     unsigned char       *data;
 3160     unsigned int        size;
 3161 
 3162     C_PTP (ptp_getdevicepropvalue (params, PTP_DPC_EnabledStreams, &propval, PTP_DTC_UINT32));
 3163     if (!(propval.u32 & 1)) {   /* video enabled already ? */
 3164         propval.u32 = 1;
 3165         C_PTP (ptp_setdevicepropvalue (params, PTP_DPC_EnabledStreams, &propval, PTP_DTC_UINT32));
 3166     }
 3167     C_PTP (ptp_getstreaminfo (params, 1, &sinfo));
 3168 
 3169     if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_GP_LEICA) &&
 3170         (ptp_operation_issupported(params, PTP_OC_LEICA_LEGetStreamData))
 3171     ) {
 3172         /* ptp header + header before ff d8
 3173         0000  58 1c 00 00 02 00 25 90-0b 00 00 00 02 01 00 00  X.....%.........
 3174         0010  46 1c 00 00 00 00 3e 1c-00 00 00 00 b4 00 00 00  F.....>.........
 3175         0020  01 00 00 00 04 00 00 00-d4 30 00 00 02 00 00 00  .........0......
 3176         0030  04 00 00 00 d4 30 00 00-03 00 00 00 04 00 00 00  .....0..........
 3177         0040  53 06 00 00 04 00 00 00-40 00 00 00 00 00 00 00  S.......@.......
 3178         0050  00 00 00 00 00 00 00 00-00 00 00 00 70 17 00 00  ............p...
 3179         0060  a0 0f 00 00 00 00 00 00-00 00 00 00 70 17 00 00  ............p...
 3180         0070  a0 0f 00 00 00 00 00 00-00 00 00 00 70 17 00 00  ............p...
 3181         0080  a0 0f 00 00 fe ff ff ff-fe ff ff ff 05 00 00 00  ................
 3182         0090  04 00 00 00 00 00 00 00-06 00 00 00 10 00 00 00  ................
 3183         00a0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
 3184         00b0  07 00 00 00 04 00 00 00-00 00 00 00 00 00 00 00  ................
 3185         00c0  ff d8
 3186         */
 3187 
 3188         C_PTP (ptp_getdevicepropvalue (params, PTP_DPC_VideoFormat, &propval, PTP_DTC_UINT32));
 3189 
 3190         C_PTP (ptp_leica_getstreamdata (params, &data, &size));
 3191         if (propval.u32 == 0x47504a4d) { /* MJPG */
 3192             unsigned char   *jpgStartPtr;
 3193 
 3194             /* look for the JPEG SOI marker (0xFFD8) in data */
 3195             jpgStartPtr = (unsigned char*)memchr(data, 0xff, size);
 3196             while(jpgStartPtr && ((jpgStartPtr+1) < (data + size))) {
 3197                 if(*(jpgStartPtr + 1) == 0xd8) { /* SOI found */
 3198                     break;
 3199                 } else { /* go on looking (starting at next byte) */
 3200                     jpgStartPtr++;
 3201                     jpgStartPtr = (unsigned char*)memchr(jpgStartPtr, 0xff, data + size - jpgStartPtr);
 3202                 }
 3203             }
 3204             if(!jpgStartPtr) { /* no SOI -> no JPEG */
 3205                 gp_context_error (context, _("Sorry, your Nikon camera does not seem to return a JPEG image in LiveView mode"));
 3206                 return GP_ERROR;
 3207             }
 3208 
 3209             /* assume ff d9 is at the end for now */
 3210             gp_file_append (file, (char*)jpgStartPtr, size - (jpgStartPtr - data));
 3211             gp_file_set_mime_type (file, GP_MIME_JPEG);
 3212             gp_file_set_name (file, "preview.jpg");
 3213         } else {
 3214             gp_file_append (file, (char*)data, size);
 3215         }
 3216         gp_file_set_mtime (file, time(NULL));
 3217         free (data);
 3218         SET_CONTEXT_P(params, NULL);
 3219         return GP_OK;
 3220     }
 3221     if (ptp_operation_issupported(params, PTP_OC_GetStream)) {
 3222         C_PTP (ptp_getstream (params, &data, &size));
 3223         gp_file_append (file, (char*)data, size);
 3224         free (data);
 3225         SET_CONTEXT_P(params, NULL);
 3226         return GP_OK;
 3227     }
 3228     SET_CONTEXT_P(params, NULL);
 3229     return GP_ERROR_NOT_SUPPORTED;
 3230 }
 3231 
 3232 static int
 3233 camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
 3234 {
 3235     unsigned char   *data = NULL, *jpgStartPtr = NULL, *jpgEndPtr = NULL;
 3236     uint32_t    size = 0;
 3237     uint16_t    ret;
 3238     PTPParams *params = &camera->pl->params;
 3239 
 3240     camera->pl->checkevents = TRUE;
 3241     switch (params->deviceinfo.VendorExtensionID) {
 3242     case PTP_VENDOR_CANON:
 3243         /* Canon PowerShot / IXUS preview mode */
 3244         if (ptp_operation_issupported(params, PTP_OC_CANON_ViewfinderOn)) {
 3245             SET_CONTEXT_P(params, context);
 3246             /* check if we need to prepare capture */
 3247             if (!params->canon_event_mode)
 3248                 CR (camera_prepare_capture (camera, context));
 3249             if (!params->canon_viewfinder_on) { /* enable on demand, but just once */
 3250                 C_PTP_REP_MSG (ptp_canon_viewfinderon (params),
 3251                            _("Canon enable viewfinder failed"));
 3252                 params->canon_viewfinder_on = 1;
 3253             }
 3254             C_PTP_REP_MSG (ptp_canon_getviewfinderimage (params, &data, &size),
 3255                        _("Canon get viewfinder image failed"));
 3256             gp_file_append ( file, (char*)data, size );
 3257             free (data);
 3258             gp_file_set_mime_type (file, GP_MIME_JPEG);     /* always */
 3259             /* Add an arbitrary file name so caller won't crash */
 3260             gp_file_set_name (file, "canon_preview.jpg");
 3261             gp_file_set_mtime (file, time(NULL));
 3262             SET_CONTEXT_P(params, NULL);
 3263             return GP_OK;
 3264         }
 3265         /* Canon EOS DSLR preview mode */
 3266         if (ptp_operation_issupported(params, PTP_OC_CANON_EOS_GetViewFinderData)) {
 3267             PTPPropertyValue    val;
 3268             /* FIXME: this might cause a focusing pass and take seconds. 20 was not
 3269              * enough (would be 0.2 seconds, too short for the mirror up operation.). */
 3270             /* The EOS 100D takes 1.2 seconds */
 3271             PTPDevicePropDesc       dpd;
 3272             int         try = 0;
 3273             struct timeval      event_start;
 3274 
 3275             SET_CONTEXT_P(params, context);
 3276 
 3277             if (!params->eos_captureenabled)
 3278                 camera_prepare_capture (camera, context);
 3279             memset (&dpd,0,sizeof(dpd));
 3280 
 3281             /* do not set it everytime, it will cause delays */
 3282             ret = ptp_canon_eos_getdevicepropdesc (params, PTP_DPC_CANON_EOS_EVFMode, &dpd);
 3283             if ((ret == PTP_RC_OK) && (dpd.CurrentValue.u16 != 1)) {
 3284                 /* 0 means off, 1 means on */
 3285                 val.u16 = 1;
 3286                 ret = ptp_canon_eos_setdevicepropvalue (params, PTP_DPC_CANON_EOS_EVFMode, &val, PTP_DTC_UINT16);
 3287                 /* in movie mode we get busy, but can proceed */
 3288                 if ((ret != PTP_RC_OK) && (ret != PTP_RC_DeviceBusy))
 3289                     C_PTP_MSG (ret, "setval of evf enable to 1 failed (curval is %d)!", dpd.CurrentValue.u16);
 3290             }
 3291             ptp_free_devicepropdesc (&dpd);
 3292             /* do not set it everytime, it will cause delays */
 3293             ret = ptp_canon_eos_getdevicepropdesc (params, PTP_DPC_CANON_EOS_EVFOutputDevice, &dpd);
 3294             /* see config.c what kind of values we have ... it seems to be a mask. bit 0 is TFT, bit 1 PC, bit 2 MOBILE, bit 3 MOBILE2? */
 3295             /* so lets see it only if it does not have any bit set (discounted bit 0) */
 3296             if ((ret == PTP_RC_OK) && ((dpd.CurrentValue.u32 & ~1) == 0)) {
 3297                 /* 2 means PC, 1 means TFT */
 3298                 val.u32 = 2;
 3299                 C_PTP_MSG (ptp_canon_eos_setdevicepropvalue (params, PTP_DPC_CANON_EOS_EVFOutputDevice, &val, PTP_DTC_UINT32),
 3300                        "setval of evf outputmode to 2 failed (curval is %d)!", dpd.CurrentValue.u32);
 3301             }
 3302             ptp_free_devicepropdesc (&dpd);
 3303 
 3304             /* Otherwise the camera will auto-shutdown */
 3305             if (ptp_operation_issupported(params, PTP_OC_CANON_EOS_KeepDeviceOn)) C_PTP (ptp_canon_eos_keepdeviceon (params));
 3306 
 3307             params->inliveview = 1;
 3308             event_start = time_now();
 3309             do {
 3310                 unsigned char   *xdata;
 3311                 /* Poll for camera events, but just call
 3312                  * it once and do not drain the queue now */
 3313                 C_PTP (ptp_check_eos_events (params));
 3314 
 3315                 ret = ptp_canon_eos_get_viewfinder_image (params , &data, &size);
 3316                 if ((ret == 0xa102) || (ret == PTP_RC_DeviceBusy)) { /* means "not there yet" ... so wait */
 3317                     /* wait 3 seconds at most ... use a bit of backoff logic for cameras where we should not drain compute. */
 3318                     usleep((++try)*5*1000);
 3319                     if (time_since (event_start) < 3*1000)
 3320                         continue;
 3321 /*
 3322                     if (waiting_for_timeout (&back_off_wait, event_start, 3*1000))
 3323                         continue;
 3324 */
 3325                 }
 3326                 C_PTP_MSG (ret, "get_viewfinder_image failed");
 3327 
 3328                 /* returns multiple blobs, they are usually structured as
 3329                  * uint32 len
 3330                  * uint32 type
 3331                  * ... data ...
 3332                  *
 3333                  * 1: JPEG preview
 3334                  */
 3335 
 3336                 xdata = data;
 3337                 GP_LOG_D ("total size: len=%d", size);
 3338                 while ((xdata-data) < size) {
 3339                     uint32_t    len  = dtoh32a(xdata);
 3340                     uint32_t    type = dtoh32a(xdata+4);
 3341 
 3342                     /* 4 byte len of jpeg data, 4 byte type */
 3343                     /* JPEG blob */
 3344                     /* stuff */
 3345                     GP_LOG_D ("get_viewfinder_image header: len=%d type=%d", len, type);
 3346                     switch (type) {
 3347                     default:
 3348                         if (len > (size-(xdata-data))) {
 3349                             len = size;
 3350                             GP_LOG_E ("len=%d larger than rest size %ld", len, (size-(xdata-data)));
 3351                         }
 3352                         GP_LOG_DATA ((char*)xdata, len, "get_viewfinder_image header:");
 3353                         xdata = xdata+len;
 3354                         continue;
 3355                     case 9:
 3356                     case 1:
 3357                     case 11:
 3358                         if (len > (size-(xdata-data))) {
 3359                             len = size;
 3360                             GP_LOG_E ("len=%d larger than rest size %ld", len, (size-(xdata-data)));
 3361                             break;
 3362                         }
 3363                         gp_file_append ( file, (char*)xdata+8, len-8 );
 3364                         /* type 1 is JPEG (regular), type 9 is in movie mode */
 3365 
 3366                         gp_file_set_mime_type (file, ((type == 1) || (type == 11)) ? GP_MIME_JPEG : GP_MIME_RAW);
 3367 
 3368                         /* Add an arbitrary file name so caller won't crash */
 3369                         gp_file_set_name (file, "preview.jpg");
 3370 
 3371                         /* dump the rest of the blobs */
 3372                         xdata = xdata+len;
 3373                         while ((xdata-data) < size) {
 3374                             len  = dtoh32a(xdata);
 3375                             type = dtoh32a(xdata+4);
 3376 
 3377                             if (len > (size-(xdata-data))) {
 3378                                 len = size;
 3379                                 GP_LOG_E ("len=%d larger than rest size %ld", len, (size-(xdata-data)));
 3380                                 break;
 3381                             }
 3382                             GP_LOG_D ("get_viewfinder_image header: len=%d type=%d", len, type);
 3383                             GP_LOG_DATA ((char*)xdata, len, "get_viewfinder_image header:");
 3384                             xdata = xdata+len;
 3385                         }
 3386                         free (data);
 3387                         SET_CONTEXT_P(params, NULL);
 3388                         return GP_OK;
 3389                     }
 3390                 }
 3391                 return GP_ERROR;
 3392             } while (1);
 3393             GP_LOG_E ("get_viewfinder_image failed after all tries with ret: 0x%x\n", ret);
 3394             SET_CONTEXT_P(params, NULL);
 3395             return translate_ptp_result (ret);
 3396         }
 3397         gp_context_error (context, _("Sorry, your Canon camera does not support Canon Viewfinder mode"));
 3398         return GP_ERROR_NOT_SUPPORTED;
 3399     case PTP_VENDOR_NIKON: {
 3400         PTPPropertyValue    value;
 3401         int             tries, firstimage = 0;
 3402 
 3403         if (!ptp_operation_issupported(params, PTP_OC_NIKON_StartLiveView)) {
 3404             gp_context_error (context,
 3405                 _("Sorry, your Nikon camera does not support LiveView mode"));
 3406             return GP_ERROR_NOT_SUPPORTED;
 3407         }
 3408         SET_CONTEXT_P(params, context);
 3409 
 3410         /* Nilon V and J seem to like that */
 3411         if (!params->controlmode && ptp_operation_issupported(params,PTP_OC_NIKON_ChangeCameraMode)) {
 3412             ret = ptp_nikon_changecameramode (params, 1);
 3413             /* FIXME: PTP_RC_NIKON_ChangeCameraModeFailed does not seem to be problematic */
 3414             if (ret != PTP_RC_NIKON_ChangeCameraModeFailed)
 3415                 C_PTP_REP (ret);
 3416             params->controlmode = 1;
 3417         }
 3418 
 3419         ret = ptp_getdevicepropvalue (params, PTP_DPC_NIKON_LiveViewStatus, &value, PTP_DTC_UINT8);
 3420         if (ret != PTP_RC_OK)
 3421             value.u8 = 0;
 3422 
 3423 enable_liveview:
 3424         if (!value.u8) {
 3425             value.u8 = 1;
 3426             if (have_prop(camera, params->deviceinfo.VendorExtensionID, PTP_DPC_NIKON_RecordingMedia))
 3427                 LOG_ON_PTP_E (ptp_setdevicepropvalue (params, PTP_DPC_NIKON_RecordingMedia, &value, PTP_DTC_UINT8));
 3428 
 3429             if (have_prop(camera, params->deviceinfo.VendorExtensionID, PTP_DPC_NIKON_LiveViewProhibitCondition)) {
 3430                 PTPPropertyValue    cond;
 3431                 C_PTP (ptp_getdevicepropvalue (params, PTP_DPC_NIKON_LiveViewProhibitCondition, &cond, PTP_DTC_UINT32));
 3432 
 3433                 if (cond.u32) {
 3434                     /* we could have multiple reasons, but just report the first one. by decreasing order of possibility */
 3435                     if (cond.u32 & (1<<8)) { gp_context_error (context, _("Liveview cannot start: Battery exhausted")); return GP_ERROR; }
 3436                     if (cond.u32 & (1<<17)){ gp_context_error (context, _("Liveview cannot start: Temperature too high")); return GP_ERROR; }
 3437                     if (cond.u32 & (1<<9)) { gp_context_error (context, _("Liveview cannot start: TTL error")); return GP_ERROR; }
 3438                     if (cond.u32 & (1<<22)){ gp_context_error (context, _("Liveview cannot start: In Mirror-up operation")); return GP_ERROR; }
 3439                     if (cond.u32 & (1<<24)){ gp_context_error (context, _("Liveview cannot start: Lens is retracting")); return GP_ERROR; }
 3440                     if (cond.u32 & (1<<5)) { gp_context_error (context, _("Liveview cannot start: Minimum aperture warning")); return GP_ERROR; }
 3441                     if (cond.u32 & (1<<15)){ gp_context_error (context, _("Liveview cannot start: Processing of shooting operation")); return GP_ERROR; }
 3442                     if (cond.u32 & (1<<2)) { gp_context_error (context, _("Liveview cannot start: Sequence error")); return GP_ERROR; }
 3443                     if (cond.u32 & (1<<31)) { gp_context_error (context, _("Liveview cannot start: Exposure Program Mode is not P/A/S/M")); return GP_ERROR; }
 3444                     if (cond.u32 & (1<<21)) { gp_context_error (context, _("Liveview cannot start: Bulb warning")); return GP_ERROR; }
 3445                     if (cond.u32 & (1<<20)) { gp_context_error (context, _("Liveview cannot start: Card unformatted")); return GP_ERROR; }
 3446                     if (cond.u32 & (1<<19)) { gp_context_error (context, _("Liveview cannot start: Card error")); return GP_ERROR; }
 3447                     if (cond.u32 & (1<<18)) { gp_context_error (context, _("Liveview cannot start: Card protected")); return GP_ERROR; }
 3448                     if (cond.u32 & (1<<14)) { gp_context_error (context, _("Liveview cannot start: Recording destination card, but no card or card protected")); return GP_ERROR; }
 3449                     if (cond.u32 & (1<<12)) { gp_context_error (context, _("Liveview cannot start: Pending unretrieved SDRAM image")); return GP_ERROR; }
 3450                     if (cond.u32 & (1<<12)) { gp_context_error (context, _("Liveview cannot start: Pending unretrieved SDRAM image")); return GP_ERROR; }
 3451                     if (cond.u32 & (1<<4)) { gp_context_error (context, _("Liveview cannot start: Fully pressed button")); return GP_ERROR; }
 3452                     gp_context_error (context, _("Liveview cannot start: code 0x%08x"), cond.u32);
 3453                     return GP_ERROR;
 3454                 }
 3455             }
 3456 
 3457             ret = ptp_nikon_start_liveview (params);
 3458             if ((ret != PTP_RC_OK) && (ret != PTP_RC_DeviceBusy))
 3459                 C_PTP_REP_MSG (ret, _("Nikon enable liveview failed"));
 3460 
 3461             /* wait up to 1 second */
 3462             C_PTP_REP_MSG (nikon_wait_busy(params,20,2000), _("Nikon enable liveview failed"));
 3463             params->inliveview = 1;
 3464             firstimage = 1;
 3465         }
 3466         /* nikon 1 special */
 3467         if (value.u8 && !params->inliveview) {
 3468             ret = ptp_nikon_start_liveview (params);
 3469             if ((ret != PTP_RC_OK) && (ret != PTP_RC_DeviceBusy))
 3470                 C_PTP_REP_MSG (ret, _("Nikon enable liveview failed"));
 3471 
 3472             C_PTP_REP_MSG (nikon_wait_busy(params,20,2000), _("Nikon enable liveview failed"));
 3473             params->inliveview = 1;
 3474         }
 3475         tries = 20;
 3476         while (tries--) {
 3477             ret = ptp_nikon_get_liveview_image (params , &data, &size);
 3478             if (ret == PTP_RC_NIKON_NotLiveView) {
 3479                 /* this happens on the D7000 after 14000 frames... reenable liveview */
 3480                 params->inliveview = 0;
 3481                 value.u8 = 0;
 3482                 goto enable_liveview;
 3483             }
 3484             if (ret == PTP_RC_OK) {
 3485                 if (firstimage) {
 3486                     /* the first image on the S9700 is corrupted. so just skip the first image */
 3487                     firstimage = 0;
 3488                     free (data);
 3489                     continue;
 3490                 }
 3491                 /* look for the JPEG SOI marker (0xFFD8) in data */
 3492                 jpgStartPtr = (unsigned char*)memchr(data, 0xff, size);
 3493                 while(jpgStartPtr && ((jpgStartPtr+1) < (data + size))) {
 3494                     if(*(jpgStartPtr + 1) == 0xd8) { /* SOI found */
 3495                         break;
 3496                     } else { /* go on looking (starting at next byte) */
 3497                         jpgStartPtr++;
 3498                         jpgStartPtr = (unsigned char*)memchr(jpgStartPtr, 0xff, data + size - jpgStartPtr);
 3499                     }
 3500                 }
 3501                 if(!jpgStartPtr) { /* no SOI -> no JPEG */
 3502                     gp_context_error (context, _("Sorry, your Nikon camera does not seem to return a JPEG image in LiveView mode"));
 3503                     return GP_ERROR;
 3504                 }
 3505                 /* if SOI found, start looking for EOI marker (0xFFD9) one byte after SOI
 3506                    (just to be sure we will not go beyond the end of the data array) */
 3507                 jpgEndPtr = (unsigned char*)memchr(jpgStartPtr+1, 0xff, data+size-jpgStartPtr-1);
 3508                 while(jpgEndPtr && ((jpgEndPtr+1) < (data + size))) {
 3509                     if(*(jpgEndPtr + 1) == 0xd9) { /* EOI found */
 3510                         jpgEndPtr += 2;
 3511                         break;
 3512                     } else { /* go on looking (starting at next byte) */
 3513                         jpgEndPtr++;
 3514                         jpgEndPtr = (unsigned char*)memchr(jpgEndPtr, 0xff, data + size - jpgEndPtr);
 3515                     }
 3516                 }
 3517                 if(!jpgEndPtr) { /* no EOI -> no JPEG */
 3518                     gp_context_error (context, _("Sorry, your Nikon camera does not seem to return a JPEG image in LiveView mode"));
 3519                     return GP_ERROR;
 3520                 }
 3521                 gp_file_append (file, (char*)jpgStartPtr, jpgEndPtr-jpgStartPtr);
 3522                 free (data); /* FIXME: perhaps handle the 128 byte header data too. */
 3523                 gp_file_set_mime_type (file, GP_MIME_JPEG);     /* always */
 3524                 /* Add an arbitrary file name so caller won't crash */
 3525                 gp_file_set_name (file, "preview.jpg");
 3526                 gp_file_set_mtime (file, time(NULL));
 3527                 break;
 3528             }
 3529             if (ret == PTP_RC_DeviceBusy) {
 3530                 GP_LOG_D ("busy, retrying after a bit of wait, try %d", tries);
 3531                 usleep(10*1000);
 3532                 continue;
 3533             }
 3534             SET_CONTEXT_P(params, NULL);
 3535             return translate_ptp_result (ret);
 3536         }
 3537 #if 0
 3538         C_PTP_REP_MSG (ptp_nikon_end_liveview (params),
 3539                    _("Nikon disable liveview failed"));
 3540 #endif
 3541         SET_CONTEXT_P(params, NULL);
 3542         return GP_OK;
 3543     }
 3544     case PTP_VENDOR_SONY: {
 3545         /* same for Alpha series and QX */
 3546         uint32_t    preview_object = 0xffffc002; /* this is where the liveview image is accessed */
 3547         unsigned char   *ximage = NULL;
 3548         int     tries = 50;
 3549 
 3550 #if 0
 3551         /* this times out, with 0.3 seconds wait ... bad */
 3552         ptp_check_event (params);   /* will stall for some reason */
 3553 #endif
 3554         do {
 3555             PTPObjectInfo oi;
 3556 
 3557             /* This state can persist for up to 1 second on the ZV-1 */
 3558             ret = ptp_getobjectinfo(params, preview_object, &oi);
 3559             if (ret == PTP_RC_InvalidObjectHandle) {
 3560                 usleep(50*1000);
 3561                 continue;
 3562             }
 3563 
 3564             ret = ptp_getobject_with_size(params, preview_object, &ximage, &size);
 3565             if (ret == PTP_RC_OK)
 3566                 break;
 3567             if (ret != PTP_RC_AccessDenied) /* we get those when we are too fast */
 3568                 C_PTP (ret);
 3569             usleep(20*1000);
 3570         } while (tries--);
 3571 
 3572         jpgStartPtr = ximage;
 3573         /* There is an initial blob, and we had a case where 0xff 0xd8 was in the initial blob
 3574          * https://github.com/gphoto/gphoto2/issues/389
 3575          * as the data starts with an apparent offset into the data to the JPEG, try to use that
 3576          */
 3577         if (size > 4) {
 3578             unsigned int offset = ximage[0] | (ximage[1] << 8) | (ximage[2] << 16) | (ximage[3] << 24);
 3579             if ((offset+1 < size) && (ximage[offset] == 0xff) && (ximage[offset+1] == 0xd8))
 3580                 jpgStartPtr = ximage + offset;
 3581         }
 3582 
 3583         /* look for the JPEG SOI marker (0xFFD8) in data */
 3584         jpgStartPtr = (unsigned char*)memchr(jpgStartPtr, 0xff, size);
 3585         while(jpgStartPtr && ((jpgStartPtr+1) < (ximage + size))) {
 3586             if(*(jpgStartPtr + 1) == 0xd8) { /* SOI found */
 3587                 break;
 3588             } else { /* go on looking (starting at next byte) */
 3589                 jpgStartPtr++;
 3590                 jpgStartPtr = (unsigned char*)memchr(jpgStartPtr, 0xff, ximage + size - jpgStartPtr);
 3591             }
 3592         }
 3593         if(!jpgStartPtr) { /* no SOI -> no JPEG */
 3594             gp_context_error (context, _("Sorry, your Sony camera does not seem to return a JPEG image in LiveView mode"));
 3595             return GP_ERROR;
 3596         }
 3597         /* if SOI found, start looking for EOI marker (0xFFD9) one byte after SOI
 3598            (just to be sure we will not go beyond the end of the data array) */
 3599         jpgEndPtr = (unsigned char*)memchr(jpgStartPtr+1, 0xff, ximage+size-jpgStartPtr-1);
 3600         while(jpgEndPtr && ((jpgEndPtr+1) < (ximage + size))) {
 3601             if(*(jpgEndPtr + 1) == 0xd9) { /* EOI found */
 3602                 jpgEndPtr += 2;
 3603                 break;
 3604             } else { /* go on looking (starting at next byte) */
 3605                 jpgEndPtr++;
 3606                 jpgEndPtr = (unsigned char*)memchr(jpgEndPtr, 0xff, ximage + size - jpgEndPtr);
 3607             }
 3608         }
 3609         if(!jpgEndPtr) { /* no EOI -> no JPEG */
 3610             gp_context_error (context, _("Sorry, your Sony camera does not seem to return a JPEG image in LiveView mode"));
 3611             return GP_ERROR;
 3612         }
 3613         gp_file_append (file, (char*)jpgStartPtr, jpgEndPtr-jpgStartPtr);
 3614         free (ximage); /* FIXME: perhaps handle the 128 byte header data too. */
 3615 
 3616         gp_file_set_mime_type (file, GP_MIME_JPEG);
 3617         gp_file_set_name (file, "sony_preview.jpg");
 3618         gp_file_set_mtime (file, time(NULL));
 3619 
 3620         SET_CONTEXT_P(params, NULL);
 3621         return GP_OK;
 3622     }
 3623     case PTP_VENDOR_FUJI: {
 3624         PTPObjectInfo   oi;
 3625         uint32_t    preview_object = 0x80000001; /* this is where the liveview image is accessed */
 3626         unsigned char   *ximage = NULL;
 3627         int     tries = 10;
 3628 
 3629         if (params->jpgfd) {
 3630             unsigned int i;
 3631             C_PTP (ptp_fujiptpip_jpeg (params, &ximage, &size));
 3632             /* there is a bit of header in front ... skip it */
 3633             for (i=0;i<size;i++)
 3634                 if (ximage[i]==0xff)
 3635                     break;
 3636             gp_file_append (file, (char*)ximage+i, size-i);
 3637             free (ximage);
 3638 
 3639             gp_file_set_mime_type (file, GP_MIME_JPEG);
 3640             gp_file_set_name (file, "fuji_preview.jpg");
 3641             gp_file_set_mtime (file, time(NULL));
 3642 
 3643             SET_CONTEXT_P(params, NULL);
 3644             return GP_OK;
 3645         }
 3646 
 3647         while (tries--) {
 3648             ret = ptp_getobjectinfo (params, preview_object, &oi);
 3649             if (ret == PTP_RC_OK) break;
 3650             if (ret == PTP_RC_InvalidObjectHandle) {
 3651                 /* 1000 x 10 tries was not enough for the S10 ... make the wait a bit longer
 3652                  * see https://github.com/gphoto/libgphoto2/issues/603 */
 3653                 usleep(5*1000);
 3654                 continue;
 3655             }
 3656             C_PTP_REP (ret);
 3657         }
 3658 
 3659         if(ret != PTP_RC_OK) {
 3660             tries = 5;
 3661             while (tries--) {
 3662                 ret = ptp_initiateopencapture(params, 0x00000000, 0x00000000);
 3663                 if (ret == PTP_RC_OK) {
 3664                     params->opencapture_transid = params->transaction_id-1;
 3665                     params->inliveview = 1;
 3666                     usleep(100*1000); /* this basically waits until the first object is there. */
 3667                     break;
 3668                 }
 3669                 usleep(200*1000);
 3670             }
 3671         }
 3672 
 3673         tries = 20;
 3674         do {
 3675             ret = ptp_getobject_with_size(params, preview_object, &ximage, &size);
 3676             if (ret == PTP_RC_OK)
 3677                 break;
 3678             if(ret == PTP_RC_DeviceBusy) {
 3679                 usleep(1000);
 3680                 continue;
 3681             }
 3682 
 3683             if (ret != PTP_RC_AccessDenied) /* we get those when we are too fast */ /* priobably pasted from nikon, check? */
 3684                 C_PTP (ret);
 3685         } while (tries--);
 3686         C_PTP_REP (ptp_deleteobject(params, preview_object, 0));
 3687 
 3688         /* Fuji Liveview returns FF D8 ... FF D9 ... so no meta data wrapped around the jpeg data */
 3689         gp_file_append (file, (char*)ximage, size);
 3690         free (ximage);
 3691 
 3692         gp_file_set_mime_type (file, GP_MIME_JPEG);
 3693         gp_file_set_name (file, "sony_preview.jpg");
 3694         gp_file_set_mtime (file, time(NULL));
 3695 
 3696         SET_CONTEXT_P(params, NULL);
 3697         return GP_OK;
 3698     }
 3699     case PTP_VENDOR_PANASONIC: {
 3700         unsigned char   *ximage = NULL;
 3701         int     tries = 25;
 3702 
 3703         if(!params->inliveview) {
 3704             C_PTP_REP(ptp_panasonic_liveview(params, 1));
 3705             params->inliveview = 1;
 3706             usleep(100000);
 3707         }
 3708 
 3709         for (;;) {
 3710             tries--;
 3711             if(tries <= 0)
 3712                 return translate_ptp_result (ret);
 3713             ret = ptp_panasonic_liveview_image (params, &ximage, &size);
 3714             if(ret == PTP_RC_DeviceBusy) {
 3715                 usleep(40000);
 3716                 continue;
 3717             } else {
 3718                 break;
 3719             }
 3720         }
 3721         /* look for the JPEG SOI marker (0xFFD8) in data */
 3722         jpgStartPtr = (unsigned char*)memchr(ximage, 0xff, size);
 3723         while(jpgStartPtr && ((jpgStartPtr+1) < (ximage + size))) {
 3724             if(*(jpgStartPtr + 1) == 0xd8) { /* SOI found */
 3725                 break;
 3726             } else { /* go on looking (starting at next byte) */
 3727                 jpgStartPtr++;
 3728                 jpgStartPtr = (unsigned char*)memchr(jpgStartPtr, 0xff, ximage + size - jpgStartPtr);
 3729             }
 3730         }
 3731         if(!jpgStartPtr) { /* no SOI -> no JPEG */
 3732             gp_context_error (context, _("Sorry, your Panasonic camera does not seem to return a JPEG image in LiveView mode"));
 3733             return GP_ERROR;
 3734         }
 3735         /* if SOI found, start looking for EOI marker (0xFFD9) one byte after SOI
 3736            (just to be sure we will not go beyond the end of the data array) */
 3737         jpgEndPtr = (unsigned char*)memchr(jpgStartPtr+1, 0xff, ximage+size-jpgStartPtr-1);
 3738         while(jpgEndPtr && ((jpgEndPtr+1) < (ximage + size))) {
 3739             if(*(jpgEndPtr + 1) == 0xd9) { /* EOI found */
 3740                 jpgEndPtr += 2;
 3741                 break;
 3742             } else { /* go on looking (starting at next byte) */
 3743                 jpgEndPtr++;
 3744                 jpgEndPtr = (unsigned char*)memchr(jpgEndPtr, 0xff, ximage + size - jpgEndPtr);
 3745             }
 3746         }
 3747         if(!jpgEndPtr) { /* no EOI -> no JPEG */
 3748             gp_context_error (context, _("Sorry, your Panasonic camera does not seem to return a JPEG image in LiveView mode"));
 3749             return GP_ERROR;
 3750         }
 3751         gp_file_append (file, (char*)jpgStartPtr, jpgEndPtr-jpgStartPtr);
 3752         free (ximage); /* FIXME: perhaps handle the 128 byte header data too. */
 3753 
 3754         gp_file_set_mime_type (file, GP_MIME_JPEG);
 3755         gp_file_set_name (file, "preview.jpg");
 3756         gp_file_set_mtime (file, time(NULL));
 3757 
 3758         SET_CONTEXT_P(params, NULL);
 3759         return GP_OK;
 3760     }
 3761     case PTP_VENDOR_GP_OLYMPUS_OMD: {
 3762         unsigned char       *ximage = NULL;
 3763         PTPPropertyValue    value;
 3764         int         tries = 25;
 3765 
 3766         ret = ptp_getdevicepropvalue (params, PTP_DPC_OLYMPUS_LiveViewModeOM, &value, PTP_DTC_UINT32);
 3767         if (ret != PTP_RC_OK)
 3768             value.u32 = 0;
 3769 
 3770         if (value.u32 != 67109632) {    /* 0x04000300 */
 3771             value.u32 = 67109632;
 3772             LOG_ON_PTP_E (ptp_setdevicepropvalue (params, PTP_DPC_OLYMPUS_LiveViewModeOM, &value, PTP_DTC_UINT32));
 3773 
 3774             params->inliveview = 1;
 3775         }
 3776 
 3777         for(;;) {
 3778             tries--;
 3779             if(tries <= 0) {
 3780                 return ret;
 3781             }
 3782             ret = ptp_olympus_liveview_image (params, &ximage, &size);
 3783             if(ret == PTP_RC_DeviceBusy || size < 1024) {
 3784                 usleep(40000);
 3785                 continue;
 3786             } else {
 3787                 break;
 3788             }
 3789         }
 3790 
 3791         gp_file_append (file, (char*)ximage, size);
 3792         free (ximage);
 3793 
 3794         gp_file_set_mime_type (file, GP_MIME_JPEG);
 3795         gp_file_set_name (file, "preview.jpg");
 3796         gp_file_set_mtime (file, time(NULL));
 3797 
 3798         SET_CONTEXT_P(params, NULL);
 3799         return GP_OK;
 3800     }
 3801     default:
 3802         break;
 3803     }
 3804     /* Check if we can do PTP 1.1 stream method */
 3805     if (    ptp_operation_issupported(params,PTP_OC_GetStreamInfo) &&
 3806         ptp_property_issupported(params, PTP_DPC_SupportedStreams)
 3807     )  {
 3808         PTPPropertyValue propval;
 3809 
 3810         C_PTP (ptp_getdevicepropvalue (params, PTP_DPC_SupportedStreams, &propval, PTP_DTC_UINT32));
 3811         if (propval.u32 & 1) /* camera does Video streams */
 3812             return camera_capture_stream_preview (camera, file, context);
 3813         /* fallthrough */
 3814     }
 3815     return GP_ERROR_NOT_SUPPORTED;
 3816 }
 3817 
 3818 static int
 3819 get_folder_from_handle (Camera *camera, uint32_t storage, uint32_t handle, char *folder) {
 3820     PTPObject   *ob;
 3821     PTPParams   *params = &camera->pl->params;
 3822 
 3823     GP_LOG_D ("(%x,%x,%s)", storage, handle, folder);
 3824     if (handle == PTP_HANDLER_ROOT)
 3825         return GP_OK;
 3826 
 3827     C_PTP (ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED, &ob));
 3828     CR (get_folder_from_handle (camera, storage, ob->oi.ParentObject, folder));
 3829     /* now ob could be invalid, since we might have reallocated params->objects */
 3830     ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED, &ob);
 3831     strcat (folder, ob->oi.Filename);
 3832     strcat (folder, "/");
 3833     return (GP_OK);
 3834 }
 3835 
 3836 static int
 3837 add_objectid_and_upload (Camera *camera, CameraFilePath *path, GPContext *context,
 3838     uint32_t newobject, PTPObjectInfo *oi) {
 3839     int         ret;
 3840     PTPParams       *params = &camera->pl->params;
 3841     CameraFile      *file = NULL;
 3842     unsigned char       *ximage = NULL;
 3843     CameraFileInfo      info;
 3844 
 3845     ret = gp_file_new(&file);
 3846     if (ret!=GP_OK) return ret;
 3847     gp_file_set_mtime (file, time(NULL));
 3848     set_mimetype (file, params->deviceinfo.VendorExtensionID, oi->ObjectFormat);
 3849     C_PTP_REP (ptp_getobject(params, newobject, &ximage));
 3850 
 3851     GP_LOG_D ("setting size");
 3852     ret = gp_file_set_data_and_size(file, (char*)ximage, oi->ObjectCompressedSize);
 3853     if (ret != GP_OK) {
 3854         gp_file_free (file);
 3855         return ret;
 3856     }
 3857     GP_LOG_D ("append to fs");
 3858     ret = gp_filesystem_append(camera->fs, path->folder, path->name, context);
 3859         if (ret != GP_OK) {
 3860         gp_file_free (file);
 3861         return ret;
 3862     }
 3863     GP_LOG_D ("adding filedata to fs");
 3864     ret = gp_filesystem_set_file_noop(camera->fs, path->folder, path->name, GP_FILE_TYPE_NORMAL, file, context);
 3865         if (ret != GP_OK) {
 3866         gp_file_free (file);
 3867         return ret;
 3868     }
 3869 
 3870     /* We have now handed over the file, disclaim responsibility by unref. */
 3871     gp_file_unref (file);
 3872 
 3873     /* we also get the fs info for free, so just set it */
 3874     info.file.fields = GP_FILE_INFO_TYPE |
 3875             GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT |
 3876             GP_FILE_INFO_SIZE | GP_FILE_INFO_MTIME;
 3877     strcpy_mime (info.file.type, params->deviceinfo.VendorExtensionID, oi->ObjectFormat);
 3878     info.file.width     = oi->ImagePixWidth;
 3879     info.file.height    = oi->ImagePixHeight;
 3880     info.file.size      = oi->ObjectCompressedSize;
 3881     info.file.mtime     = time(NULL);
 3882 
 3883     info.preview.fields = GP_FILE_INFO_TYPE |
 3884             GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT |
 3885             GP_FILE_INFO_SIZE;
 3886     strcpy_mime (info.preview.type, params->deviceinfo.VendorExtensionID, oi->ThumbFormat);
 3887     info.preview.width  = oi->ThumbPixWidth;
 3888     info.preview.height = oi->ThumbPixHeight;
 3889     info.preview.size   = oi->ThumbCompressedSize;
 3890     GP_LOG_D ("setting fileinfo in fs");
 3891     return gp_filesystem_set_info_noop(camera->fs, path->folder, path->name, info, context);
 3892 }
 3893 
 3894 /**
 3895  * camera_nikon_capture:
 3896  * params:      Camera*         - camera object
 3897  *              CameraCaptureType type  - type of object to capture
 3898  *              CameraFilePath *path    - filled out with filename and folder on return
 3899  *              uint32_t af             - use autofocus or not.
 3900  *              uint32_t sdram          - capture to sdram or not
 3901  *              GPContext* context      - gphoto context for this operation
 3902  *
 3903  * This function captures an image using special Nikon capture to SDRAM.
 3904  * The object(s) do(es) not appear in the "objecthandles" array returned by GetObjectHandles,
 3905  * so we need to download them here immediately.
 3906  *
 3907  * Return values: A gphoto return code.
 3908  * Upon success CameraFilePath *path contains the folder and filename of the captured
 3909  * image.
 3910  */
 3911 static int
 3912 camera_nikon_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path,
 3913         uint32_t af, int sdram, GPContext *context)
 3914 {
 3915     PTPObjectInfo       oi;
 3916     PTPParams       *params = &camera->pl->params;
 3917     PTPDevicePropDesc   propdesc;
 3918     PTPPropertyValue    propval;
 3919     int         i, ret, burstnumber = 1, done, tries;
 3920     uint32_t        newobject;
 3921     int         back_off_wait = 0;
 3922     struct timeval          capture_start;
 3923     int         loops;
 3924 
 3925 
 3926     if (type != GP_CAPTURE_IMAGE)
 3927         return GP_ERROR_NOT_SUPPORTED;
 3928 
 3929     if (params->deviceinfo.VendorExtensionID!=PTP_VENDOR_NIKON)
 3930         return GP_ERROR_NOT_SUPPORTED;
 3931 
 3932     /* Nilon V and J seem to like that */
 3933     if (!params->controlmode && ptp_operation_issupported(params,PTP_OC_NIKON_ChangeCameraMode)) {
 3934         ret = ptp_nikon_changecameramode (params, 1);
 3935         /* FIXME: PTP_RC_NIKON_ChangeCameraModeFailed does not seem to be problematic */
 3936         if (ret != PTP_RC_NIKON_ChangeCameraModeFailed)
 3937             C_PTP_REP (ret);
 3938         params->controlmode = 1;
 3939     }
 3940 
 3941     if (    !ptp_operation_issupported(params,PTP_OC_NIKON_InitiateCaptureRecInSdram) &&
 3942         !ptp_operation_issupported(params,PTP_OC_NIKON_AfCaptureSDRAM) &&
 3943         !ptp_operation_issupported(params,PTP_OC_NIKON_InitiateCaptureRecInMedia)
 3944     ) {
 3945         gp_context_error(context,
 3946