"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/camlibs/ptp2/ptp-pack.c" (21 Feb 2021, 104836 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 "ptp-pack.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 /* ptp-pack.c
    2  *
    3  * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
    4  * Copyright (C) 2003-2019 Marcus Meissner <marcus@jet.franken.de>
    5  * Copyright (C) 2006-2008 Linus Walleij <triad@df.lth.se>
    6  * Copyright (C) 2007 Tero Saarni <tero.saarni@gmail.com>
    7  * Copyright (C) 2009 Axel Waggershauser <awagger@web.de>
    8  *
    9  * This library is free software; you can redistribute it and/or
   10  * modify it under the terms of the GNU Lesser General Public
   11  * License as published by the Free Software Foundation; either
   12  * version 2 of the License, or (at your option) any later version.
   13  *
   14  * This library is distributed in the hope that it will be useful,
   15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   17  * Lesser General Public License for more details.
   18  *
   19  * You should have received a copy of the GNU Lesser General Public
   20  * License along with this library; if not, write to the
   21  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   22  * Boston, MA  02110-1301  USA
   23  */
   24 
   25 /* currently this file is included into ptp.c */
   26 
   27 #ifdef HAVE_LIMITS_H
   28 #include <limits.h>
   29 #endif
   30 #ifndef UINT_MAX
   31 # define UINT_MAX 0xFFFFFFFF
   32 #endif
   33 #if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
   34 #include <iconv.h>
   35 #endif
   36 
   37 static inline uint16_t
   38 htod16p (PTPParams *params, uint16_t var)
   39 {
   40     return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
   41 }
   42 
   43 static inline uint32_t
   44 htod32p (PTPParams *params, uint32_t var)
   45 {
   46     return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
   47 }
   48 
   49 static inline void
   50 htod16ap (PTPParams *params, unsigned char *a, uint16_t val)
   51 {
   52     if (params->byteorder==PTP_DL_LE)
   53         htole16a(a,val);
   54     else
   55         htobe16a(a,val);
   56 }
   57 
   58 static inline void
   59 htod32ap (PTPParams *params, unsigned char *a, uint32_t val)
   60 {
   61     if (params->byteorder==PTP_DL_LE)
   62         htole32a(a,val);
   63     else
   64         htobe32a(a,val);
   65 }
   66 
   67 static inline void
   68 htod64ap (PTPParams *params, unsigned char *a, uint64_t val)
   69 {
   70     if (params->byteorder==PTP_DL_LE)
   71         htole64a(a,val);
   72     else
   73         htobe64a(a,val);
   74 }
   75 
   76 static inline uint16_t
   77 dtoh16p (PTPParams *params, uint16_t var)
   78 {
   79     return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
   80 }
   81 
   82 static inline uint32_t
   83 dtoh32p (PTPParams *params, uint32_t var)
   84 {
   85     return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
   86 }
   87 
   88 static inline uint64_t
   89 dtoh64p (PTPParams *params, uint64_t var)
   90 {
   91     return ((params->byteorder==PTP_DL_LE)?le64toh(var):be64toh(var));
   92 }
   93 
   94 static inline uint16_t
   95 dtoh16ap (PTPParams *params, const unsigned char *a)
   96 {
   97     return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
   98 }
   99 
  100 static inline uint32_t
  101 dtoh32ap (PTPParams *params, const unsigned char *a)
  102 {
  103     return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
  104 }
  105 
  106 static inline uint64_t
  107 dtoh64ap (PTPParams *params, const unsigned char *a)
  108 {
  109     return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a));
  110 }
  111 
  112 #define htod8a(a,x) *(uint8_t*)(a) = x
  113 #define htod16a(a,x)    htod16ap(params,a,x)
  114 #define htod32a(a,x)    htod32ap(params,a,x)
  115 #define htod64a(a,x)    htod64ap(params,a,x)
  116 #define htod16(x)   htod16p(params,x)
  117 #define htod32(x)   htod32p(params,x)
  118 #define htod64(x)   htod64p(params,x)
  119 
  120 #define dtoh8a(x)   (*(uint8_t*)(x))
  121 #define dtoh16a(a)  dtoh16ap(params,a)
  122 #define dtoh32a(a)  dtoh32ap(params,a)
  123 #define dtoh64a(a)  dtoh64ap(params,a)
  124 #define dtoh16(x)   dtoh16p(params,x)
  125 #define dtoh32(x)   dtoh32p(params,x)
  126 #define dtoh64(x)   dtoh64p(params,x)
  127 
  128 
  129 /*
  130  * PTP strings ... if the size field is:
  131  * size 0  : "empty string" ... we interpret that as string with just \0 terminator, return 1
  132  *  (the whole PTP standard is not that clear, it occasionaly refers to strings as optional in such cases, but no clear guidance).
  133  * size > 0: all other strings have a terminating \0, included in the length (not sure how conforming everyone is here)
  134  *
  135  * len - in ptp string characters currently
  136  */
  137 static inline int
  138 ptp_unpack_string(PTPParams *params, unsigned char* data, uint32_t offset, uint32_t total, uint8_t *len, char **retstr)
  139 {
  140     uint8_t length;
  141     uint16_t string[PTP_MAXSTRLEN+1];
  142     /* allow for UTF-8: max of 3 bytes per UCS-2 char, plus final null */
  143     char loclstr[PTP_MAXSTRLEN*3+1];
  144     size_t nconv, srclen, destlen;
  145     char *src, *dest;
  146 
  147     *len = 0;
  148     *retstr = NULL;
  149 
  150     if (offset + 1 > total)
  151         return 0;
  152 
  153     length = dtoh8a(&data[offset]); /* PTP_MAXSTRLEN == 255, 8 bit len */
  154     if (length == 0) {      /* nothing to do? */
  155         *len = 0;
  156         *retstr = strdup("");   /* return an empty string, not NULL */
  157         return 1;
  158     }
  159 
  160     if (offset + 1 + length*sizeof(string[0]) > total)
  161         return 0;
  162 
  163     *len = length;
  164 
  165     /* copy to string[] to ensure correct alignment for iconv(3) */
  166     memcpy(string, &data[offset+1], length * sizeof(string[0]));
  167     string[length] = 0x0000U;   /* be paranoid!  add a terminator. */
  168     loclstr[0] = '\0';
  169 
  170     /* convert from camera UCS-2 to our locale */
  171     src = (char *)string;
  172     srclen = length * sizeof(string[0]);
  173     dest = loclstr;
  174     destlen = sizeof(loclstr)-1;
  175     nconv = (size_t)-1;
  176 #if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
  177     if (params->cd_ucs2_to_locale != (iconv_t)-1)
  178         nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen, &dest, &destlen);
  179 #endif
  180     if (nconv == (size_t) -1) { /* do it the hard way */
  181         int i;
  182         /* try the old way, in case iconv is broken */
  183         for (i=0;i<length;i++) {
  184             if (dtoh16a(&data[offset+1+2*i])>127)
  185                 loclstr[i] = '?';
  186             else
  187                 loclstr[i] = dtoh16a(&data[offset+1+2*i]);
  188         }
  189         dest = loclstr+length;
  190     }
  191     *dest = '\0';
  192     loclstr[sizeof(loclstr)-1] = '\0';   /* be safe? */
  193     *retstr = strdup(loclstr);
  194     return 1;
  195 }
  196 
  197 static inline int
  198 ucs2strlen(uint16_t const * const unicstr)
  199 {
  200     int length = 0;
  201 
  202     /* Unicode strings are terminated with 2 * 0x00 */
  203     for(length = 0; unicstr[length] != 0x0000U; length ++);
  204     return length;
  205 }
  206 
  207 
  208 static inline void
  209 ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
  210 {
  211     int packedlen = 0;
  212     uint16_t ucs2str[PTP_MAXSTRLEN+1];
  213     char *ucs2strp = (char *) ucs2str;
  214     size_t convlen = strlen(string);
  215 
  216     /* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
  217     memset(ucs2strp, 0, sizeof(ucs2str));  /* XXX: necessary? */
  218 #if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
  219     if (params->cd_locale_to_ucs2 != (iconv_t)-1) {
  220         size_t nconv;
  221         size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
  222         char *stringp = string;
  223 
  224         nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
  225             &ucs2strp, &convmax);
  226         if (nconv == (size_t) -1)
  227             ucs2str[0] = 0x0000U;
  228     } else
  229 #endif
  230     {
  231         unsigned int i;
  232 
  233         for (i=0;i<convlen;i++) {
  234             ucs2str[i] = string[i];
  235         }
  236         ucs2str[convlen] = 0;
  237     }
  238     /*
  239      * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
  240      *      why do we need ucs2strlen()?
  241      */
  242     packedlen = ucs2strlen(ucs2str);
  243     if (packedlen > PTP_MAXSTRLEN-1) {
  244         *len=0;
  245         return;
  246     }
  247 
  248     /* number of characters including terminating 0 (PTP standard confirmed) */
  249     htod8a(&data[offset],packedlen+1);
  250     memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
  251     htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
  252 
  253     /* The returned length is in number of characters */
  254     *len = (uint8_t) packedlen+1;
  255 }
  256 
  257 static inline unsigned char *
  258 ptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
  259 {
  260     uint8_t packed[PTP_MAXSTRLEN*2+3], len;
  261     size_t plen;
  262     unsigned char *retcopy = NULL;
  263 
  264     if (string == NULL)
  265       ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
  266     else
  267       ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
  268 
  269     /* returned length is in characters, then one byte for string length */
  270     plen = len*2 + 1;
  271 
  272     retcopy = malloc(plen);
  273     if (!retcopy) {
  274         *packed_size = 0;
  275         return NULL;
  276     }
  277     memcpy(retcopy, packed, plen);
  278     *packed_size = plen;
  279     return (retcopy);
  280 }
  281 
  282 static inline uint32_t
  283 ptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint32_t **array)
  284 {
  285     uint32_t n, i=0;
  286 
  287     if (!data)
  288         return 0;
  289 
  290     if (offset >= datalen)
  291         return 0;
  292 
  293     if (offset + sizeof(uint32_t) > datalen)
  294         return 0;
  295 
  296     *array = NULL;
  297     n=dtoh32a(&data[offset]);
  298     if (n >= UINT_MAX/sizeof(uint32_t))
  299         return 0;
  300     if (!n)
  301         return 0;
  302 
  303     if (offset + sizeof(uint32_t)*(n+1) > datalen) {
  304         ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)*(n+1) , datalen);
  305         return 0;
  306     }
  307 
  308     *array = calloc (n,sizeof(uint32_t));
  309     if (!*array)
  310         return 0;
  311     for (i=0;i<n;i++)
  312         (*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
  313     return n;
  314 }
  315 
  316 static inline uint32_t
  317 ptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
  318 {
  319     uint32_t i=0;
  320 
  321     *data = calloc ((arraylen+1),sizeof(uint32_t));
  322     if (!*data)
  323         return 0;
  324     htod32a(&(*data)[0],arraylen);
  325     for (i=0;i<arraylen;i++)
  326         htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
  327     return (arraylen+1)*sizeof(uint32_t);
  328 }
  329 
  330 static inline uint32_t
  331 ptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint16_t **array)
  332 {
  333     uint32_t n, i=0;
  334 
  335     if (!data)
  336         return 0;
  337     *array = NULL;
  338 
  339     if (datalen - offset < sizeof(uint32_t))
  340         return 0;
  341     n=dtoh32a(&data[offset]);
  342 
  343     if (n >= (UINT_MAX - offset - sizeof(uint32_t))/sizeof(uint16_t))
  344         return 0;
  345     if (!n)
  346         return 0;
  347     if (offset + sizeof(uint32_t) > datalen)
  348         return 0;
  349     if (offset + sizeof(uint32_t)+sizeof(uint16_t)*n > datalen) {
  350         ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)+n*sizeof(uint16_t) , datalen);
  351         return 0;
  352     }
  353     *array = calloc (n,sizeof(uint16_t));
  354     if (!*array)
  355         return 0;
  356     for (i=0;i<n;i++)
  357         (*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
  358     return n;
  359 }
  360 
  361 /* DeviceInfo pack/unpack */
  362 
  363 #define PTP_di_StandardVersion       0
  364 #define PTP_di_VendorExtensionID     2
  365 #define PTP_di_VendorExtensionVersion    6
  366 #define PTP_di_VendorExtensionDesc   8
  367 #define PTP_di_FunctionalMode        8
  368 #define PTP_di_OperationsSupported  10
  369 
  370 static inline int
  371 ptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
  372 {
  373     uint8_t len;
  374     unsigned int totallen;
  375 
  376     if (!data) return 0;
  377     if (datalen < 12) return 0;
  378     memset (di, 0, sizeof(*di));
  379     di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
  380     di->VendorExtensionID =
  381         dtoh32a(&data[PTP_di_VendorExtensionID]);
  382     di->VendorExtensionVersion =
  383         dtoh16a(&data[PTP_di_VendorExtensionVersion]);
  384     if (!ptp_unpack_string(params, data,
  385         PTP_di_VendorExtensionDesc,
  386         datalen,
  387         &len,
  388         &di->VendorExtensionDesc)
  389     )
  390         return 0;
  391     totallen=len*2+1;
  392     if (datalen <= totallen + PTP_di_FunctionalMode + sizeof(uint16_t)) {
  393         ptp_debug (params, "datalen %d <= totallen + PTP_di_FunctionalMode + sizeof(uint16_t) %d", datalen, totallen + PTP_di_FunctionalMode + sizeof(uint16_t));
  394         return 0;
  395     }
  396     di->FunctionalMode =
  397         dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
  398     di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
  399         PTP_di_OperationsSupported+totallen,
  400         datalen,
  401         &di->OperationsSupported);
  402     totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
  403     if (datalen <= totallen+PTP_di_OperationsSupported) {
  404         ptp_debug (params, "datalen %d <= totallen+PTP_di_OperationsSupported %d 1", datalen, totallen+PTP_di_OperationsSupported);
  405         return 0;
  406     }
  407     di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
  408         PTP_di_OperationsSupported+totallen,
  409         datalen,
  410         &di->EventsSupported);
  411     totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
  412     if (datalen <= totallen+PTP_di_OperationsSupported) {
  413         ptp_debug (params, "datalen %d <= totallen+PTP_di_OperationsSupported %d 2", datalen, totallen+PTP_di_OperationsSupported);
  414         return 0;
  415     }
  416     di->DevicePropertiesSupported_len =
  417         ptp_unpack_uint16_t_array(params, data,
  418         PTP_di_OperationsSupported+totallen,
  419         datalen,
  420         &di->DevicePropertiesSupported);
  421     totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
  422     if (datalen <= totallen+PTP_di_OperationsSupported) {
  423         ptp_debug (params, "datalen %d <= totallen+PTP_di_OperationsSupported %d 3", datalen, totallen+PTP_di_OperationsSupported);
  424         return 0;
  425     }
  426     di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
  427         PTP_di_OperationsSupported+totallen,
  428         datalen,
  429         &di->CaptureFormats);
  430     totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
  431     if (datalen <= totallen+PTP_di_OperationsSupported) {
  432         ptp_debug (params, "datalen %d <= totallen+PTP_di_OperationsSupported %d 4", datalen, totallen+PTP_di_OperationsSupported);
  433         return 0;
  434     }
  435     di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
  436         PTP_di_OperationsSupported+totallen,
  437         datalen,
  438         &di->ImageFormats);
  439     totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
  440     if (datalen <= totallen+PTP_di_OperationsSupported) {
  441         ptp_debug (params, "datalen %d <= totallen+PTP_di_OperationsSupported %d 5", datalen, totallen+PTP_di_OperationsSupported);
  442         return 0;
  443     }
  444     if (!ptp_unpack_string(params, data,
  445         PTP_di_OperationsSupported+totallen,
  446         datalen,
  447         &len,
  448         &di->Manufacturer)
  449     )
  450         return 0;
  451     totallen+=len*2+1;
  452     /* be more relaxed ... as these are optional its ok if they are not here */
  453     if (datalen <= totallen+PTP_di_OperationsSupported) {
  454         ptp_debug (params, "datalen %d <= totallen+PTP_di_OperationsSupported %d 6", datalen, totallen+PTP_di_OperationsSupported);
  455         return 1;
  456     }
  457     if (!ptp_unpack_string(params, data,
  458         PTP_di_OperationsSupported+totallen,
  459         datalen,
  460         &len,
  461         &di->Model)
  462     )
  463         return 1;
  464     totallen+=len*2+1;
  465     /* be more relaxed ... as these are optional its ok if they are not here */
  466     if (datalen <= totallen+PTP_di_OperationsSupported) {
  467         ptp_debug (params, "datalen %d <= totallen+PTP_di_OperationsSupported %d 7", datalen, totallen+PTP_di_OperationsSupported);
  468         return 1;
  469     }
  470     if (!ptp_unpack_string(params, data,
  471         PTP_di_OperationsSupported+totallen,
  472         datalen,
  473         &len,
  474         &di->DeviceVersion)
  475     )
  476         return 1;
  477     totallen+=len*2+1;
  478     /* be more relaxed ... as these are optional its ok if they are not here */
  479     if (datalen <= totallen+PTP_di_OperationsSupported) {
  480         ptp_debug (params, "datalen %d <= totallen+PTP_di_OperationsSupported %d 8", datalen, totallen+PTP_di_OperationsSupported);
  481         return 1;
  482     }
  483     if (!ptp_unpack_string(params, data,
  484         PTP_di_OperationsSupported+totallen,
  485         datalen,
  486         &len,
  487         &di->SerialNumber)
  488     )
  489         return 1;
  490     return 1;
  491 }
  492 
  493 inline static void
  494 ptp_free_DI (PTPDeviceInfo *di) {
  495     free (di->SerialNumber);
  496     free (di->DeviceVersion);
  497     free (di->Model);
  498     free (di->Manufacturer);
  499     free (di->ImageFormats);
  500     free (di->CaptureFormats);
  501     free (di->VendorExtensionDesc);
  502     free (di->OperationsSupported);
  503     free (di->EventsSupported);
  504     free (di->DevicePropertiesSupported);
  505     memset(di, 0, sizeof(*di));
  506 }
  507 
  508 /* EOS Device Info unpack */
  509 static inline int
  510 ptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
  511 {
  512     unsigned int totallen = 4;
  513 
  514     memset (di,0, sizeof(*di));
  515     if (datalen < 8) return 0;
  516 
  517     /* uint32_t struct len - ignore */
  518     di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
  519         totallen, datalen, &di->EventsSupported);
  520     if (!di->EventsSupported) return 0;
  521     totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
  522     if (totallen >= datalen) return 0;
  523 
  524     di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
  525         totallen, datalen, &di->DevicePropertiesSupported);
  526     if (!di->DevicePropertiesSupported) return 0;
  527     totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
  528     if (totallen >= datalen) return 0;
  529 
  530     di->unk_len = ptp_unpack_uint32_t_array(params, data,
  531         totallen, datalen, &di->unk);
  532     if (!di->unk) return 0;
  533     totallen += di->unk_len*sizeof(uint32_t)+4;
  534     return 1;
  535 }
  536 
  537 static inline void
  538 ptp_free_EOS_DI (PTPCanonEOSDeviceInfo *di)
  539 {
  540     free (di->EventsSupported);
  541     free (di->DevicePropertiesSupported);
  542     free (di->unk);
  543 }
  544 
  545 /* ObjectHandles array pack/unpack */
  546 
  547 #define PTP_oh               0
  548 
  549 static inline void
  550 ptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
  551 {
  552     if (len) {
  553         oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, len, &oh->Handler);
  554     } else {
  555         oh->n = 0;
  556         oh->Handler = NULL;
  557     }
  558 }
  559 
  560 /* StoreIDs array pack/unpack */
  561 
  562 #define PTP_sids             0
  563 
  564 static inline void
  565 ptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
  566 {
  567     sids->n = 0;
  568     sids->Storage = NULL;
  569 
  570     if (!data || !len)
  571         return;
  572 
  573     sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids, len, &sids->Storage);
  574 }
  575 
  576 /* StorageInfo pack/unpack */
  577 
  578 #define PTP_si_StorageType       0
  579 #define PTP_si_FilesystemType        2
  580 #define PTP_si_AccessCapability      4
  581 #define PTP_si_MaxCapability         6
  582 #define PTP_si_FreeSpaceInBytes     14
  583 #define PTP_si_FreeSpaceInImages    22
  584 #define PTP_si_StorageDescription   26
  585 
  586 static inline int
  587 ptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
  588 {
  589     uint8_t storagedescriptionlen;
  590 
  591     if (len < 26) return 0;
  592     si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
  593     si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
  594     si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
  595     si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
  596     si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
  597     si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
  598 
  599     /* FIXME: check more lengths here */
  600     if (!ptp_unpack_string(params, data,
  601         PTP_si_StorageDescription,
  602         len,
  603         &storagedescriptionlen,
  604         &si->StorageDescription)
  605     )
  606         return 0;
  607 
  608     if (!ptp_unpack_string(params, data,
  609         PTP_si_StorageDescription+storagedescriptionlen*2+1,
  610         len,
  611         &storagedescriptionlen,
  612         &si->VolumeLabel)) {
  613         ptp_debug(params, "could not unpack storage description");
  614         return 0;
  615     }
  616     return 1;
  617 }
  618 
  619 /* ObjectInfo pack/unpack */
  620 
  621 #define PTP_oi_StorageID         0
  622 #define PTP_oi_ObjectFormat      4
  623 #define PTP_oi_ProtectionStatus      6
  624 #define PTP_oi_ObjectCompressedSize  8
  625 #define PTP_oi_ThumbFormat      12
  626 #define PTP_oi_ThumbCompressedSize  14
  627 #define PTP_oi_ThumbPixWidth        18
  628 #define PTP_oi_ThumbPixHeight       22
  629 #define PTP_oi_ImagePixWidth        26
  630 #define PTP_oi_ImagePixHeight       30
  631 #define PTP_oi_ImageBitDepth        34
  632 #define PTP_oi_ParentObject     38
  633 #define PTP_oi_AssociationType      42
  634 #define PTP_oi_AssociationDesc      44
  635 #define PTP_oi_SequenceNumber       48
  636 #define PTP_oi_filenamelen      52
  637 #define PTP_oi_Filename         53
  638 
  639 /* the max length assuming zero length dates. We have need 3 */
  640 /* bytes for these. */
  641 #define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
  642 
  643 static inline uint32_t
  644 ptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
  645 {
  646     unsigned char* oidata;
  647     uint8_t filenamelen;
  648     uint8_t capturedatelen=0;
  649     /* let's allocate some memory first; correct assuming zero length dates */
  650     oidata=malloc(PTP_oi_MaxLen + params->ocs64*4);
  651     *oidataptr=oidata;
  652     /* the caller should free it after use! */
  653 #if 0
  654     char *capture_date="20020101T010101"; /* XXX Fake date */
  655 #endif
  656     memset (oidata, 0, PTP_oi_MaxLen + params->ocs64*4);
  657     htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
  658     htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
  659     htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
  660     htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
  661     if (params->ocs64)
  662         oidata += 4;
  663     htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
  664     htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
  665     htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
  666     htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
  667     htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
  668     htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
  669     htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
  670     htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
  671     htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
  672     htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
  673     htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
  674 
  675     ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
  676 /*
  677     filenamelen=(uint8_t)strlen(oi->Filename);
  678     htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
  679     for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
  680         req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
  681     }
  682 */
  683     /*
  684      *XXX Fake date.
  685      * for example Kodak sets Capture date on the basis of EXIF data.
  686      * Spec says that this field is from perspective of Initiator.
  687      */
  688 #if 0   /* seems now we don't need any data packed in OI dataset... for now ;)*/
  689     capturedatelen=strlen(capture_date);
  690     htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
  691         capturedatelen+1);
  692     for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
  693         data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
  694     }
  695     htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
  696         capturedatelen+1);
  697     for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
  698         data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
  699           capture_date[i];
  700     }
  701 #endif
  702     /* XXX this function should return dataset length */
  703     return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3)+params->ocs64*4;
  704 }
  705 
  706 static time_t
  707 ptp_unpack_PTPTIME (const char *str) {
  708     char ptpdate[40];
  709     char tmp[5];
  710     size_t  ptpdatelen;
  711     struct tm tm;
  712 
  713     if (!str)
  714         return 0;
  715     ptpdatelen = strlen(str);
  716     if (ptpdatelen >= sizeof (ptpdate)) {
  717         /*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
  718         return 0;
  719     }
  720     if (ptpdatelen<15) {
  721         /*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
  722         return 0;
  723     }
  724     strncpy (ptpdate, str, sizeof(ptpdate));
  725     ptpdate[sizeof(ptpdate) - 1] = '\0';
  726 
  727     memset(&tm,0,sizeof(tm));
  728     strncpy (tmp, ptpdate, 4);
  729     tmp[4] = 0;
  730     tm.tm_year=atoi (tmp) - 1900;
  731     strncpy (tmp, ptpdate + 4, 2);
  732     tmp[2] = 0;
  733     tm.tm_mon = atoi (tmp) - 1;
  734     strncpy (tmp, ptpdate + 6, 2);
  735     tmp[2] = 0;
  736     tm.tm_mday = atoi (tmp);
  737     strncpy (tmp, ptpdate + 9, 2);
  738     tmp[2] = 0;
  739     tm.tm_hour = atoi (tmp);
  740     strncpy (tmp, ptpdate + 11, 2);
  741     tmp[2] = 0;
  742     tm.tm_min = atoi (tmp);
  743     strncpy (tmp, ptpdate + 13, 2);
  744     tmp[2] = 0;
  745     tm.tm_sec = atoi (tmp);
  746     tm.tm_isdst = -1;
  747     return mktime (&tm);
  748 }
  749 
  750 static inline void
  751 ptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
  752 {
  753     uint8_t filenamelen;
  754     uint8_t capturedatelen;
  755     char *capture_date;
  756 
  757     if (len < PTP_oi_SequenceNumber)
  758         return;
  759 
  760     oi->Filename = oi->Keywords = NULL;
  761 
  762     /* FIXME: also handle length with all the strings at the end */
  763     oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
  764     oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
  765     oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
  766     oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
  767 
  768     /* Stupid Samsung Galaxy developers emit a 64bit objectcompressedsize */
  769     if ((data[PTP_oi_filenamelen] == 0) && (data[PTP_oi_filenamelen+4] != 0)) {
  770         ptp_debug (params, "objectsize 64bit detected!");
  771         params->ocs64 = 1;
  772         data += 4;
  773         len -= 4;
  774     }
  775     oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
  776     oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
  777     oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
  778     oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
  779     oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
  780     oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
  781     oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
  782     oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
  783     oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
  784     oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
  785     oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
  786 
  787     ptp_unpack_string(params, data, PTP_oi_filenamelen, len, &filenamelen, &oi->Filename);
  788     ptp_unpack_string(params, data, PTP_oi_filenamelen+filenamelen*2+1, len, &capturedatelen, &capture_date);
  789     /* subset of ISO 8601, without '.s' tenths of second and
  790      * time zone
  791      */
  792     oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
  793     free(capture_date);
  794 
  795     /* now the modification date ... */
  796     ptp_unpack_string(params, data,
  797         PTP_oi_filenamelen+filenamelen*2
  798         +capturedatelen*2+2, len, &capturedatelen, &capture_date
  799     );
  800     oi->ModificationDate = ptp_unpack_PTPTIME(capture_date);
  801     free(capture_date);
  802 }
  803 
  804 /* Custom Type Value Assignement (without Length) macro frequently used below */
  805 #define CTVAL(target,func) {            \
  806     if (total - *offset < sizeof(target))   \
  807         return 0;           \
  808     target = func(&data[*offset]);      \
  809     *offset += sizeof(target);      \
  810 }
  811 
  812 #define RARR(val,member,func)   {           \
  813     unsigned int n,j;               \
  814     if (total - *offset < sizeof(uint32_t))     \
  815         return 0;               \
  816     n = dtoh32a (&data[*offset]);           \
  817     *offset += sizeof(uint32_t);            \
  818                             \
  819     if (n >= UINT_MAX/sizeof(val->a.v[0]))      \
  820         return 0;               \
  821     if (n > (total - (*offset))/sizeof(val->a.v[0]))\
  822         return 0;               \
  823     val->a.count = n;               \
  824     val->a.v = calloc(sizeof(val->a.v[0]),n);   \
  825     if (!val->a.v) return 0;            \
  826     for (j=0;j<n;j++)               \
  827         CTVAL(val->a.v[j].member, func);    \
  828 }
  829 
  830 static inline unsigned int
  831 ptp_unpack_DPV (
  832     PTPParams *params, unsigned char* data, unsigned int *offset, unsigned int total,
  833     PTPPropertyValue* value, uint16_t datatype
  834 ) {
  835     if (*offset >= total)   /* we are at the end or over the end of the buffer */
  836         return 0;
  837 
  838     switch (datatype) {
  839     case PTP_DTC_INT8:
  840         CTVAL(value->i8,dtoh8a);
  841         break;
  842     case PTP_DTC_UINT8:
  843         CTVAL(value->u8,dtoh8a);
  844         break;
  845     case PTP_DTC_INT16:
  846         CTVAL(value->i16,dtoh16a);
  847         break;
  848     case PTP_DTC_UINT16:
  849         CTVAL(value->u16,dtoh16a);
  850         break;
  851     case PTP_DTC_INT32:
  852         CTVAL(value->i32,dtoh32a);
  853         break;
  854     case PTP_DTC_UINT32:
  855         CTVAL(value->u32,dtoh32a);
  856         break;
  857     case PTP_DTC_INT64:
  858         CTVAL(value->i64,dtoh64a);
  859         break;
  860     case PTP_DTC_UINT64:
  861         CTVAL(value->u64,dtoh64a);
  862         break;
  863 
  864     case PTP_DTC_UINT128:
  865         *offset += 16;
  866         /*fprintf(stderr,"unhandled unpack of uint128n");*/
  867         break;
  868     case PTP_DTC_INT128:
  869         *offset += 16;
  870         /*fprintf(stderr,"unhandled unpack of int128n");*/
  871         break;
  872 
  873 
  874 
  875     case PTP_DTC_AINT8:
  876         RARR(value,i8,dtoh8a);
  877         break;
  878     case PTP_DTC_AUINT8:
  879         RARR(value,u8,dtoh8a);
  880         break;
  881     case PTP_DTC_AUINT16:
  882         RARR(value,u16,dtoh16a);
  883         break;
  884     case PTP_DTC_AINT16:
  885         RARR(value,i16,dtoh16a);
  886         break;
  887     case PTP_DTC_AUINT32:
  888         RARR(value,u32,dtoh32a);
  889         break;
  890     case PTP_DTC_AINT32:
  891         RARR(value,i32,dtoh32a);
  892         break;
  893     case PTP_DTC_AUINT64:
  894         RARR(value,u64,dtoh64a);
  895         break;
  896     case PTP_DTC_AINT64:
  897         RARR(value,i64,dtoh64a);
  898         break;
  899     /* XXX: other int types are unimplemented */
  900     /* XXX: other int arrays are unimplemented also */
  901     case PTP_DTC_STR: {
  902         uint8_t len;
  903         /* XXX: max size */
  904 
  905         if (*offset >= total+1)
  906             return 0;
  907 
  908         if (!ptp_unpack_string(params,data,*offset,total,&len,&value->str))
  909             return 0;
  910         *offset += len*2+1;
  911         break;
  912     }
  913     default:
  914         return 0;
  915     }
  916     return 1;
  917 }
  918 
  919 /* Device Property pack/unpack */
  920 #define PTP_dpd_DevicePropertyCode  0
  921 #define PTP_dpd_DataType        2
  922 #define PTP_dpd_GetSet          4
  923 #define PTP_dpd_FactoryDefaultValue 5
  924 
  925 static inline int
  926 ptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen, unsigned int *newoffset)
  927 {
  928     unsigned int offset = 0, ret;
  929 
  930     *newoffset = 0;
  931 
  932     memset (dpd, 0, sizeof(*dpd));
  933     if (dpdlen <= 5)
  934         return 0;
  935     dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
  936     dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
  937     dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
  938     dpd->FormFlag=PTP_DPFF_None;
  939 
  940     offset = PTP_dpd_FactoryDefaultValue;
  941     ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
  942     if (!ret) goto outofmemory;
  943     if ((dpd->DataType == PTP_DTC_STR) && (offset == dpdlen)) {
  944         *newoffset = offset;
  945         return 1;
  946     }
  947     ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
  948     if (!ret) goto outofmemory;
  949 
  950     /* if offset==0 then Data Type format is not supported by this
  951        code or the Data Type is a string (with two empty strings as
  952        values). In both cases Form Flag should be set to 0x00 and FORM is
  953        not present. */
  954 
  955     if (offset + sizeof(uint8_t) > dpdlen) {
  956         *newoffset = offset;
  957         return 1;
  958     }
  959 
  960     dpd->FormFlag=dtoh8a(&data[offset]);
  961     offset+=sizeof(uint8_t);
  962 
  963     switch (dpd->FormFlag) {
  964     case PTP_DPFF_Range:
  965         ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
  966         if (!ret) goto outofmemory;
  967         ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
  968         if (!ret) goto outofmemory;
  969         ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
  970         if (!ret) goto outofmemory;
  971         break;
  972     case PTP_DPFF_Enumeration: {
  973         int i;
  974 #define N   dpd->FORM.Enum.NumberOfValues
  975 
  976         if (offset + sizeof(uint16_t) > dpdlen) goto outofmemory;
  977 
  978         N = dtoh16a(&data[offset]);
  979         offset+=sizeof(uint16_t);
  980         dpd->FORM.Enum.SupportedValue = calloc(N,sizeof(dpd->FORM.Enum.SupportedValue[0]));
  981         if (!dpd->FORM.Enum.SupportedValue)
  982             goto outofmemory;
  983 
  984         for (i=0;i<N;i++) {
  985             ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
  986 
  987             /* Slightly different handling here. The HP PhotoSmart 120
  988              * specifies an enumeration with N in wrong endian
  989              * 00 01 instead of 01 00, so we count the enum just until the
  990              * the end of the packet.
  991              */
  992             if (!ret) {
  993                 if (!i)
  994                     goto outofmemory;
  995                 dpd->FORM.Enum.NumberOfValues = i;
  996                 break;
  997             }
  998         }
  999         }
 1000     }
 1001 #undef N
 1002     *newoffset = offset;
 1003     return 1;
 1004 outofmemory:
 1005     ptp_free_devicepropdesc(dpd);
 1006     return 0;
 1007 }
 1008 
 1009 /* Device Property pack/unpack */
 1010 #define PTP_dpd_Sony_DevicePropertyCode     0
 1011 #define PTP_dpd_Sony_DataType           2
 1012 #define PTP_dpd_Sony_ChangeMethod       4
 1013 #define PTP_dpd_Sony_GetSet         5
 1014 #define PTP_dpd_Sony_FactoryDefaultValue    6
 1015 
 1016 static inline int
 1017 ptp_unpack_Sony_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen, unsigned int *poffset)
 1018 {
 1019     unsigned int ret;
 1020     unsigned int changemethod, getset;
 1021 
 1022     memset (dpd, 0, sizeof(*dpd));
 1023     dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_Sony_DevicePropertyCode]);
 1024     dpd->DataType=dtoh16a(&data[PTP_dpd_Sony_DataType]);
 1025 
 1026     changemethod = dtoh8a(&data[PTP_dpd_Sony_ChangeMethod]);
 1027     getset = dtoh8a(&data[PTP_dpd_Sony_GetSet]);
 1028 
 1029     ptp_debug (params, "prop 0x%04x, datatype 0x%04x, changemethod %d getset %d", dpd->DevicePropertyCode, dpd->DataType, changemethod, getset);
 1030     switch (getset) {
 1031     case 0: /* read only */
 1032     case 2: /* camera side only */
 1033         dpd->GetSet=0;
 1034         break;
 1035     case 1: /* writeable */
 1036         dpd->GetSet=1;
 1037         break;
 1038     default: /* values over 128 ... likely action triggers */
 1039         dpd->GetSet=1;
 1040         break;
 1041     }
 1042     dpd->FormFlag=PTP_DPFF_None;
 1043 
 1044     *poffset = PTP_dpd_Sony_FactoryDefaultValue;
 1045     ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
 1046     if (!ret) goto outofmemory;
 1047     if ((dpd->DataType == PTP_DTC_STR) && (*poffset == dpdlen))
 1048         return 1;
 1049     ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->CurrentValue, dpd->DataType);
 1050     if (!ret) goto outofmemory;
 1051 
 1052     /* if offset==0 then Data Type format is not supported by this
 1053        code or the Data Type is a string (with two empty strings as
 1054        values). In both cases Form Flag should be set to 0x00 and FORM is
 1055        not present. */
 1056 
 1057     if (*poffset==PTP_dpd_Sony_FactoryDefaultValue)
 1058         return 1;
 1059 
 1060     dpd->FormFlag=dtoh8a(&data[*poffset]);
 1061     *poffset+=sizeof(uint8_t);
 1062 
 1063     switch (dpd->FormFlag) {
 1064     case PTP_DPFF_Range:
 1065         ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
 1066         if (!ret) goto outofmemory;
 1067         ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
 1068         if (!ret) goto outofmemory;
 1069         ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
 1070         if (!ret) goto outofmemory;
 1071         break;
 1072     case PTP_DPFF_Enumeration: {
 1073         int i;
 1074 #define N   dpd->FORM.Enum.NumberOfValues
 1075         N = dtoh16a(&data[*poffset]);
 1076         *poffset+=sizeof(uint16_t);
 1077         dpd->FORM.Enum.SupportedValue = calloc(N,sizeof(dpd->FORM.Enum.SupportedValue[0]));
 1078         if (!dpd->FORM.Enum.SupportedValue)
 1079             goto outofmemory;
 1080 
 1081         for (i=0;i<N;i++) {
 1082             ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
 1083 
 1084             /* Slightly different handling here. The HP PhotoSmart 120
 1085              * specifies an enumeration with N in wrong endian
 1086              * 00 01 instead of 01 00, so we count the enum just until the
 1087              * the end of the packet.
 1088              */
 1089             if (!ret) {
 1090                 if (!i)
 1091                     goto outofmemory;
 1092                 dpd->FORM.Enum.NumberOfValues = i;
 1093                 break;
 1094             }
 1095         }
 1096         }
 1097     }
 1098 #undef N
 1099     return 1;
 1100 outofmemory:
 1101     ptp_free_devicepropdesc(dpd);
 1102     return 0;
 1103 }
 1104 
 1105 static inline void
 1106 duplicate_PropertyValue (const PTPPropertyValue *src, PTPPropertyValue *dst, uint16_t type) {
 1107     if (type == PTP_DTC_STR) {
 1108         if (src->str)
 1109             dst->str = strdup(src->str);
 1110         else
 1111             dst->str = NULL;
 1112         return;
 1113     }
 1114 
 1115     if (type & PTP_DTC_ARRAY_MASK) {
 1116         unsigned int i;
 1117 
 1118         dst->a.count = src->a.count;
 1119         dst->a.v = calloc (sizeof(src->a.v[0]),src->a.count);
 1120         for (i=0;i<src->a.count;i++)
 1121             duplicate_PropertyValue (&src->a.v[i], &dst->a.v[i], type & ~PTP_DTC_ARRAY_MASK);
 1122         return;
 1123     }
 1124     switch (type & ~PTP_DTC_ARRAY_MASK) {
 1125     case PTP_DTC_INT8:  dst->i8 = src->i8; break;
 1126     case PTP_DTC_UINT8: dst->u8 = src->u8; break;
 1127     case PTP_DTC_INT16: dst->i16 = src->i16; break;
 1128     case PTP_DTC_UINT16:    dst->u16 = src->u16; break;
 1129     case PTP_DTC_INT32: dst->i32 = src->i32; break;
 1130     case PTP_DTC_UINT32:    dst->u32 = src->u32; break;
 1131     case PTP_DTC_UINT64:    dst->u64 = src->u64; break;
 1132     case PTP_DTC_INT64: dst->i64 = src->i64; break;
 1133 #if 0
 1134     case PTP_DTC_INT128:    dst->i128 = src->i128; break;
 1135     case PTP_DTC_UINT128:   dst->u128 = src->u128; break;
 1136 #endif
 1137     default:        break;
 1138     }
 1139     return;
 1140 }
 1141 
 1142 static inline void
 1143 duplicate_DevicePropDesc(const PTPDevicePropDesc *src, PTPDevicePropDesc *dst) {
 1144     int i;
 1145 
 1146     dst->DevicePropertyCode = src->DevicePropertyCode;
 1147     dst->DataType       = src->DataType;
 1148     dst->GetSet     = src->GetSet;
 1149 
 1150     duplicate_PropertyValue (&src->FactoryDefaultValue, &dst->FactoryDefaultValue, src->DataType);
 1151     duplicate_PropertyValue (&src->CurrentValue, &dst->CurrentValue, src->DataType);
 1152 
 1153     dst->FormFlag       = src->FormFlag;
 1154     switch (src->FormFlag) {
 1155     case PTP_DPFF_Range:
 1156         duplicate_PropertyValue (&src->FORM.Range.MinimumValue, &dst->FORM.Range.MinimumValue, src->DataType);
 1157         duplicate_PropertyValue (&src->FORM.Range.MaximumValue, &dst->FORM.Range.MaximumValue, src->DataType);
 1158         duplicate_PropertyValue (&src->FORM.Range.StepSize,     &dst->FORM.Range.StepSize,     src->DataType);
 1159         break;
 1160     case PTP_DPFF_Enumeration:
 1161         dst->FORM.Enum.NumberOfValues = src->FORM.Enum.NumberOfValues;
 1162         dst->FORM.Enum.SupportedValue = calloc (sizeof(dst->FORM.Enum.SupportedValue[0]),src->FORM.Enum.NumberOfValues);
 1163         for (i = 0; i<src->FORM.Enum.NumberOfValues ; i++)
 1164             duplicate_PropertyValue (&src->FORM.Enum.SupportedValue[i], &dst->FORM.Enum.SupportedValue[i], src->DataType);
 1165         break;
 1166     case PTP_DPFF_None:
 1167         break;
 1168     }
 1169 }
 1170 
 1171 #define PTP_opd_ObjectPropertyCode  0
 1172 #define PTP_opd_DataType        2
 1173 #define PTP_opd_GetSet          4
 1174 #define PTP_opd_FactoryDefaultValue 5
 1175 
 1176 static inline int
 1177 ptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
 1178 {
 1179     unsigned int offset=0, ret;
 1180     uint8_t len;
 1181 
 1182     memset (opd, 0, sizeof(*opd));
 1183 
 1184     if (opdlen < 5)
 1185         return 0;
 1186 
 1187     opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
 1188     opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
 1189     opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
 1190 
 1191     offset = PTP_opd_FactoryDefaultValue;
 1192     ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
 1193     if (!ret) goto outofmemory;
 1194 
 1195     if (offset + sizeof(uint32_t) > opdlen) goto outofmemory;
 1196     opd->GroupCode=dtoh32a(&data[offset]);
 1197     offset+=sizeof(uint32_t);
 1198 
 1199     if (offset + sizeof(uint8_t) > opdlen) goto outofmemory;
 1200     opd->FormFlag=dtoh8a(&data[offset]);
 1201     offset+=sizeof(uint8_t);
 1202 
 1203     switch (opd->FormFlag) {
 1204     case PTP_OPFF_Range:
 1205         ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
 1206         if (!ret) goto outofmemory;
 1207         ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
 1208         if (!ret) goto outofmemory;
 1209         ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
 1210         if (!ret) goto outofmemory;
 1211         break;
 1212     case PTP_OPFF_Enumeration: {
 1213         unsigned int i;
 1214 #define N   opd->FORM.Enum.NumberOfValues
 1215 
 1216         if (offset + sizeof(uint16_t) > opdlen) goto outofmemory;
 1217         N = dtoh16a(&data[offset]);
 1218         offset+=sizeof(uint16_t);
 1219 
 1220         opd->FORM.Enum.SupportedValue = calloc(N,sizeof(opd->FORM.Enum.SupportedValue[0]));
 1221         if (!opd->FORM.Enum.SupportedValue)
 1222             goto outofmemory;
 1223 
 1224         for (i=0;i<N;i++) {
 1225             ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
 1226 
 1227             /* Slightly different handling here. The HP PhotoSmart 120
 1228              * specifies an enumeration with N in wrong endian
 1229              * 00 01 instead of 01 00, so we count the enum just until the
 1230              * the end of the packet.
 1231              */
 1232             if (!ret) {
 1233                 if (!i)
 1234                     goto outofmemory;
 1235                 opd->FORM.Enum.NumberOfValues = i;
 1236                 break;
 1237             }
 1238         }
 1239 #undef N
 1240         }
 1241         break;
 1242     case PTP_OPFF_DateTime:
 1243         if (!ptp_unpack_string(params, data, offset, opdlen, &len, &opd->FORM.DateTime.String))
 1244             opd->FORM.DateTime.String = NULL;
 1245         offset += 2*len+1; /* offset not used afterwards anymore */
 1246         break;
 1247     case PTP_OPFF_RegularExpression:
 1248         if (!ptp_unpack_string(params, data, offset, opdlen, &len, &opd->FORM.RegularExpression.String))
 1249             opd->FORM.RegularExpression.String = NULL;
 1250         offset += 2*len+1; /* offset not used afterwards anymore */
 1251         break;
 1252     case PTP_OPFF_FixedLengthArray:
 1253         if (offset + sizeof(uint16_t) > opdlen) goto outofmemory;
 1254         opd->FORM.FixedLengthArray.NumberOfValues = dtoh16a(&data[offset]);
 1255         offset += sizeof(uint16_t); /* offset not used afterwards anymore */
 1256         break;
 1257     case PTP_OPFF_ByteArray:
 1258         if (offset + sizeof(uint16_t) > opdlen) goto outofmemory;
 1259         opd->FORM.ByteArray.NumberOfValues = dtoh16a(&data[offset]);
 1260         offset += sizeof(uint16_t); /* offset not used afterwards anymore */
 1261         break;
 1262     case PTP_OPFF_LongString:
 1263         break;
 1264     }
 1265     return 1;
 1266 outofmemory:
 1267     ptp_free_objectpropdesc(opd);
 1268     return 0;
 1269 }
 1270 
 1271 static inline uint32_t
 1272 ptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
 1273 {
 1274     unsigned char* dpv=NULL;
 1275     uint32_t size=0;
 1276     unsigned int i;
 1277 
 1278     switch (datatype) {
 1279     case PTP_DTC_INT8:
 1280         size=sizeof(int8_t);
 1281         dpv=malloc(size);
 1282         htod8a(dpv,value->i8);
 1283         break;
 1284     case PTP_DTC_UINT8:
 1285         size=sizeof(uint8_t);
 1286         dpv=malloc(size);
 1287         htod8a(dpv,value->u8);
 1288         break;
 1289     case PTP_DTC_INT16:
 1290         size=sizeof(int16_t);
 1291         dpv=malloc(size);
 1292         htod16a(dpv,value->i16);
 1293         break;
 1294     case PTP_DTC_UINT16:
 1295         size=sizeof(uint16_t);
 1296         dpv=malloc(size);
 1297         htod16a(dpv,value->u16);
 1298         break;
 1299     case PTP_DTC_INT32:
 1300         size=sizeof(int32_t);
 1301         dpv=malloc(size);
 1302         htod32a(dpv,value->i32);
 1303         break;
 1304     case PTP_DTC_UINT32:
 1305         size=sizeof(uint32_t);
 1306         dpv=malloc(size);
 1307         htod32a(dpv,value->u32);
 1308         break;
 1309     case PTP_DTC_INT64:
 1310         size=sizeof(int64_t);
 1311         dpv=malloc(size);
 1312         htod64a(dpv,value->i64);
 1313         break;
 1314     case PTP_DTC_UINT64:
 1315         size=sizeof(uint64_t);
 1316         dpv=malloc(size);
 1317         htod64a(dpv,value->u64);
 1318         break;
 1319     case PTP_DTC_AUINT8:
 1320         size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
 1321         dpv=malloc(size);
 1322         htod32a(dpv,value->a.count);
 1323         for (i=0;i<value->a.count;i++)
 1324             htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
 1325         break;
 1326     case PTP_DTC_AINT8:
 1327         size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
 1328         dpv=malloc(size);
 1329         htod32a(dpv,value->a.count);
 1330         for (i=0;i<value->a.count;i++)
 1331             htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
 1332         break;
 1333     case PTP_DTC_AUINT16:
 1334         size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
 1335         dpv=malloc(size);
 1336         htod32a(dpv,value->a.count);
 1337         for (i=0;i<value->a.count;i++)
 1338             htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
 1339         break;
 1340     case PTP_DTC_AINT16:
 1341         size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
 1342         dpv=malloc(size);
 1343         htod32a(dpv,value->a.count);
 1344         for (i=0;i<value->a.count;i++)
 1345             htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
 1346         break;
 1347     case PTP_DTC_AUINT32:
 1348         size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
 1349         dpv=malloc(size);
 1350         htod32a(dpv,value->a.count);
 1351         for (i=0;i<value->a.count;i++)
 1352             htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
 1353         break;
 1354     case PTP_DTC_AINT32:
 1355         size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
 1356         dpv=malloc(size);
 1357         htod32a(dpv,value->a.count);
 1358         for (i=0;i<value->a.count;i++)
 1359             htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
 1360         break;
 1361     case PTP_DTC_AUINT64:
 1362         size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
 1363         dpv=malloc(size);
 1364         htod32a(dpv,value->a.count);
 1365         for (i=0;i<value->a.count;i++)
 1366             htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
 1367         break;
 1368     case PTP_DTC_AINT64:
 1369         size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
 1370         dpv=malloc(size);
 1371         htod32a(dpv,value->a.count);
 1372         for (i=0;i<value->a.count;i++)
 1373             htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
 1374         break;
 1375     /* XXX: other int types are unimplemented */
 1376     case PTP_DTC_STR: {
 1377         dpv=ptp_get_packed_stringcopy(params, value->str, &size);
 1378         break;
 1379     }
 1380     }
 1381     *dpvptr=dpv;
 1382     return size;
 1383 }
 1384 
 1385 #define MAX_MTP_PROPS 127
 1386 static inline uint32_t
 1387 ptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
 1388 {
 1389     unsigned char* opldata;
 1390     MTPProperties *propitr;
 1391     unsigned char *packedprops[MAX_MTP_PROPS];
 1392     uint32_t packedpropslens[MAX_MTP_PROPS];
 1393     uint32_t packedobjecthandles[MAX_MTP_PROPS];
 1394     uint16_t packedpropsids[MAX_MTP_PROPS];
 1395     uint16_t packedpropstypes[MAX_MTP_PROPS];
 1396     uint32_t totalsize = 0;
 1397     uint32_t bufp = 0;
 1398     uint32_t noitems = 0;
 1399     uint32_t i;
 1400 
 1401     totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
 1402     propitr = props;
 1403     while (nrofprops-- && noitems < MAX_MTP_PROPS) {
 1404         /* Object Handle */
 1405         packedobjecthandles[noitems]=propitr->ObjectHandle;
 1406         totalsize += sizeof(uint32_t); /* Object ID */
 1407         /* Metadata type */
 1408         packedpropsids[noitems]=propitr->property;
 1409         totalsize += sizeof(uint16_t);
 1410         /* Data type */
 1411         packedpropstypes[noitems]= propitr->datatype;
 1412         totalsize += sizeof(uint16_t);
 1413         /* Add each property to be sent. */
 1414             packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
 1415         totalsize += packedpropslens[noitems];
 1416         noitems ++;
 1417         propitr ++;
 1418     }
 1419 
 1420     /* Allocate memory for the packed property list */
 1421     opldata = malloc(totalsize);
 1422 
 1423     htod32a(&opldata[bufp],noitems);
 1424     bufp += 4;
 1425 
 1426     /* Copy into a nice packed list */
 1427     for (i = 0; i < noitems; i++) {
 1428         /* Object ID */
 1429         htod32a(&opldata[bufp],packedobjecthandles[i]);
 1430         bufp += sizeof(uint32_t);
 1431         htod16a(&opldata[bufp],packedpropsids[i]);
 1432         bufp += sizeof(uint16_t);
 1433         htod16a(&opldata[bufp],packedpropstypes[i]);
 1434         bufp += sizeof(uint16_t);
 1435         /* The copy the actual property */
 1436         memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
 1437         bufp += packedpropslens[i];
 1438         free(packedprops[i]);
 1439     }
 1440     *opldataptr = opldata;
 1441     return totalsize;
 1442 }
 1443 
 1444 static int
 1445 _compare_func(const void* x, const void *y) {
 1446     const MTPProperties *px = x;
 1447     const MTPProperties *py = y;
 1448 
 1449     return px->ObjectHandle - py->ObjectHandle;
 1450 }
 1451 
 1452 static inline int
 1453 ptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
 1454 {
 1455     uint32_t prop_count;
 1456     MTPProperties *props = NULL;
 1457     unsigned int offset = 0, i;
 1458 
 1459     if (len < sizeof(uint32_t)) {
 1460         ptp_debug (params ,"must have at least 4 bytes data, not %d", len);
 1461         return 0;
 1462     }
 1463 
 1464     prop_count = dtoh32a(data);
 1465     *pprops = NULL;
 1466     if (prop_count == 0)
 1467         return 0;
 1468 
 1469     if (prop_count >= INT_MAX/sizeof(MTPProperties)) {
 1470         ptp_debug (params ,"prop_count %d is too large", prop_count);
 1471         return 0;
 1472     }
 1473     ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
 1474 
 1475     data += sizeof(uint32_t);
 1476     len -= sizeof(uint32_t);
 1477     props = calloc(prop_count , sizeof(MTPProperties));
 1478     if (!props) return 0;
 1479     for (i = 0; i < prop_count; i++) {
 1480         if (len <= (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t))) {
 1481             ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
 1482             ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL");
 1483             ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST");
 1484             qsort (props, i, sizeof(MTPProperties),_compare_func);
 1485             *pprops = props;
 1486             return i;
 1487         }
 1488 
 1489 
 1490         props[i].ObjectHandle = dtoh32a(data);
 1491         data += sizeof(uint32_t);
 1492         len -= sizeof(uint32_t);
 1493 
 1494         props[i].property = dtoh16a(data);
 1495         data += sizeof(uint16_t);
 1496         len -= sizeof(uint16_t);
 1497 
 1498         props[i].datatype = dtoh16a(data);
 1499         data += sizeof(uint16_t);
 1500         len -= sizeof(uint16_t);
 1501 
 1502         offset = 0;
 1503         if (!ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype)) {
 1504             ptp_debug (params ,"unpacking DPV of property %d encountered insufficient buffer. attack?", i);
 1505             qsort (props, i, sizeof(MTPProperties),_compare_func);
 1506             *pprops = props;
 1507             return i;
 1508         }
 1509         data += offset;
 1510         len -= offset;
 1511     }
 1512     qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
 1513     *pprops = props;
 1514     return prop_count;
 1515 }
 1516 
 1517 /*
 1518     PTP USB Event container unpack
 1519     Copyright (c) 2003 Nikolai Kopanygin
 1520 */
 1521 
 1522 #define PTP_ec_Length       0
 1523 #define PTP_ec_Type     4
 1524 #define PTP_ec_Code     6
 1525 #define PTP_ec_TransId      8
 1526 #define PTP_ec_Param1       12
 1527 #define PTP_ec_Param2       16
 1528 #define PTP_ec_Param3       20
 1529 
 1530 static inline void
 1531 ptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
 1532 {
 1533     unsigned int    length;
 1534     int type;
 1535 
 1536     if (data==NULL)
 1537         return;
 1538     memset(ec,0,sizeof(*ec));
 1539 
 1540     length=dtoh32a(&data[PTP_ec_Length]);
 1541     if (length > len) {
 1542         ptp_debug (params, "length %d in container, but data only %d bytes?!", length, len);
 1543         return;
 1544     }
 1545     type = dtoh16a(&data[PTP_ec_Type]);
 1546 
 1547     ec->Code=dtoh16a(&data[PTP_ec_Code]);
 1548     ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
 1549 
 1550     if (type!=PTP_USB_CONTAINER_EVENT) {
 1551         ptp_debug (params, "Unknown canon event type %d (code=%x,tid=%x), please report!",type,ec->Code,ec->Transaction_ID);
 1552         return;
 1553     }
 1554     if (length>=(PTP_ec_Param1+4)) {
 1555         ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
 1556         ec->Nparam=1;
 1557     }
 1558     if (length>=(PTP_ec_Param2+4)) {
 1559         ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
 1560         ec->Nparam=2;
 1561     }
 1562     if (length>=(PTP_ec_Param3+4)) {
 1563         ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
 1564         ec->Nparam=3;
 1565     }
 1566 }
 1567 
 1568 /*
 1569     PTP Canon Folder Entry unpack
 1570     Copyright (c) 2003 Nikolai Kopanygin
 1571 */
 1572 #define PTP_cfe_ObjectHandle        0
 1573 #define PTP_cfe_ObjectFormatCode    4
 1574 #define PTP_cfe_Flags           6
 1575 #define PTP_cfe_ObjectSize      7
 1576 #define PTP_cfe_Time            11
 1577 #define PTP_cfe_Filename        15
 1578 
 1579 static inline void
 1580 ptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
 1581 {
 1582     int i;
 1583     if (data==NULL)
 1584         return;
 1585     fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
 1586     fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
 1587     fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
 1588     fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
 1589     fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
 1590     for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
 1591         fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
 1592 }
 1593 
 1594 /*
 1595     PTP Canon EOS Folder Entry unpack
 1596 0: 00 00 08 a0     objectid
 1597 4: 01 00 02 00     storageid
 1598 8: 01 30 00 00     ofc
 1599 12: 01 00
 1600 14: 00 00
 1601 16: 11 00 00 00
 1602 20: 00 00 00 00
 1603 24: 00 00 00 80
 1604 28: 00 00 08 a0
 1605 32: 4d 49 53 43-00 00 00 00 00 00 00 00     name
 1606 00 00 00 00
 1607 84 bc 74 46     objectime
 1608 
 1609 
 1610 (normal PTP GetObjectInfo)
 1611 ObjectInfo for 'IMG_0199.JPG':
 1612   Object ID: 0x92740c72
 1613   StorageID: 0x00020001
 1614   ObjectFormat: 0x3801
 1615   ProtectionStatus: 0x0000
 1616   ObjectCompressedSize: 2217241
 1617   ThumbFormat: 0x3808
 1618   ThumbCompressedSize: 5122
 1619   ThumbPixWidth: 160
 1620   ThumbPixHeight: 120
 1621   ImagePixWidth: 4000
 1622   ImagePixHeight: 3000
 1623   ImageBitDepth: 24
 1624   ParentObject: 0x92740000
 1625   AssociationType: 0x0000
 1626   AssociationDesc: 0x00000000
 1627   SequenceNumber: 0x00000000
 1628   ModificationDate: 0x4d985ff0
 1629   CaptureDate: 0x4d985ff0
 1630 
 1631 0010  38 00 00 00  Size of this entry
 1632 0014  72 0c 74 92  OID
 1633 0018  01 00 02 00  StorageID
 1634 001c  01 38 00 00  OFC
 1635 0020  00 00 00 00 ??
 1636 0024  21 00 00 00  flags (4 bytes? 1 byte?)
 1637 0028  19 d5 21 00  Size
 1638 002c  00 00 74 92  ?
 1639 0030  70 0c 74 92  OID
 1640 0034  49 4d 47 5f-30 31 39 39 2e 4a 50 47  IMG_0199.JPG
 1641 0040  00 00 00 00
 1642 0044  10 7c 98 4d Time
 1643 
 1644 
 1645 */
 1646 #define PTP_cefe_ObjectHandle       0
 1647 #define PTP_cefe_StorageID      4
 1648 #define PTP_cefe_ObjectFormatCode   8
 1649 #define PTP_cefe_Flags          16
 1650 #define PTP_cefe_ObjectSize     20
 1651 #define PTP_cefe_Filename       32
 1652 #define PTP_cefe_Time           48
 1653 
 1654 static inline void
 1655 ptp_unpack_Canon_EOS_FE (PTPParams *params, unsigned char* data, unsigned int size, PTPCANONFolderEntry *fe)
 1656 {
 1657     int i;
 1658 
 1659     if (size < PTP_cefe_Time + 4) return;
 1660 
 1661     fe->ObjectHandle=dtoh32a(&data[PTP_cefe_ObjectHandle]);
 1662     fe->ObjectFormatCode=dtoh16a(&data[PTP_cefe_ObjectFormatCode]);
 1663     fe->Flags=dtoh8a(&data[PTP_cefe_Flags]);
 1664     fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cefe_ObjectSize]);
 1665     fe->Time=(time_t)dtoh32a(&data[PTP_cefe_Time]);
 1666     for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
 1667         fe->Filename[i]=(char)data[PTP_cefe_Filename+i];
 1668     fe->Filename[PTP_CANON_FilenameBufferLen-1] = 0;
 1669 }
 1670 
 1671 
 1672 static inline uint16_t
 1673 ptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
 1674 {
 1675     /*
 1676       EOS ImageFormat entries (of at least the 5DM2 and the 400D) look like this:
 1677         uint32: number of entries / generated files (1 or 2)
 1678         uint32: size of this entry in bytes (most likely allways 0x10)
 1679         uint32: image type (1 == JPG, 6 == RAW)
 1680         uint32: image size (0 == Large, 1 == Medium, 2 == Small, 0xe == S1, 0xf == S2, 0x10 == S3)
 1681         uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW)
 1682       If the number of entries is 2 the last 4 uint32 repeat.
 1683 
 1684       example:
 1685         0: 0x       1
 1686         1: 0x      10
 1687         2: 0x       6
 1688         3: 0x       1
 1689         4: 0x       4
 1690 
 1691       The idea is to simply 'condense' these values to just one uint16 to be able to conveniently
 1692       use the available enumeration facilities (look-up table). The image size and compression
 1693       values used to fully describe the image format, but at least since EOS M50 (with cRAW)
 1694       it is no longer true - we need to store RAW flag (8).
 1695       Hence we generate a uint16 with the four nibles set as follows:
 1696 
 1697       entry 1 size | entry 1 compression & RAW flag | entry 2 size | entry 2 compression & RAW flag.
 1698 
 1699       The above example would result in the value 0x1400.
 1700 
 1701       The EOS 5D Mark III (and possibly other high-end EOS as well) added the extra fancy S1, S2
 1702       and S3 JPEG options. S1 replaces the old Small. -1 the S1/S2/S3 to prevent the 0x10 overflow.
 1703       */
 1704 
 1705     const unsigned char* d = *data;
 1706     uint32_t n = dtoh32a( d );
 1707     uint32_t l, t1, s1, c1, t2 = 0, s2 = 0, c2 = 0;
 1708 
 1709     if (n != 1 && n !=2) {
 1710         ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
 1711         return 0;
 1712     }
 1713 
 1714     l = dtoh32a( d+=4 );
 1715     if (l != 0x10) {
 1716         ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
 1717         return 0;
 1718     }
 1719 
 1720     t1 = dtoh32a( d+=4 );
 1721     s1 = dtoh32a( d+=4 );
 1722     c1 = dtoh32a( d+=4 );
 1723 
 1724     if (n == 2) {
 1725         l = dtoh32a( d+=4 );
 1726         if (l != 0x10) {
 1727             ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
 1728             return 0;
 1729         }
 1730         t2 = dtoh32a( d+=4 );
 1731         s2 = dtoh32a( d+=4 );
 1732         c2 = dtoh32a( d+=4 );
 1733     }
 1734 
 1735     *data = (unsigned char*) d+4;
 1736 
 1737     /* deal with S1/S2/S3 JPEG sizes, see above. */
 1738     if( s1 >= 0xe )
 1739         s1--;
 1740     if( s2 >= 0xe )
 1741         s2--;
 1742 
 1743     /* encode RAW flag */
 1744     c1 |= (t1 == 6) ? 8 : 0;
 1745     c2 |= (t2 == 6) ? 8 : 0;
 1746 
 1747     return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
 1748 }
 1749 
 1750 static inline uint32_t
 1751 ptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
 1752 {
 1753     uint32_t n = (value & 0xFF) ? 2 : 1;
 1754     uint32_t s = 4 + 0x10 * n;
 1755 
 1756     if( !data )
 1757         return s;
 1758 
 1759 #define PACK_5DM3_SMALL_JPEG_SIZE( X ) (X) >= 0xd ? (X)+1 : (X)
 1760 
 1761     htod32a(data+=0, n);
 1762     htod32a(data+=4, 0x10);
 1763     htod32a(data+=4, (((value >> 8) & 0xF) >> 3) ? 6 : 1);
 1764     htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 12) & 0xF));
 1765     htod32a(data+=4, ((value >> 8) & 0xF) & ~8);
 1766 
 1767     if (n==2) {
 1768         htod32a(data+=4, 0x10);
 1769         htod32a(data+=4, (((value >> 0) & 0xF) >> 3) ? 6 : 1);
 1770         htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 4) & 0xF));
 1771         htod32a(data+=4, ((value >> 0) & 0xF) & ~8);
 1772     }
 1773 
 1774 #undef PACK_5DM3_SMALL_JPEG_SIZE
 1775 
 1776     return s;
 1777 }
 1778 
 1779 /* 00: 32 bit size
 1780  * 04: 16 bit subsize
 1781  * 08: 16 bit version (?)
 1782  * 0c: 16 bit focus_points_in_struct
 1783  * 10: 16 bit focus_points_in_use
 1784  * 14: variable arrays:
 1785  *  16 bit sizex, 16 bit sizey
 1786  *  16 bit othersizex, 16 bit othersizey
 1787  *  16 bit array height[focus_points_in_struct]
 1788  *  16 bit array width[focus_points_in_struct]
 1789  *  16 bit array offsetheight[focus_points_in_struct] middle is 0
 1790  *  16 bit array offsetwidth[focus_points_in_struct] middle is ?
 1791  * bitfield of selected focus points, starting with 0 [size focus_points_in_struct in bits]
 1792  * unknown stuff , likely which are active
 1793  * 16 bit 0xffff
 1794  *
 1795  * size=NxN,size2=NxN,points={NxNxNxN,NxNxNxN,...},selected={0,1,2}
 1796  */
 1797 static inline char*
 1798 ptp_unpack_EOS_FocusInfoEx (PTPParams* params, unsigned char** data, uint32_t datasize )
 1799 {
 1800     uint32_t size           = dtoh32a( *data );
 1801     uint32_t halfsize       = dtoh16a( (*data) + 4);
 1802     uint32_t version        = dtoh16a( (*data) + 6);
 1803     uint32_t focus_points_in_struct = dtoh16a( (*data) + 8);
 1804     uint32_t focus_points_in_use    = dtoh16a( (*data) + 10);
 1805     uint32_t sizeX          = dtoh16a( (*data) + 12);
 1806     uint32_t sizeY          = dtoh16a( (*data) + 14);
 1807     uint32_t size2X         = dtoh16a( (*data) + 16);
 1808     uint32_t size2Y         = dtoh16a( (*data) + 18);
 1809     uint32_t i;
 1810     uint32_t maxlen;
 1811     char    *str, *p;
 1812 
 1813     if ((size >= datasize) || (size < 20))
 1814         return strdup("bad size 1");
 1815     /* If data is zero-filled, then it is just a placeholder, so nothing
 1816        useful, but also not an error */
 1817     if (!focus_points_in_struct || !focus_points_in_use) {
 1818         ptp_debug(params, "skipped FocusInfoEx data (zero filled)");
 1819         return strdup("no focus points returned by camera");
 1820     }
 1821 
 1822     /* every focuspoint gets 4 (16 bit number possible "-" sign and a x) and a ,*/
 1823     /* initial things around lets say 100 chars at most.
 1824      * FIXME: check selected when we decode it
 1825      */
 1826     if (size < focus_points_in_struct*8) {
 1827         ptp_error(params, "focus_points_in_struct %d is too large vs size %d", focus_points_in_struct, size);
 1828         return strdup("bad size 2");
 1829     }
 1830     if (focus_points_in_use > focus_points_in_struct) {
 1831         ptp_error(params, "focus_points_in_use %d is larger than focus_points_in_struct %d", focus_points_in_use, focus_points_in_struct);
 1832         return strdup("bad size 3");
 1833     }
 1834 
 1835     maxlen = focus_points_in_use*32 + 100 + (size - focus_points_in_struct*8)*2;
 1836     if (halfsize != size-4) {
 1837         ptp_error(params, "halfsize %d is not expected %d", halfsize, size-4);
 1838         return strdup("bad size 4");
 1839     }
 1840     if (20 + focus_points_in_struct*8 + (focus_points_in_struct+7)/8 > size) {
 1841         ptp_error(params, "size %d is too large for fp in struct %d", focus_points_in_struct*8 + 20 + (focus_points_in_struct+7)/8, size);
 1842         return strdup("bad size 5");
 1843     }
 1844 #if 0
 1845     ptp_debug(params,"d1d3 content:");
 1846     for (i=0;i<size;i+=2)
 1847         ptp_debug(params,"%d: %02x %02x", i, (*data)[i], (*data)[i+1]);
 1848 #endif
 1849     ptp_debug(params,"d1d3 version %d", version);
 1850     ptp_debug(params,"d1d3 size %d", size);
 1851     ptp_debug(params,"d1d3 focus points in struct %d, in use %d", focus_points_in_struct, focus_points_in_use);
 1852 
 1853     str = (char*)malloc( maxlen );
 1854     if (!str)
 1855         return NULL;
 1856     p = str;
 1857 
 1858     p += sprintf(p,"eosversion=%u,size=%ux%u,size2=%ux%u,points={", version, sizeX, sizeY, size2X, size2Y);
 1859     for (i=0;i<focus_points_in_use;i++) {
 1860         int16_t x = dtoh16a((*data) + focus_points_in_struct*4 + 20 + 2*i);
 1861         int16_t y = dtoh16a((*data) + focus_points_in_struct*6 + 20 + 2*i);
 1862         int16_t w = dtoh16a((*data) + focus_points_in_struct*2 + 20 + 2*i);
 1863         int16_t h = dtoh16a((*data) + focus_points_in_struct*0 + 20 + 2*i);
 1864 
 1865         p += sprintf(p,"{%d,%d,%d,%d}",x,y,w,h);
 1866 
 1867         if (i<focus_points_in_use-1)
 1868             p += sprintf(p,",");
 1869     }
 1870     p += sprintf(p,"},select={");
 1871     for (i=0;i<focus_points_in_use;i++) {
 1872         if ((1<<(i%8)) & ((*data)[focus_points_in_struct*8+20+i/8]))
 1873             p+=sprintf(p,"%u,", i);
 1874     }
 1875 
 1876     p += sprintf(p,"},unknown={");
 1877     for (i=focus_points_in_struct*8+(focus_points_in_struct+7)/8+20;i<size;i++) {
 1878         if ((p-str) > maxlen - 4)
 1879             break;
 1880         p+=sprintf(p,"%02x", (*data)[i]);
 1881     }
 1882     p += sprintf(p,"}");
 1883     return str;
 1884 }
 1885 
 1886 
 1887 static inline char*
 1888 ptp_unpack_EOS_CustomFuncEx (PTPParams* params, unsigned char** data )
 1889 {
 1890     uint32_t s = dtoh32a( *data );
 1891     uint32_t n = s/4, i;
 1892     char    *str, *p;
 1893 
 1894     if (s > 1024) {
 1895         ptp_debug (params, "customfuncex data is larger than 1k / %d... unexpected?", s);
 1896         return strdup("bad length");
 1897     }
 1898     str = (char*)malloc( s*2+s/4+1 ); /* n is size in uint32, maximum %x len is 8 chars and \0*/
 1899     if (!str)
 1900         return strdup("malloc failed");
 1901 
 1902     p = str;
 1903     for (i=0; i < n; ++i)
 1904         p += sprintf(p, "%x,", dtoh32a( *data + 4*i ));
 1905     return str;
 1906 }
 1907 
 1908 static inline uint32_t
 1909 ptp_pack_EOS_CustomFuncEx (PTPParams* params, unsigned char* data, char* str)
 1910 {
 1911     uint32_t s = strtoul(str, NULL, 16);
 1912     uint32_t n = s/4, i, v;
 1913 
 1914     if (!data)
 1915         return s;
 1916 
 1917     for (i=0; i<n; i++)
 1918     {
 1919         v = strtoul(str, &str, 16);
 1920         str++; /* skip the ',' delimiter */
 1921         htod32a(data + i*4, v);
 1922     }
 1923 
 1924     return s;
 1925 }
 1926 
 1927 /*
 1928     PTP EOS Changes Entry unpack
 1929 */
 1930 #define PTP_ece_Size        0
 1931 #define PTP_ece_Type        4
 1932 
 1933 #define PTP_ece_Prop_Subtype    8   /* only for properties */
 1934 #define PTP_ece_Prop_Val_Data   0xc /* only for properties */
 1935 #define PTP_ece_Prop_Desc_Type  0xc /* only for property descs */
 1936 #define PTP_ece_Prop_Desc_Count 0x10    /* only for property descs */
 1937 #define PTP_ece_Prop_Desc_Data  0x14    /* only for property descs */
 1938 
 1939 /* for PTP_EC_CANON_EOS_RequestObjectTransfer */
 1940 #define PTP_ece_OI_ObjectID 8
 1941 #define PTP_ece_OI_OFC      0x0c
 1942 #define PTP_ece_OI_Size     0x14
 1943 #define PTP_ece_OI_Name     0x1c
 1944 
 1945 /* for PTP_EC_CANON_EOS_ObjectAddedEx */
 1946 #define PTP_ece_OA_ObjectID 8
 1947 #define PTP_ece_OA_StorageID    0x0c
 1948 #define PTP_ece_OA_OFC      0x10
 1949 #define PTP_ece_OA_Size     0x1c
 1950 #define PTP_ece_OA_Parent   0x20
 1951 #define PTP_ece_OA_Name     0x28
 1952 
 1953 #define PTP_ece2_OA_ObjectID    8   /* OK */
 1954 #define PTP_ece2_OA_StorageID   0x0c    /* OK */
 1955 #define PTP_ece2_OA_OFC     0x10    /* OK */
 1956 #define PTP_ece2_OA_Size    0x1c    /* OK, might be 64 bit now? */
 1957 #define PTP_ece2_OA_Parent  0x24
 1958 #define PTP_ece2_OA_2ndOID  0x28
 1959 #define PTP_ece2_OA_Name    0x2c    /* OK */
 1960 
 1961 /* for PTP_EC_CANON_EOS_ObjectAddedNew */
 1962 #define PTP_ece_OAN_OFC     0x0c
 1963 #define PTP_ece_OAN_Size    0x14
 1964 
 1965 static PTPDevicePropDesc*
 1966 _lookup_or_allocate_canon_prop(PTPParams *params, uint16_t proptype)
 1967 {
 1968     unsigned int j;
 1969 
 1970     for (j=0;j<params->nrofcanon_props;j++)
 1971         if (params->canon_props[j].proptype == proptype)
 1972             break;
 1973     if (j<params->nrofcanon_props)
 1974         return &params->canon_props[j].dpd;
 1975 
 1976     if (j)
 1977         params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
 1978     else
 1979         params->canon_props = malloc(sizeof(params->canon_props[0]));
 1980     params->canon_props[j].proptype = proptype;
 1981     params->canon_props[j].size = 0;
 1982     params->canon_props[j].data = NULL;
 1983     memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
 1984     params->canon_props[j].dpd.GetSet = 1;
 1985     params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
 1986     params->nrofcanon_props = j+1;
 1987     return &params->canon_props[j].dpd;
 1988 }
 1989 
 1990 
 1991 static inline int
 1992 ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, unsigned int datasize, PTPCanon_changes_entry **pce)
 1993 {
 1994     int i = 0, entries = 0;
 1995     unsigned char   *curdata = data;
 1996     PTPCanon_changes_entry *ce;
 1997 
 1998     if (data==NULL)
 1999         return 0;
 2000     while (curdata - data + 8 < datasize) {
 2001         uint32_t    size = dtoh32a(&curdata[PTP_ece_Size]);
 2002         uint32_t    type = dtoh32a(&curdata[PTP_ece_Type]);
 2003 
 2004         if (size > datasize) {
 2005             ptp_debug (params, "size %d is larger than datasize %d", size, datasize);
 2006             break;
 2007         }
 2008         if (size < 8) {
 2009             ptp_debug (params, "size %d is smaller than 8.", size);
 2010             break;
 2011         }
 2012         if ((size == 8) && (type == 0))
 2013             break;
 2014         if ((curdata - data) + size >= datasize) {
 2015             ptp_debug (params, "canon eos event decoder ran over supplied data, skipping entries");
 2016             break;
 2017         }
 2018         if (type == PTP_EC_CANON_EOS_OLCInfoChanged) {
 2019             unsigned int j;
 2020 
 2021             entries++;
 2022             if (size >= 12+2) {
 2023                 for (j=0;j<31;j++)
 2024                     if (dtoh16a(curdata+12) & (1<<j))
 2025                         entries++;
 2026             }
 2027         }
 2028         curdata += size;
 2029         entries++;
 2030     }
 2031     ce = calloc (sizeof(PTPCanon_changes_entry),(entries+1));
 2032     if (!ce) return 0;
 2033 
 2034     curdata = data;
 2035     while (curdata - data  + 8 < datasize) {
 2036         uint32_t    size = dtoh32a(&curdata[PTP_ece_Size]);
 2037         uint32_t    type = dtoh32a(&curdata[PTP_ece_Type]);
 2038 
 2039         if (size > datasize) {
 2040             ptp_debug (params, "size %d is larger than datasize %d", size, datasize);
 2041             break;
 2042         }
 2043         if (size < 8) {
 2044             ptp_debug (params, "size %d is smaller than 8", size);
 2045             break;
 2046         }
 2047 
 2048         if ((size == 8) && (type == 0))
 2049             break;
 2050 
 2051         if ((curdata - data) + size >= datasize) {
 2052             ptp_debug (params, "canon eos event decoder ran over supplied data, skipping entries");
 2053             break;
 2054         }
 2055 
 2056         ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2057         ce[i].u.info = NULL;
 2058         switch (type) {
 2059         case PTP_EC_CANON_EOS_ObjectContentChanged:
 2060             if (size < PTP_ece_OA_ObjectID+1) {
 2061                 ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_OA_ObjectID+1);
 2062                 break;
 2063             }
 2064             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTCONTENT_CHANGE;
 2065             ce[i].u.object.oid          = dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
 2066             break;
 2067         case PTP_EC_CANON_EOS_ObjectInfoChangedEx:
 2068         case PTP_EC_CANON_EOS_ObjectAddedEx:
 2069             if (size < PTP_ece_OA_Name+1) {
 2070                 ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_OA_Name+1);
 2071                 break;
 2072             }
 2073             ce[i].type = ((type == PTP_EC_CANON_EOS_ObjectAddedEx) ? PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO : PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO_CHANGE);
 2074             ce[i].u.object.oid          = dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
 2075             ce[i].u.object.oi.StorageID = dtoh32a(&curdata[PTP_ece_OA_StorageID]);
 2076             ce[i].u.object.oi.ParentObject  = dtoh32a(&curdata[PTP_ece_OA_Parent]);
 2077             ce[i].u.object.oi.ObjectFormat  = dtoh16a(&curdata[PTP_ece_OA_OFC]);
 2078             ce[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
 2079             ce[i].u.object.oi.Filename  = strdup(((char*)&curdata[PTP_ece_OA_Name]));
 2080             if (type == PTP_EC_CANON_EOS_ObjectAddedEx) {
 2081                 ptp_debug (params, "event %d: objectinfo added oid %08lx, parent %08lx, ofc %04x, size %d, filename %s", i, ce[i].u.object.oid, ce[i].u.object.oi.ParentObject, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename);
 2082             } else {
 2083                 ptp_debug (params, "event %d: objectinfo changed oid %08lx, parent %08lx, ofc %04x, size %d, filename %s", i, ce[i].u.object.oid, ce[i].u.object.oi.ParentObject, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename);
 2084             }
 2085             break;
 2086         case PTP_EC_CANON_EOS_ObjectAddedEx64:  /* FIXME: review if the data used is correct */
 2087             if (size < PTP_ece2_OA_Name+1) {
 2088                 ptp_debug (params, "size %d is smaller than %d", size, PTP_ece2_OA_Name+1);
 2089                 break;
 2090             }
 2091             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
 2092             ce[i].u.object.oid          = dtoh32a(&curdata[PTP_ece2_OA_ObjectID]);
 2093             ce[i].u.object.oi.StorageID = dtoh32a(&curdata[PTP_ece2_OA_StorageID]);
 2094             ce[i].u.object.oi.ParentObject  = dtoh32a(&curdata[PTP_ece2_OA_Parent]);
 2095             ce[i].u.object.oi.ObjectFormat  = dtoh16a(&curdata[PTP_ece2_OA_OFC]);
 2096             ce[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece2_OA_Size]);    /* FIXME: might be 64bit now */
 2097             ce[i].u.object.oi.Filename  = strdup(((char*)&curdata[PTP_ece2_OA_Name]));
 2098             ptp_debug (params, "event %d: objectinfo added oid %08lx, parent %08lx, ofc %04x, size %d, filename %s", i, ce[i].u.object.oid, ce[i].u.object.oi.ParentObject, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename);
 2099             break;
 2100         case PTP_EC_CANON_EOS_RequestObjectTransfer:
 2101         case PTP_EC_CANON_EOS_RequestObjectTransfer64:
 2102             if (size < PTP_ece_OI_Name+1) {
 2103                 ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_OI_Name+1);
 2104                 break;
 2105             }
 2106             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
 2107             ce[i].u.object.oid          = dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
 2108             ce[i].u.object.oi.StorageID     = 0; /* use as marker */
 2109             ce[i].u.object.oi.ObjectFormat  = dtoh16a(&curdata[PTP_ece_OI_OFC]);
 2110             ce[i].u.object.oi.ParentObject  = 0; /* check, but use as marker */
 2111             ce[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
 2112             ce[i].u.object.oi.Filename  = strdup(((char*)&curdata[PTP_ece_OI_Name]));
 2113 
 2114             ptp_debug (params, "event %d: request object transfer oid %08lx, ofc %04x, size %d, filename %p", i, ce[i].u.object.oid, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename);
 2115             break;
 2116         case PTP_EC_CANON_EOS_AvailListChanged: {   /* property desc */
 2117             uint32_t    proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
 2118             uint32_t    propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
 2119             uint32_t    propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
 2120             unsigned char   *xdata = &curdata[PTP_ece_Prop_Desc_Data];
 2121             unsigned int    j;
 2122             PTPDevicePropDesc   *dpd;
 2123 
 2124             if (size < PTP_ece_Prop_Desc_Data) {
 2125                 ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_Prop_Desc_Data);
 2126                 break;
 2127             }
 2128 
 2129             ptp_debug (params, "event %d: EOS prop %04x (%s) desc record, datasize %d, propxtype %d", i, proptype, ptp_get_property_description (params, proptype), size-PTP_ece_Prop_Desc_Data, propxtype);
 2130             for (j=0;j<params->nrofcanon_props;j++)
 2131                 if (params->canon_props[j].proptype == proptype)
 2132                     break;
 2133             if (j==params->nrofcanon_props) {
 2134                 ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
 2135                 break;
 2136             }
 2137             dpd = &params->canon_props[j].dpd;
 2138             /* 1 - uint16 ?
 2139              * 3 - uint16
 2140              * 7 - string?
 2141              */
 2142             if (propxtype != 3) {
 2143                 ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled, size %d", i, propxtype, proptype, size);
 2144                 for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++)
 2145                     ptp_debug (params, "    %d: %02x", j, xdata[j]);
 2146                 break;
 2147             }
 2148             if (! propxcnt)
 2149                 break;
 2150             if (propxcnt >= 2<<16) /* buggy or exploit */
 2151                 break;
 2152 
 2153             ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
 2154                    i, propxtype, proptype, dpd->DataType, propxcnt);
 2155             dpd->FormFlag = PTP_DPFF_Enumeration;
 2156             dpd->FORM.Enum.NumberOfValues = propxcnt;
 2157             free (dpd->FORM.Enum.SupportedValue);
 2158             dpd->FORM.Enum.SupportedValue = calloc (sizeof (PTPPropertyValue),propxcnt);
 2159 
 2160             switch (proptype) {
 2161             case PTP_DPC_CANON_EOS_ImageFormat:
 2162             case PTP_DPC_CANON_EOS_ImageFormatCF:
 2163             case PTP_DPC_CANON_EOS_ImageFormatSD:
 2164             case PTP_DPC_CANON_EOS_ImageFormatExtHD:
 2165                 /* special handling of ImageFormat properties */
 2166                 for (j=0;j<propxcnt;j++) {
 2167                     dpd->FORM.Enum.SupportedValue[j].u16 =
 2168                             ptp_unpack_EOS_ImageFormat( params, &xdata );
 2169                     ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
 2170                 }
 2171                 break;
 2172             default:
 2173                 /* 'normal' enumerated types */
 2174                 switch (dpd->DataType) {
 2175 #define XX( TYPE, CONV )\
 2176                     if (sizeof(dpd->FORM.Enum.SupportedValue[j].TYPE)*propxcnt + PTP_ece_Prop_Desc_Data > size) {   \
 2177                         ptp_debug (params, "size %lu does not match needed %u", sizeof(dpd->FORM.Enum.SupportedValue[j].TYPE)*propxcnt + PTP_ece_Prop_Desc_Data, size); \
 2178                         break;                          \
 2179                     }                               \
 2180                     for (j=0;j<propxcnt;j++) {                  \
 2181                         dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(xdata);    \
 2182                         ptp_debug (params, "event %u: suppval[%u] of %x is 0x%x.", i, j, proptype, CONV(xdata)); \
 2183                         xdata += 4; /* might only be for propxtype 3 */ \
 2184                     } \
 2185                     break;
 2186 
 2187                 case PTP_DTC_INT16: XX( i16, dtoh16a );
 2188                 case PTP_DTC_UINT16:    XX( u16, dtoh16a );
 2189                 case PTP_DTC_UINT32:    XX( u32, dtoh32a );
 2190                 case PTP_DTC_INT32: XX( i32, dtoh32a );
 2191                 case PTP_DTC_UINT8: XX( u8,  dtoh8a );
 2192                 case PTP_DTC_INT8:  XX( i8,  dtoh8a );
 2193 #undef XX
 2194                 default:
 2195                     free (dpd->FORM.Enum.SupportedValue);
 2196                     dpd->FORM.Enum.SupportedValue = NULL;
 2197                     dpd->FORM.Enum.NumberOfValues = 0;
 2198                     ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, size %d, raw values:", i, dpd->DataType, proptype, dtoh32a(xdata), size);
 2199                     for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, xdata+=4) /* 4 is good for propxtype 3 */
 2200                         ptp_debug (params, "    %3d: 0x%8x", j, dtoh32a(xdata));
 2201                     break;
 2202                 }
 2203             }
 2204             break;
 2205         }
 2206         case PTP_EC_CANON_EOS_PropValueChanged:
 2207             if (size >= 0xc) {  /* property info */
 2208                 unsigned int j;
 2209                 uint32_t    proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
 2210                 unsigned char   *xdata = &curdata[PTP_ece_Prop_Val_Data];
 2211                 PTPDevicePropDesc   *dpd;
 2212 
 2213                 if (size < PTP_ece_Prop_Val_Data) {
 2214                     ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_Prop_Val_Data);
 2215                     break;
 2216                 }
 2217                 ptp_debug (params, "event %d: EOS prop %04x (%s) info record, datasize is %d", i, proptype, ptp_get_property_description(params,proptype), size-PTP_ece_Prop_Val_Data);
 2218                 for (j=0;j<params->nrofcanon_props;j++)
 2219                     if (params->canon_props[j].proptype == proptype)
 2220                         break;
 2221                 if (j<params->nrofcanon_props) {
 2222                     if (    (params->canon_props[j].size != size) ||
 2223                         (memcmp(params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data))) {
 2224                         params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
 2225                         params->canon_props[j].size = size;
 2226                         memcpy (params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data);
 2227                     }
 2228                 } else {
 2229                     if (j)
 2230                         params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
 2231                     else
 2232                         params->canon_props = malloc(sizeof(params->canon_props[0]));
 2233                     params->canon_props[j].proptype = proptype;
 2234                     params->canon_props[j].size = size;
 2235                     params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
 2236                     memcpy(params->canon_props[j].data, xdata, size-PTP_ece_Prop_Val_Data);
 2237                     memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
 2238                     params->canon_props[j].dpd.GetSet = 1;
 2239                     params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
 2240                     params->nrofcanon_props = j+1;
 2241                 }
 2242                 dpd = &params->canon_props[j].dpd;
 2243 
 2244                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
 2245                 ce[i].u.propid = proptype;
 2246 
 2247                 /* fix GetSet value */
 2248                 switch (proptype) {
 2249 #define XX(x) case PTP_DPC_CANON_##x:
 2250                     XX(EOS_FocusMode)
 2251                     XX(EOS_BatteryPower)
 2252                     XX(EOS_BatterySelect)
 2253                     XX(EOS_ModelID)
 2254                     XX(EOS_PTPExtensionVersion)
 2255                     XX(EOS_DPOFVersion)
 2256                     XX(EOS_AvailableShots)
 2257                     XX(EOS_CurrentStorage)
 2258                     XX(EOS_CurrentFolder)
 2259                     XX(EOS_MyMenu)
 2260                     XX(EOS_MyMenuList)
 2261                     XX(EOS_HDDirectoryStructure)
 2262                     XX(EOS_BatteryInfo)
 2263                     XX(EOS_AdapterInfo)
 2264                     XX(EOS_LensStatus)
 2265                     XX(EOS_CardExtension)
 2266                     XX(EOS_TempStatus)
 2267                     XX(EOS_ShutterCounter)
 2268                     XX(EOS_SerialNumber)
 2269                     XX(EOS_DepthOfFieldPreview)
 2270                     XX(EOS_EVFRecordStatus)
 2271                     XX(EOS_LvAfSystem)
 2272                     XX(EOS_FocusInfoEx)
 2273                     XX(EOS_DepthOfField)
 2274                     XX(EOS_Brightness)
 2275                     XX(EOS_EFComp)
 2276                     XX(EOS_LensName)
 2277                     XX(EOS_LensID)
 2278                     XX(EOS_FixedMovie)
 2279 #undef XX
 2280                         dpd->GetSet = PTP_DPGS_Get;
 2281                         break;
 2282                 }
 2283 
 2284                 /* set DataType */
 2285                 switch (proptype) {
 2286                 case PTP_DPC_CANON_EOS_CameraTime:
 2287                 case PTP_DPC_CANON_EOS_UTCTime:
 2288                 case PTP_DPC_CANON_EOS_Summertime: /* basical the DST flag */
 2289                 case PTP_DPC_CANON_EOS_AvailableShots:
 2290                 case PTP_DPC_CANON_EOS_CaptureDestination:
 2291                 case PTP_DPC_CANON_EOS_WhiteBalanceXA:
 2292                 case PTP_DPC_CANON_EOS_WhiteBalanceXB:
 2293                 case PTP_DPC_CANON_EOS_CurrentStorage:
 2294                 case PTP_DPC_CANON_EOS_CurrentFolder:
 2295                 case PTP_DPC_CANON_EOS_ShutterCounter:
 2296                 case PTP_DPC_CANON_EOS_ModelID:
 2297                 case PTP_DPC_CANON_EOS_LensID:
 2298                 case PTP_DPC_CANON_EOS_StroboFiring:
 2299                 case PTP_DPC_CANON_EOS_AFSelectFocusArea:
 2300                 case PTP_DPC_CANON_EOS_ContinousAFMode:
 2301                 case PTP_DPC_CANON_EOS_MirrorUpSetting:
 2302                 case PTP_DPC_CANON_EOS_OLCInfoVersion:
 2303                 case PTP_DPC_CANON_EOS_PowerZoomPosition:
 2304                 case PTP_DPC_CANON_EOS_PowerZoomSpeed:
 2305                 case PTP_DPC_CANON_EOS_BuiltinStroboMode:
 2306                 case PTP_DPC_CANON_EOS_StroboETTL2Metering:
 2307                 case PTP_DPC_CANON_EOS_ColorTemperature:
 2308                 case PTP_DPC_CANON_EOS_FixedMovie:
 2309                 case PTP_DPC_CANON_EOS_AutoPowerOff:
 2310                 case PTP_DPC_CANON_EOS_AloMode:
 2311                 case PTP_DPC_CANON_EOS_LvViewTypeSelect:
 2312                 case PTP_DPC_CANON_EOS_EVFColorTemp:
 2313                 case PTP_DPC_CANON_EOS_LvAfSystem:
 2314                 case PTP_DPC_CANON_EOS_OneShotRawOn:
 2315                 case PTP_DPC_CANON_EOS_FlashChargingState:
 2316                     dpd->DataType = PTP_DTC_UINT32;
 2317                     break;
 2318                 /* enumeration for AEM is never provided, but is available to set */
 2319                 case PTP_DPC_CANON_EOS_AEModeDial:
 2320                 case PTP_DPC_CANON_EOS_AutoExposureMode:
 2321                     dpd->DataType = PTP_DTC_UINT16;
 2322                     dpd->FormFlag = PTP_DPFF_Enumeration;
 2323                     dpd->FORM.Enum.NumberOfValues = 0;
 2324                     break;
 2325                 case PTP_DPC_CANON_EOS_Aperture:
 2326                 case PTP_DPC_CANON_EOS_ShutterSpeed:
 2327                 case PTP_DPC_CANON_EOS_ISOSpeed:
 2328                 case PTP_DPC_CANON_EOS_FocusMode:
 2329                 case PTP_DPC_CANON_EOS_ColorSpace:
 2330                 case PTP_DPC_CANON_EOS_BatteryPower:
 2331                 case PTP_DPC_CANON_EOS_BatterySelect:
 2332                 case PTP_DPC_CANON_EOS_PTPExtensionVersion:
 2333                 case PTP_DPC_CANON_EOS_DriveMode:
 2334                 case PTP_DPC_CANON_EOS_AEB:
 2335                 case PTP_DPC_CANON_EOS_BracketMode:
 2336                 case PTP_DPC_CANON_EOS_QuickReviewTime:
 2337                 case PTP_DPC_CANON_EOS_EVFMode:
 2338                 case PTP_DPC_CANON_EOS_EVFOutputDevice:
 2339                 case PTP_DPC_CANON_EOS_EVFRecordStatus:
 2340                 case PTP_DPC_CANON_EOS_HighISOSettingNoiseReduction:
 2341                 case PTP_DPC_CANON_EOS_MultiAspect: /* actually a 32bit value, but lets try it for easyness */
 2342                     dpd->DataType = PTP_DTC_UINT16;
 2343                     break;
 2344                 case PTP_DPC_CANON_EOS_PictureStyle:
 2345                 case PTP_DPC_CANON_EOS_WhiteBalance:
 2346                 case PTP_DPC_CANON_EOS_MeteringMode:
 2347                 case PTP_DPC_CANON_EOS_ExpCompensation:
 2348                     dpd->DataType = PTP_DTC_UINT8;
 2349                     break;
 2350                 case PTP_DPC_CANON_EOS_Owner:
 2351                 case PTP_DPC_CANON_EOS_Artist:
 2352                 case PTP_DPC_CANON_EOS_Copyright:
 2353                 case PTP_DPC_CANON_EOS_SerialNumber:
 2354                 case PTP_DPC_CANON_EOS_LensName:
 2355                 case PTP_DPC_CANON_EOS_CameraNickname:
 2356                     dpd->DataType = PTP_DTC_STR;
 2357                     break;
 2358                 case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
 2359                 case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
 2360                     dpd->DataType = PTP_DTC_INT32;
 2361                     break;
 2362                 /* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
 2363                 case PTP_DPC_CANON_EOS_DPOFVersion:
 2364                     dpd->DataType = PTP_DTC_UINT16;
 2365                     ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
 2366                     for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
 2367                         ptp_debug (params, "    %d: %02x", j, xdata[j]);
 2368                     break;
 2369                 case PTP_DPC_CANON_EOS_CustomFunc1:
 2370                 case PTP_DPC_CANON_EOS_CustomFunc2:
 2371                 case PTP_DPC_CANON_EOS_CustomFunc3:
 2372                 case PTP_DPC_CANON_EOS_CustomFunc4:
 2373                 case PTP_DPC_CANON_EOS_CustomFunc5:
 2374                 case PTP_DPC_CANON_EOS_CustomFunc6:
 2375                 case PTP_DPC_CANON_EOS_CustomFunc7:
 2376                 case PTP_DPC_CANON_EOS_CustomFunc8:
 2377                 case PTP_DPC_CANON_EOS_CustomFunc9:
 2378                 case PTP_DPC_CANON_EOS_CustomFunc10:
 2379                 case PTP_DPC_CANON_EOS_CustomFunc11:
 2380                     dpd->DataType = PTP_DTC_UINT8;
 2381                     ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint8", i ,proptype, size-PTP_ece_Prop_Val_Data);
 2382                     for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
 2383                         ptp_debug (params, "    %d: %02x", j, xdata[j]);
 2384                     /* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */
 2385                     xdata += 4;
 2386                     break;
 2387                 /* yet unknown 32bit props */
 2388                 case PTP_DPC_CANON_EOS_WftStatus:
 2389                 case PTP_DPC_CANON_EOS_LensStatus:
 2390                 case PTP_DPC_CANON_EOS_CardExtension:
 2391                 case PTP_DPC_CANON_EOS_TempStatus:
 2392                 case PTP_DPC_CANON_EOS_PhotoStudioMode:
 2393                 case PTP_DPC_CANON_EOS_DepthOfFieldPreview:
 2394                 case PTP_DPC_CANON_EOS_EVFSharpness:
 2395                 case PTP_DPC_CANON_EOS_EVFWBMode:
 2396                 case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
 2397                 case PTP_DPC_CANON_EOS_ExposureSimMode:
 2398                 case PTP_DPC_CANON_EOS_MovSize:
 2399                 case PTP_DPC_CANON_EOS_DepthOfField:
 2400                 case PTP_DPC_CANON_EOS_Brightness:
 2401                 case PTP_DPC_CANON_EOS_GPSLogCtrl:
 2402                 case PTP_DPC_CANON_EOS_GPSDeviceActive:
 2403                     dpd->DataType = PTP_DTC_UINT32;
 2404                     ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
 2405                     if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
 2406                         ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
 2407                     for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
 2408                         ptp_debug (params, "    %d: 0x%8x", j, dtoh32a(xdata+j*4));
 2409                     break;
 2410                 /* ImageFormat properties have to be ignored here, see special handling below */
 2411                 case PTP_DPC_CANON_EOS_ImageFormat:
 2412                 case PTP_DPC_CANON_EOS_ImageFormatCF:
 2413                 case PTP_DPC_CANON_EOS_ImageFormatSD:
 2414                 case PTP_DPC_CANON_EOS_ImageFormatExtHD:
 2415                 case PTP_DPC_CANON_EOS_CustomFuncEx:
 2416                 case PTP_DPC_CANON_EOS_FocusInfoEx:
 2417                     break;
 2418                 default:
 2419                     ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
 2420                     for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
 2421                         ptp_debug (params, "    %d: %02x", j, xdata[j]);
 2422                     break;
 2423                 }
 2424                 switch (dpd->DataType) {
 2425                 case PTP_DTC_UINT32:
 2426                     dpd->FactoryDefaultValue.u32    = dtoh32a(xdata);
 2427                     dpd->CurrentValue.u32       = dtoh32a(xdata);
 2428                     ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
 2429                     break;
 2430                 case PTP_DTC_INT16:
 2431                     dpd->FactoryDefaultValue.i16    = dtoh16a(xdata);
 2432                     dpd->CurrentValue.i16       = dtoh16a(xdata);
 2433                     ptp_debug (params,"event %d: currentvalue of %x is %d", i, proptype, dpd->CurrentValue.i16);
 2434                     break;
 2435                 case PTP_DTC_UINT16:
 2436                     dpd->FactoryDefaultValue.u16    = dtoh16a(xdata);
 2437                     dpd->CurrentValue.u16       = dtoh16a(xdata);
 2438                     ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
 2439                     break;
 2440                 case PTP_DTC_UINT8:
 2441                     dpd->FactoryDefaultValue.u8 = dtoh8a(xdata);
 2442                     dpd->CurrentValue.u8        = dtoh8a(xdata);
 2443                     ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
 2444                     break;
 2445                 case PTP_DTC_INT8:
 2446                     dpd->FactoryDefaultValue.i8 = dtoh8a(xdata);
 2447                     dpd->CurrentValue.i8        = dtoh8a(xdata);
 2448                     ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.i8);
 2449                     break;
 2450                 case PTP_DTC_STR: {
 2451 #if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
 2452                     uint8_t len = 0;
 2453                     dpd->FactoryDefaultValue.str    = ptp_unpack_string(params, data, 0, &len);
 2454                     dpd->CurrentValue.str       = ptp_unpack_string(params, data, 0, &len);
 2455 #else
 2456                     free (dpd->FactoryDefaultValue.str);
 2457                     dpd->FactoryDefaultValue.str    = strdup( (char*)xdata );
 2458 
 2459                     free (dpd->CurrentValue.str);
 2460                     dpd->CurrentValue.str       = strdup( (char*)xdata );
 2461 #endif
 2462                     ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
 2463                     break;
 2464                 }
 2465                 default:
 2466                     /* debug is printed in switch above this one */
 2467                     break;
 2468                 }
 2469 
 2470                 /* ImageFormat and customFuncEx special handling (WARNING: dont move this in front of the dpd->DataType switch!) */
 2471                 switch (proptype) {
 2472                 case PTP_DPC_CANON_EOS_ImageFormat:
 2473                 case PTP_DPC_CANON_EOS_ImageFormatCF:
 2474                 case PTP_DPC_CANON_EOS_ImageFormatSD:
 2475                 case PTP_DPC_CANON_EOS_ImageFormatExtHD:
 2476                     dpd->DataType = PTP_DTC_UINT16;
 2477                     dpd->FactoryDefaultValue.u16    = ptp_unpack_EOS_ImageFormat( params, &xdata );
 2478                     dpd->CurrentValue.u16       = dpd->FactoryDefaultValue.u16;
 2479                     ptp_debug (params,"event %d: decoded imageformat, currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
 2480                     break;
 2481                 case PTP_DPC_CANON_EOS_CustomFuncEx:
 2482                     dpd->DataType = PTP_DTC_STR;
 2483                     free (dpd->FactoryDefaultValue.str);
 2484                     free (dpd->CurrentValue.str);
 2485                     dpd->FactoryDefaultValue.str    = ptp_unpack_EOS_CustomFuncEx( params, &xdata );
 2486                     dpd->CurrentValue.str       = strdup( (char*)dpd->FactoryDefaultValue.str );
 2487                     ptp_debug (params,"event %d: decoded custom function, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
 2488                     break;
 2489                 case PTP_DPC_CANON_EOS_FocusInfoEx:
 2490                     dpd->DataType = PTP_DTC_STR;
 2491                     free (dpd->FactoryDefaultValue.str);
 2492                     free (dpd->CurrentValue.str);
 2493                     dpd->FactoryDefaultValue.str    = ptp_unpack_EOS_FocusInfoEx( params, &xdata, size );
 2494                     dpd->CurrentValue.str       = strdup( (char*)dpd->FactoryDefaultValue.str );
 2495                     ptp_debug (params,"event %d: decoded focus info, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
 2496                     break;
 2497                 }
 2498             }
 2499             break;
 2500         /* one more information record handed to us */
 2501         /* Versions seen: (d199)
 2502          * 100D:    7 (original reference)
 2503          * 5d Mark 3:   7
 2504          * 650D:    7
 2505          * 6D:      7
 2506          * M10:     8
 2507          * 70D:     8
 2508          * 5Dsr:    b
 2509          * 200D:    f
 2510          * EOS R:   0x11
 2511          * EOS M6 Mark2 0x12
 2512          * EOS R5:  0x13
 2513          */
 2514         case PTP_EC_CANON_EOS_OLCInfoChanged: {
 2515             uint32_t        len, curoff;
 2516             uint16_t        mask,proptype;
 2517             PTPDevicePropDesc   *dpd;
 2518             int         olcver = 0;
 2519 
 2520             dpd = _lookup_or_allocate_canon_prop(params, PTP_DPC_CANON_EOS_OLCInfoVersion);
 2521             if (dpd) {
 2522                 ptp_debug (params, "olcinfoversion is %d", dpd->CurrentValue.u32);
 2523                 olcver = dpd->CurrentValue.u32;
 2524             }
 2525 
 2526             /* unclear what OLC stands for */
 2527             ptp_debug (params, "event %d: EOS event OLCInfoChanged (size %d)", i, size);
 2528             if (size >= 0x8) {  /* event info */
 2529                 unsigned int k;
 2530                 for (k=8;k<size;k++)
 2531                     ptp_debug (params, "    %d: %02x", k-8, curdata[k]);
 2532             }
 2533             len = dtoh32a(curdata+8);
 2534             if ((len != size-8) && (len != size-4)) {
 2535                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2536                 ce[i].u.info = strdup("OLC size unexpected");
 2537                 ptp_debug (params, "event %d: OLC unexpected size %d for blob len %d (not -4 nor -8)", i, size, len);
 2538                 break;
 2539             }
 2540             mask = dtoh16a(curdata+8+4);
 2541             if (size < 14) {
 2542                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2543                 ce[i].u.info = strdup("OLC size too small");
 2544                 ptp_debug (params, "event %d: OLC unexpected size %d", i, size);
 2545                 break;
 2546             }
 2547             curoff = 8+4+4;
 2548             if (mask & CANON_EOS_OLC_BUTTON) {
 2549                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2550                 ce[i].u.info = malloc(strlen("Button 1234567"));
 2551                 sprintf(ce[i].u.info, "Button %d",  dtoh16a(curdata+curoff));
 2552                 i++;
 2553                 curoff += 2; /* 7, 8 , f */
 2554             }
 2555 
 2556             if (mask & CANON_EOS_OLC_SHUTTERSPEED) {
 2557                 /* 6 bytes: 01 01 98 10 00 60 */
 2558                 /* this seem to be the shutter speed record */
 2559                 /* EOS 200D seems to have 7 bytes here, sample:
 2560                  * 7 bytes: 01 03 98 10 00 70 00
 2561                  * EOS R also 7 bytes
 2562                  * 7 bytes: 01 01 a0 0c 00 0c 00
 2563                  */
 2564                 proptype = PTP_DPC_CANON_EOS_ShutterSpeed;
 2565                 dpd = _lookup_or_allocate_canon_prop(params, proptype);
 2566                 dpd->CurrentValue.u16 = curdata[curoff+5]; /* just use last byte */
 2567 
 2568                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
 2569                 ce[i].u.propid = proptype;
 2570                 /* hack to differ between older EOS and EOS 200D newer */
 2571                 switch (olcver) {
 2572                 case 0xf:
 2573                 case 0x11:
 2574                 case 0x12:
 2575                 case 0x13:
 2576                     curoff += 7;    /* f (200D), 8 (M10) ???, 11 is EOS R , 12 is EOS m6 Mark2*/
 2577                     break;
 2578                 case 0x7:
 2579                 case 0x8: /* EOS 70D */
 2580                 case 0xb: /* EOS 5Ds */
 2581                     curoff += 6;    /* 7 , b (5ds) */
 2582                     break;
 2583                 default:
 2584                     if (olcver >= 0xf)
 2585                         curoff += 7;
 2586                     else
 2587                         curoff += 6;
 2588                     break;
 2589                 }
 2590                 i++;
 2591             }
 2592             if (mask & CANON_EOS_OLC_APERTURE) {
 2593                 /* 5 bytes: 01 01 5b 30 30 */
 2594                 /* this seem to be the aperture record */
 2595                 /* EOS 200D seems to have 6 bytes here?
 2596                  * 6 bytes: 01 01 50 20 20 00 *
 2597                  * EOS M6 Mark 2:
 2598                  * 9 bytes: 01 03 00 58 00 2d 00 30 00
 2599                  */
 2600                 proptype = PTP_DPC_CANON_EOS_Aperture;
 2601                 dpd = _lookup_or_allocate_canon_prop(params, proptype);
 2602                 if (olcver >= 0x12)
 2603                     dpd->CurrentValue.u16 = curdata[curoff+5]; /* CHECK */
 2604                 else
 2605                     dpd->CurrentValue.u16 = curdata[curoff+4]; /* just use last byte */
 2606 
 2607                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
 2608                 ce[i].u.propid = proptype;
 2609                 if (olcver >= 0x12) {
 2610                     curoff += 9;    /* m6 mark 2, r5 */
 2611                 } else {
 2612                     if (olcver >= 0xf) {
 2613                         curoff += 6;    /* f, 11 */
 2614                     } else {
 2615                         curoff += 5;    /* 7, 8, b */
 2616                     }
 2617                 }
 2618                 i++;
 2619             }
 2620             if (mask & CANON_EOS_OLC_ISO) {
 2621                 /* 4 bytes: 01 01 00 78 */
 2622                 /* EOS M6 Mark2: 01 01 00 6b 68 28 */
 2623                 /* this seem to be the ISO record */
 2624                 proptype = PTP_DPC_CANON_EOS_ISOSpeed;
 2625                 dpd = _lookup_or_allocate_canon_prop(params, proptype);
 2626                 dpd->CurrentValue.u16 = curdata[curoff+3]; /* just use last byte */
 2627 
 2628                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
 2629                 ce[i].u.propid = proptype;
 2630                 if (curoff >= 0x12)
 2631                     curoff += 6;    /* m6 mark 2 */
 2632                 else
 2633                     curoff += 4;    /* 7, 8, b, f*/
 2634                 i++;
 2635             }
 2636             if (mask & 0x0010) {
 2637                 /* mask 0x0010: 4 bytes, 04 00 00 00 observed */
 2638                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2639                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0010 content 01234567")+1);
 2640                 sprintf(ce[i].u.info,"OLCInfo event 0x0010 content %02x%02x%02x%02x",
 2641                     curdata[curoff],
 2642                     curdata[curoff+1],
 2643                     curdata[curoff+2],
 2644                     curdata[curoff+3]
 2645                 );
 2646                 curoff += 4;
 2647                 i++;
 2648             }
 2649             if (mask & 0x0020) {
 2650                 /* mask 0x0020: 6 bytes, 00 00 00 00 00 00 observed.
 2651                  * This seems to be the self-timer record: when active,
 2652                  * has the form of 00 00 01 00 XX XX, where the last two bytes
 2653                  * stand for the number of seconds remaining until the shot */
 2654                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2655                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0020 content 0123456789ab")+1);
 2656                 sprintf(ce[i].u.info,"OLCInfo event 0x0020 content %02x%02x%02x%02x%02x%02x",
 2657                     curdata[curoff],
 2658                     curdata[curoff+1],
 2659                     curdata[curoff+2],
 2660                     curdata[curoff+3],
 2661                     curdata[curoff+4],
 2662                     curdata[curoff+5]
 2663                 );
 2664                 curoff += 6;
 2665                 i++;
 2666             }
 2667             if (mask & 0x0040) {
 2668                 int value = (signed char)curdata[curoff+2];
 2669                 /* mask 0x0040: 7 bytes, 01 01 00 00 00 00 00 observed */
 2670                 /* exposure indicator */
 2671                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2672                 ce[i].u.info = malloc(strlen("OLCInfo exposure indicator 012345678901234567890123456789abcd")+1);
 2673                 sprintf(ce[i].u.info,"OLCInfo exposure indicator %d,%d,%d.%d (%02x%02x%02x%02x)",
 2674                     curdata[curoff],
 2675                     curdata[curoff+1],
 2676                     value/10,abs(value)%10,
 2677                     curdata[curoff+3],
 2678                     curdata[curoff+4],
 2679                     curdata[curoff+5],
 2680                     curdata[curoff+6]
 2681                 );
 2682                 if (olcver >= 0x12) {
 2683                     curoff += 8;
 2684                 } else {
 2685                     curoff += 7;
 2686                 }
 2687                 i++;
 2688             }
 2689             if (mask & 0x0080) {
 2690                 /* mask 0x0080: 4 bytes, 00 00 00 00 observed */
 2691                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2692                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0080 content 01234567")+1);
 2693                 sprintf(ce[i].u.info,"OLCInfo event 0x0080 content %02x%02x%02x%02x",
 2694                     curdata[curoff],
 2695                     curdata[curoff+1],
 2696                     curdata[curoff+2],
 2697                     curdata[curoff+3]
 2698                 );
 2699                 curoff += 4;
 2700                 i++;
 2701             }
 2702             if (mask & 0x0100) {
 2703                 /* mask 0x0100: 6 bytes, 00 00 00 00 00 00 (before focus) and 00 00 00 00 01 00 (on focus) observed */
 2704                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSINFO;
 2705                 ce[i].u.info = malloc(strlen("0123456789ab")+1);
 2706                 sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x",
 2707                     curdata[curoff],
 2708                     curdata[curoff+1],
 2709                     curdata[curoff+2],
 2710                     curdata[curoff+3],
 2711                     curdata[curoff+4],
 2712                     curdata[curoff+5]
 2713                 );
 2714                 if (olcver >= 0x12)
 2715                     curoff += 7;
 2716                 else
 2717                     curoff += 6;
 2718                 i++;
 2719             }
 2720             if (mask & 0x0200) {
 2721                 /* mask 0x0200: 7 bytes, 00 00 00 00 00 00 00 observed */
 2722                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSMASK;
 2723                 ce[i].u.info = malloc(strlen("0123456789abcd0123456789abcdef")+1);
 2724                 sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x%02x",
 2725                     curdata[curoff],
 2726                     curdata[curoff+1],
 2727                     curdata[curoff+2],
 2728                     curdata[curoff+3],
 2729                     curdata[curoff+4],
 2730                     curdata[curoff+5],
 2731                     curdata[curoff+6]
 2732                 );
 2733                 curoff += 7;
 2734                 i++;
 2735             }
 2736             if (mask & 0x0400) {
 2737                 /* mask 0x0400: 7 bytes, 00 00 00 00 00 00 00 observed */
 2738                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2739                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0400 content 0123456789abcd")+1);
 2740                 sprintf(ce[i].u.info,"OLCInfo event 0x0400 content %02x%02x%02x%02x%02x%02x%02x",
 2741                     curdata[curoff],
 2742                     curdata[curoff+1],
 2743                     curdata[curoff+2],
 2744                     curdata[curoff+3],
 2745                     curdata[curoff+4],
 2746                     curdata[curoff+5],
 2747                     curdata[curoff+6]
 2748                 );
 2749                 curoff += 7;
 2750                 i++;
 2751             }
 2752             if (mask & 0x0800) {
 2753                 /* mask 0x0800: 8 bytes, 00 00 00 00 00 00 00 00 and 19 01 00 00 00 00 00 00 and others observed */
 2754                 /*   might be mask of focus points selected */
 2755                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2756                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0800 content 0123456789abcdef")+1);
 2757                 sprintf(ce[i].u.info,"OLCInfo event 0x0800 content %02x%02x%02x%02x%02x%02x%02x%02x",
 2758                     curdata[curoff],
 2759                     curdata[curoff+1],
 2760                     curdata[curoff+2],
 2761                     curdata[curoff+3],
 2762                     curdata[curoff+4],
 2763                     curdata[curoff+5],
 2764                     curdata[curoff+6],
 2765                     curdata[curoff+7]
 2766                 );
 2767                 curoff += 8;
 2768                 i++;
 2769             }
 2770             if (mask & 0x1000) {
 2771                 /* mask 0x1000: 1 byte, 00 observed */
 2772                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2773                 ce[i].u.info = malloc(strlen("OLCInfo event 0x1000 content 01")+1);
 2774                 sprintf(ce[i].u.info,"OLCInfo event 0x1000 content %02x",
 2775                     curdata[curoff]
 2776                 );
 2777                 curoff += 1;
 2778                 i++;
 2779             }
 2780             /* handle more masks */
 2781             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2782             ce[i].u.info = malloc(strlen("OLCInfo event mask 0123456789")+1);
 2783             sprintf(ce[i].u.info, "OLCInfo event mask=%x",  mask);
 2784             break;
 2785         }
 2786         case PTP_EC_CANON_EOS_CameraStatusChanged:
 2787             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS;
 2788             ce[i].u.status =  dtoh32a(curdata+8);
 2789             ptp_debug (params, "event %d: EOS event CameraStatusChanged (size %d) = %d", i, size, dtoh32a(curdata+8));
 2790             params->eos_camerastatus = dtoh32a(curdata+8);
 2791             break;
 2792         case 0: /* end marker */
 2793             if (size == 8) /* no output */
 2794                 break;
 2795             ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
 2796             break;
 2797         case PTP_EC_CANON_EOS_BulbExposureTime:
 2798             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2799             ce[i].u.info = malloc(strlen("BulbExposureTime 123456789012345678"));
 2800             sprintf (ce[i].u.info, "BulbExposureTime %u",  dtoh32a(curdata+8));
 2801             break;
 2802         case PTP_EC_CANON_EOS_CTGInfoCheckComplete: /* some form of storage catalog ? */
 2803             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2804             ce[i].u.info = malloc(strlen("CTGInfoCheckComplete 0x012345678"));
 2805             sprintf (ce[i].u.info, "CTGInfoCheckComplete 0x%08x",  dtoh32a(curdata+8));
 2806             break;
 2807         case PTP_EC_CANON_EOS_StorageStatusChanged:
 2808             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2809             ce[i].u.info = malloc(strlen("StorageStatusChanged 0x012345678"));
 2810             sprintf (ce[i].u.info, "StorageStatusChanged 0x%08x",  dtoh32a(curdata+8));
 2811             break;
 2812         case PTP_EC_CANON_EOS_StorageInfoChanged:
 2813             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2814             ce[i].u.info = malloc(strlen("StorageInfoChanged 0x012345678"));
 2815             sprintf (ce[i].u.info, "StorageInfoChanged 0x%08x",  dtoh32a(curdata+8));
 2816             break;
 2817         case PTP_EC_CANON_EOS_StoreAdded:
 2818             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2819             ce[i].u.info = malloc(strlen("StoreAdded 0x012345678"));
 2820             sprintf (ce[i].u.info, "StoreAdded 0x%08x",  dtoh32a(curdata+8));
 2821             break;
 2822         case PTP_EC_CANON_EOS_StoreRemoved:
 2823             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2824             ce[i].u.info = malloc(strlen("StoreRemoved 0x012345678"));
 2825             sprintf (ce[i].u.info, "StoreRemoved 0x%08x",  dtoh32a(curdata+8));
 2826             break;
 2827         case PTP_EC_CANON_EOS_ObjectRemoved:
 2828             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTREMOVED;
 2829             ce[i].u.object.oid = dtoh32a(curdata+8);
 2830             break;
 2831         default:
 2832             switch (type) {
 2833 #define XX(x)       case PTP_EC_CANON_EOS_##x:                              \
 2834                 ptp_debug (params, "event %u: unhandled EOS event "#x" (size %u)", i, size);    \
 2835                 ce[i].u.info = malloc(strlen("unhandled EOS event "#x" (size 12345678901)")+1); \
 2836                 sprintf (ce[i].u.info, "unhandled EOS event "#x" (size %u)",  size);        \
 2837                 break;
 2838             XX(RequestGetEvent)
 2839             XX(RequestGetObjectInfoEx)
 2840             XX(ObjectInfoChangedEx)
 2841             XX(ObjectContentChanged)
 2842             XX(WillSoonShutdown)
 2843             XX(ShutdownTimerUpdated)
 2844             XX(RequestCancelTransfer)
 2845             XX(RequestObjectTransferDT)
 2846             XX(RequestCancelTransferDT)
 2847             XX(BulbExposureTime)
 2848             XX(RecordingTime)
 2849             XX(RequestObjectTransferTS)
 2850             XX(AfResult)
 2851             XX(PowerZoomInfoChanged)
 2852 #undef XX
 2853             default:
 2854                 ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
 2855                 break;
 2856             }
 2857             if (size >= 0x8) {  /* event info */
 2858                 unsigned int j;
 2859                 /*ptp_debug (params, "data=%p, curdata=%p, datsize=%d, size=%d", data, curdata, datasize, size);*/
 2860                 for (j=8;j<size;j++)
 2861                     ptp_debug (params, "    %d: %02x", j, curdata[j]);
 2862             }
 2863             ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
 2864             break;
 2865         }
 2866         curdata += size;
 2867         i++;
 2868         if (i >= entries) {
 2869             ptp_debug (params, "BAD: i %d, entries %d", i, entries);
 2870         }
 2871     }
 2872     if (!i) {
 2873         free (ce);
 2874         ce = NULL;
 2875     }
 2876     *pce = ce;
 2877     return i;
 2878 }
 2879 
 2880 /*
 2881     PTP USB Event container unpack for Nikon events.
 2882 */
 2883 #define PTP_nikon_ec_Length     0
 2884 #define PTP_nikon_ec_Code       2
 2885 #define PTP_nikon_ec_Param1     4
 2886 #define PTP_nikon_ec_Size       6
 2887 static inline void
 2888 ptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, unsigned int *cnt)
 2889 {
 2890     unsigned int i;
 2891 
 2892     *ec = NULL;
 2893     if (data == NULL)
 2894         return;
 2895     if (len < PTP_nikon_ec_Code)
 2896         return;
 2897     *cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
 2898     if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) { /* broken cnt? */
 2899         *cnt = 0;
 2900         return;
 2901     }
 2902     if (!*cnt)
 2903         return;
 2904 
 2905     *ec = calloc(sizeof(PTPContainer),(*cnt));
 2906 
 2907     for (i=0;i<*cnt;i++) {
 2908         memset(&(*ec)[i],0,sizeof(PTPContainer));
 2909         (*ec)[i].Code   = dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
 2910         (*ec)[i].Param1 = dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
 2911         (*ec)[i].Nparam = 1;
 2912     }
 2913 }
 2914 
 2915 /*
 2916  *  PTP USB Event container unpack for Nikon events, 2nd generation.
 2917  */
 2918 #define PTP_nikon_ec_ex_Length      0
 2919 #define PTP_nikon_ec_ex_Code        2
 2920 
 2921 static inline int
 2922 ptp_unpack_Nikon_EC_EX (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, unsigned int *cnt)
 2923 {
 2924     unsigned int i, offset;
 2925 
 2926     *ec = NULL;
 2927     if (data == NULL)
 2928         return 0;
 2929     if (len < PTP_nikon_ec_ex_Code)
 2930         return 0;
 2931     *cnt = dtoh16a(&data[PTP_nikon_ec_ex_Length]);
 2932     if (*cnt > (len-PTP_nikon_ec_ex_Code)/4) { /* broken cnt? simple first check ... due to dynamic size, we need to do more later */
 2933         *cnt = 0;
 2934         return 0;
 2935     }
 2936     if (!*cnt)
 2937         return 1;
 2938 
 2939     *ec = calloc(sizeof(PTPContainer),(*cnt));
 2940     offset = PTP_nikon_ec_ex_Code+sizeof(uint16_t);
 2941 
 2942     for (i=0;i<*cnt;i++) {
 2943         memset(&(*ec)[i],0,sizeof(PTPContainer));
 2944         if (len - offset < 4) {
 2945             free (*ec);
 2946             *ec = NULL;
 2947             *cnt = 0;
 2948             return 0;
 2949         }
 2950         (*ec)[i].Code   = dtoh16a(&data[offset]);
 2951         (*ec)[i].Nparam = dtoh16a(&data[offset+2]);
 2952         ptp_debug (params, "nikon eventex %d: code 0x%04x, params %d", i, (*ec)[i].Code, (*ec)[i].Nparam);
 2953         if (    ((*ec)[i].Nparam > 5)                   ||
 2954             (len < ((*ec)[i].Nparam*sizeof(uint32_t)) + 4 + offset)
 2955         ) {
 2956             free (*ec);
 2957             *ec = NULL;
 2958             *cnt = 0;
 2959             return 0;
 2960         }
 2961         switch ((*ec)[i].Nparam) {
 2962         case 5: (*ec)[i].Param5 = dtoh32a(&data[offset+4+sizeof(uint32_t)*4]);/* fallthrough */
 2963         case 4: (*ec)[i].Param4 = dtoh32a(&data[offset+4+sizeof(uint32_t)*3]);/* fallthrough */
 2964         case 3: (*ec)[i].Param3 = dtoh32a(&data[offset+4+sizeof(uint32_t)*2]);/* fallthrough */
 2965         case 2: (*ec)[i].Param2 = dtoh32a(&data[offset+4+sizeof(uint32_t)*1]);/* fallthrough */
 2966         case 1: (*ec)[i].Param1 = dtoh32a(&data[offset+4]);
 2967             /* fallthrough */
 2968         case 0: break;
 2969         }
 2970         offset += (*ec)[i].Nparam*sizeof(uint32_t) + 4;
 2971     }
 2972     return 1;
 2973 }
 2974 
 2975 static inline uint32_t
 2976 ptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
 2977     int i, len = 0;
 2978     uint8_t retlen;
 2979     unsigned char *curdata;
 2980 
 2981     len =   2*(strlen(text->title)+1)+1+
 2982         2*(strlen(text->line[0])+1)+1+
 2983         2*(strlen(text->line[1])+1)+1+
 2984         2*(strlen(text->line[2])+1)+1+
 2985         2*(strlen(text->line[3])+1)+1+
 2986         2*(strlen(text->line[4])+1)+1+
 2987         4*2+2*4+2+4+2+5*4*2;
 2988     *data = malloc(len);
 2989     if (!*data) return 0;
 2990 
 2991     curdata = *data;
 2992     htod16a(curdata,100);curdata+=2;
 2993     htod16a(curdata,1);curdata+=2;
 2994     htod16a(curdata,0);curdata+=2;
 2995     htod16a(curdata,1000);curdata+=2;
 2996 
 2997     htod32a(curdata,0);curdata+=4;
 2998     htod32a(curdata,0);curdata+=4;
 2999 
 3000     htod16a(curdata,6);curdata+=2;
 3001     htod32a(curdata,0);curdata+=4;
 3002 
 3003     ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
 3004     htod16a(curdata,0x10);curdata+=2;
 3005 
 3006     for (i=0;i<5;i++) {
 3007         ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
 3008         htod16a(curdata,0x10);curdata+=2;
 3009         htod16a(curdata,0x01);curdata+=2;
 3010         htod16a(curdata,0x02);curdata+=2;
 3011         htod16a(curdata,0x06);curdata+=2;
 3012     }
 3013     return len;
 3014 }
 3015 
 3016 #define ptp_canon_dir_version   0x00
 3017 #define ptp_canon_dir_ofc   0x02
 3018 #define ptp_canon_dir_unk1  0x04
 3019 #define ptp_canon_dir_objectid  0x08
 3020 #define ptp_canon_dir_parentid  0x0c
 3021 #define ptp_canon_dir_previd    0x10    /* in same dir */
 3022 #define ptp_canon_dir_nextid    0x14    /* in same dir */
 3023 #define ptp_canon_dir_nextchild 0x18    /* down one dir */
 3024 #define ptp_canon_dir_storageid 0x1c    /* only in storage entry */
 3025 #define ptp_canon_dir_name  0x20
 3026 #define ptp_canon_dir_flags 0x2c
 3027 #define ptp_canon_dir_size  0x30
 3028 #define ptp_canon_dir_unixtime  0x34
 3029 #define ptp_canon_dir_year  0x38
 3030 #define ptp_canon_dir_month 0x39
 3031 #define ptp_canon_dir_mday  0x3a
 3032 #define ptp_canon_dir_hour  0x3b
 3033 #define ptp_canon_dir_minute    0x3c
 3034 #define ptp_canon_dir_second    0x3d
 3035 #define ptp_canon_dir_unk2  0x3e
 3036 #define ptp_canon_dir_thumbsize 0x40
 3037 #define ptp_canon_dir_width 0x44
 3038 #define ptp_canon_dir_height    0x48
 3039 
 3040 static inline uint16_t
 3041 ptp_unpack_canon_directory (
 3042     PTPParams       *params,
 3043     unsigned char       *dir,
 3044     uint32_t        cnt,
 3045     PTPObjectHandles    *handles,
 3046     PTPObjectInfo       **oinfos,   /* size(handles->n) */
 3047     uint32_t        **flags     /* size(handles->n) */
 3048 ) {
 3049     unsigned int    i, j, nrofobs = 0, curob = 0;
 3050 
 3051 #define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
 3052     for (i=0;i<cnt;i++)
 3053         if (ISOBJECT(dir+i*0x4c)) nrofobs++;
 3054     handles->n = nrofobs;
 3055     handles->Handler = calloc(nrofobs,sizeof(handles->Handler[0]));
 3056     if (!handles->Handler) return PTP_RC_GeneralError;
 3057     *oinfos = calloc(nrofobs,sizeof((*oinfos)[0]));
 3058     if (!*oinfos) return PTP_RC_GeneralError;
 3059     *flags  = calloc(nrofobs,sizeof((*flags)[0]));
 3060     if (!*flags) return PTP_RC_GeneralError;
 3061 
 3062     /* Migrate data into objects ids, handles into
 3063      * the object handler array.
 3064      */
 3065     curob = 0;
 3066     for (i=0;i<cnt;i++) {
 3067         unsigned char   *cur = dir+i*0x4c;
 3068         PTPObjectInfo   *oi = (*oinfos)+curob;
 3069 
 3070         if (!ISOBJECT(cur))
 3071             continue;
 3072 
 3073         handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
 3074         oi->StorageID       = 0xffffffff;
 3075         oi->ObjectFormat    = dtoh16a(cur + ptp_canon_dir_ofc);
 3076         oi->ParentObject    = dtoh32a(cur + ptp_canon_dir_parentid);
 3077         oi->Filename        = strdup((char*)(cur + ptp_canon_dir_name));
 3078         oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
 3079         oi->ThumbCompressedSize = dtoh32a(cur + ptp_canon_dir_thumbsize);
 3080         oi->ImagePixWidth   = dtoh32a(cur + ptp_canon_dir_width);
 3081         oi->ImagePixHeight  = dtoh32a(cur + ptp_canon_dir_height);
 3082         oi->CaptureDate     = oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
 3083         (*flags)[curob]     = dtoh32a(cur + ptp_canon_dir_flags);
 3084         curob++;
 3085     }
 3086     /* Walk over Storage ID entries and distribute the IDs to
 3087      * the parent objects. */
 3088     for (i=0;i<cnt;i++) {
 3089         unsigned char   *cur = dir+i*0x4c;
 3090         uint32_t    nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
 3091 
 3092         if (ISOBJECT(cur))
 3093             continue;
 3094         for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
 3095         if (j == handles->n) continue;
 3096         (*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
 3097     }
 3098     /* Walk over all objects and distribute the storage ids */
 3099     while (1) {
 3100         unsigned int changed = 0;
 3101         for (i=0;i<cnt;i++) {
 3102             unsigned char   *cur = dir+i*0x4c;
 3103             uint32_t    oid = dtoh32a(cur + ptp_canon_dir_objectid);
 3104             uint32_t    nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
 3105             uint32_t    nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
 3106             uint32_t    storageid;
 3107 
 3108             if (!ISOBJECT(cur))
 3109                 continue;
 3110             for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
 3111             if (j == handles->n) {
 3112                 /*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
 3113                 continue;
 3114             }
 3115             storageid = (*oinfos)[j].StorageID;
 3116             if (storageid == 0xffffffff) continue;
 3117             if (nextoid != 0xffffffff) {
 3118                 for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
 3119                 if (j == handles->n) {
 3120                     /*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
 3121                     continue;
 3122                 }
 3123                 if ((*oinfos)[j].StorageID == 0xffffffff) {
 3124                     (*oinfos)[j].StorageID = storageid;
 3125                     changed++;
 3126                 }
 3127             }
 3128             if (nextchild != 0xffffffff) {
 3129                 for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
 3130                 if (j == handles->n) {
 3131                     /*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
 3132                     continue;
 3133                 }
 3134                 if ((*oinfos)[j].StorageID == 0xffffffff) {
 3135                     (*oinfos)[j].StorageID = storageid;
 3136                     changed++;
 3137                 }
 3138             }
 3139         }
 3140         /* Check if we:
 3141          * - changed no entry (nothing more to do)
 3142          * - changed all of them at once (usually happens)
 3143          * break if we do.
 3144          */
 3145         if (!changed || (changed==nrofobs-1))
 3146             break;
 3147     }
 3148 #undef ISOBJECT
 3149     return PTP_RC_OK;
 3150 }
 3151 
 3152 static inline int
 3153 ptp_unpack_ptp11_manifest (
 3154     PTPParams       *params,
 3155     unsigned char       *data,
 3156     unsigned int        datalen,
 3157     uint64_t        *numoifs,
 3158     PTPObjectFilesystemInfo **oifs
 3159 ) {
 3160     uint64_t        numberoifs, i;
 3161     unsigned int        curoffset;
 3162     PTPObjectFilesystemInfo *xoifs;
 3163 
 3164     if (datalen < 8)
 3165         return 0;
 3166     numberoifs = dtoh64ap(params,data);
 3167     curoffset = 8;
 3168     xoifs = calloc(sizeof(PTPObjectFilesystemInfo),numberoifs);
 3169     if (!xoifs)
 3170         return 0;
 3171 
 3172     for (i = 0; i < numberoifs; i++) {
 3173         uint8_t len,dlen;
 3174         char *modify_date;
 3175         PTPObjectFilesystemInfo *oif = xoifs+i;
 3176 
 3177         if (curoffset + 34 + 2 > datalen)
 3178             goto tooshort;
 3179 
 3180         oif->ObjectHandle       = dtoh32ap(params,data+curoffset);
 3181         oif->StorageID          = dtoh32ap(params,data+curoffset+4);
 3182         oif->ObjectFormat       = dtoh16ap(params,data+curoffset+8);
 3183         oif->ProtectionStatus       = dtoh16ap(params,data+curoffset+10);
 3184         oif->ObjectCompressedSize64     = dtoh64ap(params,data+curoffset+12);
 3185         oif->ParentObject       = dtoh32ap(params,data+curoffset+20);
 3186         oif->AssociationType        = dtoh16ap(params,data+curoffset+24);
 3187         oif->AssociationDesc        = dtoh32ap(params,data+curoffset+26);
 3188         oif->SequenceNumber         = dtoh32ap(params,data+curoffset+30);
 3189         if (!ptp_unpack_string(params, data, curoffset+34, datalen, &len, &oif->Filename))
 3190             goto tooshort;
 3191         if (curoffset+34+len*2+1 > datalen)
 3192             goto tooshort;
 3193 
 3194         if (!ptp_unpack_string(params, data, curoffset+len*2+1+34, datalen, &dlen, &modify_date))
 3195             goto tooshort;
 3196 
 3197         oif->ModificationDate       = ptp_unpack_PTPTIME(modify_date);
 3198         free(modify_date);
 3199         curoffset += 34+len*2+dlen*2+2;
 3200     }
 3201     *numoifs = numberoifs;
 3202     *oifs = xoifs;
 3203     return 1;
 3204 tooshort:
 3205     for (i = 0; i < numberoifs; i++)
 3206         if (xoifs[i].Filename) free (xoifs[i].Filename);
 3207     free (xoifs);
 3208     return 0;
 3209 }
 3210 
 3211 static inline void
 3212 ptp_unpack_chdk_lv_data_header (PTPParams *params, unsigned char* data, lv_data_header *header)
 3213 {
 3214     int off = 0;
 3215     if (data==NULL)
 3216         return;
 3217     header->version_major = dtoh32a(&data[off]);
 3218     header->version_minor = dtoh32a(&data[off+=4]);
 3219     header->lcd_aspect_ratio = dtoh32a(&data[off+=4]);
 3220     header->palette_type = dtoh32a(&data[off+=4]);
 3221     header->palette_data_start = dtoh32a(&data[off+=4]);
 3222     header->vp_desc_start = dtoh32a(&data[off+=4]);
 3223     header->bm_desc_start = dtoh32a(&data[off+=4]);
 3224     if (header->version_minor > 1)
 3225         header->bmo_desc_start = dtoh32a(&data[off+=4]);
 3226 }
 3227 
 3228 static inline void
 3229 ptp_unpack_chdk_lv_framebuffer_desc (PTPParams *params, unsigned char* data, lv_framebuffer_desc *fd)
 3230 {
 3231     int off = 0;
 3232     if (data==NULL)
 3233         return;
 3234     fd->fb_type = dtoh32a(&data[off]);
 3235     fd->data_start = dtoh32a(&data[off+=4]);
 3236     fd->buffer_width = dtoh32a(&data[off+=4]);
 3237     fd->visible_width = dtoh32a(&data[off+=4]);
 3238     fd->visible_height = dtoh32a(&data[off+=4]);
 3239     fd->margin_left = dtoh32a(&data[off+=4]);
 3240     fd->margin_top = dtoh32a(&data[off+=4]);
 3241     fd->margin_right = dtoh32a(&data[off+=4]);
 3242     fd->margin_bot = dtoh32a(&data[off+=4]);
 3243 }
 3244 
 3245 static inline int
 3246 ptp_unpack_StreamInfo (PTPParams *params, unsigned char *data, PTPStreamInfo *si, unsigned int size) {
 3247     if (!data) return PTP_RC_GeneralError;
 3248     if (size < 36) return PTP_RC_GeneralError;
 3249 
 3250     si->DatasetSize     = dtoh64ap(params,data+0);
 3251     si->TimeResolution  = dtoh64ap(params,data+8);
 3252     si->FrameHeaderSize = dtoh32ap(params,data+16);
 3253     si->FrameMaxSize    = dtoh32ap(params,data+20);
 3254     si->PacketHeaderSize    = dtoh32ap(params,data+24);
 3255     si->PacketMaxSize   = dtoh32ap(params,data+28);
 3256     si->PacketAlignment = dtoh32ap(params,data+32);
 3257     return PTP_RC_OK;
 3258 }