Code Sync up from tizen_2.4
[platform/upstream/libmtp.git] / src / ptp-pack.c
1 /* ptp-pack.c
2  *
3  * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
4  * Copyright (C) 2003-2012 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 #ifdef HAVE_ICONV
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 static inline char*
130 ptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
131 {
132         uint8_t length;
133         uint16_t string[PTP_MAXSTRLEN+1];
134         /* allow for UTF-8: max of 3 bytes per UCS-2 char, plus final null */
135         char loclstr[PTP_MAXSTRLEN*3+1];
136         size_t nconv, srclen, destlen;
137         char *src, *dest;
138
139         length = dtoh8a(&data[offset]); /* PTP_MAXSTRLEN == 255, 8 bit len */
140         *len = length;
141         if (length == 0)                /* nothing to do? */
142                 return(NULL);
143
144         /* copy to string[] to ensure correct alignment for iconv(3) */
145         memcpy(string, &data[offset+1], length * sizeof(string[0]));
146         string[length] = 0x0000U;   /* be paranoid!  add a terminator. */
147         loclstr[0] = '\0';
148
149         /* convert from camera UCS-2 to our locale */
150         src = (char *)string;
151         srclen = length * sizeof(string[0]);
152         dest = loclstr;
153         destlen = sizeof(loclstr)-1;
154         nconv = (size_t)-1;
155 #ifdef HAVE_ICONV
156         if (params->cd_ucs2_to_locale != (iconv_t)-1)
157                 nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen, &dest, &destlen);
158 #endif
159         if (nconv == (size_t) -1) { /* do it the hard way */
160                 int i;
161                 /* try the old way, in case iconv is broken */
162                 for (i=0;i<length;i++) {
163                         if (dtoh16a(&data[offset+1+2*i])>127)
164                                 loclstr[i] = '?';
165                         else
166                                 loclstr[i] = dtoh16a(&data[offset+1+2*i]);
167                 }
168                 dest = loclstr+length;
169         }
170         *dest = '\0';
171         loclstr[sizeof(loclstr)-1] = '\0';   /* be safe? */
172         return(strdup(loclstr));
173 }
174
175 static inline int
176 ucs2strlen(uint16_t const * const unicstr)
177 {
178         int length = 0;
179         
180         /* Unicode strings are terminated with 2 * 0x00 */
181         for(length = 0; unicstr[length] != 0x0000U; length ++);
182         return length;
183 }
184
185
186 static inline void
187 ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
188 {
189         int packedlen = 0;
190         uint16_t ucs2str[PTP_MAXSTRLEN+1];
191         char *ucs2strp = (char *) ucs2str;
192         size_t convlen = strlen(string);
193
194         /* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
195         memset(ucs2strp, 0, sizeof(ucs2str));  /* XXX: necessary? */
196 #ifdef HAVE_ICONV
197         if (params->cd_locale_to_ucs2 != (iconv_t)-1) {
198                 size_t nconv;
199                 size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
200                 char *stringp = string;
201
202                 nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
203                         &ucs2strp, &convmax);
204                 if (nconv == (size_t) -1)
205                         ucs2str[0] = 0x0000U;
206         } else
207 #endif
208         {
209                 unsigned int i;
210
211                 for (i=0;i<convlen;i++) {
212                         ucs2str[i] = string[i];
213                 }
214                 ucs2str[convlen] = 0;
215         }
216         /*
217          * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
218          *      why do we need ucs2strlen()?
219          */
220         packedlen = ucs2strlen(ucs2str);
221         if (packedlen > PTP_MAXSTRLEN-1) {
222                 *len=0;
223                 return;
224         }
225         
226         /* number of characters including terminating 0 (PTP standard confirmed) */
227         htod8a(&data[offset],packedlen+1);
228         memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
229         htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
230
231         /* The returned length is in number of characters */
232         *len = (uint8_t) packedlen+1;
233 }
234
235 static inline unsigned char *
236 ptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
237 {
238         uint8_t packed[PTP_MAXSTRLEN*2+3], len;
239         size_t plen;
240         unsigned char *retcopy = NULL;
241   
242         if (string == NULL)
243           ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
244         else
245           ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
246   
247         /* returned length is in characters, then one byte for string length */
248         plen = len*2 + 1;
249         
250         retcopy = malloc(plen);
251         if (!retcopy) {
252                 *packed_size = 0;
253                 return NULL;
254         }
255         memcpy(retcopy, packed, plen);
256         *packed_size = plen;
257         return (retcopy);
258 }
259
260 static inline uint32_t
261 ptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
262 {
263         uint32_t n, i=0;
264
265         *array = NULL;
266         n=dtoh32a(&data[offset]);
267         if (n >= UINT_MAX/sizeof(uint32_t))
268                 return 0;
269         if (!n)
270                 return 0;
271         *array = malloc (n*sizeof(uint32_t));
272         for (i=0;i<n;i++)
273                 (*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
274         return n;
275 }
276
277 static inline uint32_t
278 ptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
279 {
280         uint32_t i=0;
281
282         *data = malloc ((arraylen+1)*sizeof(uint32_t));
283         htod32a(&(*data)[0],arraylen);
284         for (i=0;i<arraylen;i++)
285                 htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
286         return (arraylen+1)*sizeof(uint32_t);
287 }
288
289 static inline uint32_t
290 ptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
291 {
292         uint32_t n, i=0;
293
294         *array = NULL;
295         n=dtoh32a(&data[offset]);
296         if (n >= UINT_MAX/sizeof(uint16_t))
297                 return 0;
298         if (!n)
299                 return 0;
300         *array = malloc (n*sizeof(uint16_t));
301         for (i=0;i<n;i++)
302                 (*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
303         return n;
304 }
305
306 /* DeviceInfo pack/unpack */
307
308 #define PTP_di_StandardVersion           0
309 #define PTP_di_VendorExtensionID         2
310 #define PTP_di_VendorExtensionVersion    6
311 #define PTP_di_VendorExtensionDesc       8
312 #define PTP_di_FunctionalMode            8
313 #define PTP_di_OperationsSupported      10
314
315 static inline void
316 ptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
317 {
318         uint8_t len;
319         unsigned int totallen;
320
321         if (!data) return;
322         if (datalen < 12) return;
323         di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
324         di->VendorExtensionID =
325                 dtoh32a(&data[PTP_di_VendorExtensionID]);
326         di->VendorExtensionVersion =
327                 dtoh16a(&data[PTP_di_VendorExtensionVersion]);
328         di->VendorExtensionDesc = 
329                 ptp_unpack_string(params, data,
330                 PTP_di_VendorExtensionDesc, &len); 
331         totallen=len*2+1;
332         di->FunctionalMode = 
333                 dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
334         di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
335                 PTP_di_OperationsSupported+totallen,
336                 &di->OperationsSupported);
337         totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
338         di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
339                 PTP_di_OperationsSupported+totallen,
340                 &di->EventsSupported);
341         totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
342         di->DevicePropertiesSupported_len =
343                 ptp_unpack_uint16_t_array(params, data,
344                 PTP_di_OperationsSupported+totallen,
345                 &di->DevicePropertiesSupported);
346         totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
347         di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
348                 PTP_di_OperationsSupported+totallen,
349                 &di->CaptureFormats);
350         totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
351         di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
352                 PTP_di_OperationsSupported+totallen,
353                 &di->ImageFormats);
354         totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
355         di->Manufacturer = ptp_unpack_string(params, data,
356                 PTP_di_OperationsSupported+totallen,
357                 &len);
358         totallen+=len*2+1;
359         di->Model = ptp_unpack_string(params, data,
360                 PTP_di_OperationsSupported+totallen,
361                 &len);
362         totallen+=len*2+1;
363         di->DeviceVersion = ptp_unpack_string(params, data,
364                 PTP_di_OperationsSupported+totallen,
365                 &len);
366         totallen+=len*2+1;
367         di->SerialNumber = ptp_unpack_string(params, data,
368                 PTP_di_OperationsSupported+totallen,
369                 &len);
370 }
371
372 inline static void
373 ptp_free_DI (PTPDeviceInfo *di) {
374         if (di->SerialNumber) free (di->SerialNumber);
375         if (di->DeviceVersion) free (di->DeviceVersion);
376         if (di->Model) free (di->Model);
377         if (di->Manufacturer) free (di->Manufacturer);
378         if (di->ImageFormats) free (di->ImageFormats);
379         if (di->CaptureFormats) free (di->CaptureFormats);
380         if (di->VendorExtensionDesc) free (di->VendorExtensionDesc);
381         if (di->OperationsSupported) free (di->OperationsSupported);
382         if (di->EventsSupported) free (di->EventsSupported);
383         if (di->DevicePropertiesSupported) free (di->DevicePropertiesSupported);
384 }
385
386 /* EOS Device Info unpack */
387 static inline void
388 ptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
389 {
390         unsigned int totallen = 4;
391
392         memset (di,0, sizeof(*di));
393         if (datalen < 8) return;
394
395         /* uint32_t struct len - ignore */
396         di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
397                 totallen, &di->EventsSupported);
398         if (!di->EventsSupported) return;
399         totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
400         if (totallen >= datalen) return;
401
402         di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
403                 totallen, &di->DevicePropertiesSupported);
404         if (!di->DevicePropertiesSupported) return;
405         totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
406         if (totallen >= datalen) return;
407
408         di->unk_len = ptp_unpack_uint32_t_array(params, data,
409                 totallen, &di->unk);
410         if (!di->unk) return;
411         totallen += di->unk_len*sizeof(uint32_t)+4;
412         return;
413 }
414
415 static inline void
416 ptp_free_EOS_DI (PTPCanonEOSDeviceInfo *di)
417 {
418         free (di->EventsSupported);
419         free (di->DevicePropertiesSupported);
420         free (di->unk);
421 }
422         
423 /* ObjectHandles array pack/unpack */
424
425 #define PTP_oh                           0
426
427 static inline void
428 ptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
429 {
430         if (len) {
431                 oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
432         } else {
433                 oh->n = 0;
434                 oh->Handler = NULL;
435         } 
436 }
437
438 /* StoreIDs array pack/unpack */
439
440 #define PTP_sids                         0
441
442 static inline void
443 ptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
444 {
445         if (!data || !len) {
446                 sids->n = 0;
447                 sids->Storage = NULL;
448                 return;
449         }
450         sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
451         &sids->Storage);
452 }
453
454 /* StorageInfo pack/unpack */
455
456 #define PTP_si_StorageType               0
457 #define PTP_si_FilesystemType            2
458 #define PTP_si_AccessCapability          4
459 #define PTP_si_MaxCapability             6
460 #define PTP_si_FreeSpaceInBytes         14
461 #define PTP_si_FreeSpaceInImages        22
462 #define PTP_si_StorageDescription       26
463
464 static inline void
465 ptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
466 {
467         uint8_t storagedescriptionlen;
468
469         si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
470         si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
471         si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
472         si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
473         si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
474         si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
475         si->StorageDescription=ptp_unpack_string(params, data,
476                 PTP_si_StorageDescription, &storagedescriptionlen);
477         si->VolumeLabel=ptp_unpack_string(params, data,
478                 PTP_si_StorageDescription+storagedescriptionlen*2+1,
479                 &storagedescriptionlen);
480 }
481
482 /* ObjectInfo pack/unpack */
483
484 #define PTP_oi_StorageID                 0
485 #define PTP_oi_ObjectFormat              4
486 #define PTP_oi_ProtectionStatus          6
487 #define PTP_oi_ObjectCompressedSize      8
488 #define PTP_oi_ThumbFormat              12
489 #define PTP_oi_ThumbCompressedSize      14
490 #define PTP_oi_ThumbPixWidth            18
491 #define PTP_oi_ThumbPixHeight           22
492 #define PTP_oi_ImagePixWidth            26
493 #define PTP_oi_ImagePixHeight           30
494 #define PTP_oi_ImageBitDepth            34
495 #define PTP_oi_ParentObject             38
496 #define PTP_oi_AssociationType          42
497 #define PTP_oi_AssociationDesc          44
498 #define PTP_oi_SequenceNumber           48
499 #define PTP_oi_filenamelen              52
500 #define PTP_oi_Filename                 53
501
502 /* the max length assuming zero length dates. We have need 3 */
503 /* bytes for these. */
504 #define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
505
506 static inline uint32_t
507 ptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
508 {
509         unsigned char* oidata;
510         uint8_t filenamelen;
511         uint8_t capturedatelen=0;
512         /* let's allocate some memory first; correct assuming zero length dates */
513         oidata=malloc(PTP_oi_MaxLen + params->ocs64*4);
514         *oidataptr=oidata;
515         /* the caller should free it after use! */
516 #if 0
517         char *capture_date="20020101T010101"; /* XXX Fake date */
518 #endif
519         memset (oidata, 0, PTP_oi_MaxLen + params->ocs64*4);
520         htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
521         htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
522         htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
523         htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
524         if (params->ocs64)
525                 oidata += 4;
526         htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
527         htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
528         htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
529         htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
530         htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
531         htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
532         htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
533         htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
534         htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
535         htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
536         htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
537         
538         ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
539 /*
540         filenamelen=(uint8_t)strlen(oi->Filename);
541         htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
542         for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
543                 req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
544         }
545 */
546         /*
547          *XXX Fake date.
548          * for example Kodak sets Capture date on the basis of EXIF data.
549          * Spec says that this field is from perspective of Initiator.
550          */
551 #if 0   /* seems now we don't need any data packed in OI dataset... for now ;)*/
552         capturedatelen=strlen(capture_date);
553         htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
554                 capturedatelen+1);
555         for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
556                 data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
557         }
558         htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
559                 capturedatelen+1);
560         for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
561                 data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
562                   capture_date[i];
563         }
564 #endif
565         /* XXX this function should return dataset length */
566         return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3)+params->ocs64*4;
567 }
568
569 static time_t
570 ptp_unpack_PTPTIME (const char *str) {
571         char ptpdate[40];
572         char tmp[5];
573         size_t  ptpdatelen;
574         struct tm tm;
575
576         if (!str)
577                 return 0;
578         ptpdatelen = strlen(str);
579         if (ptpdatelen >= sizeof (ptpdate)) {
580                 /*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
581                 return 0;
582         }
583         if (ptpdatelen<15) {
584                 /*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
585                 return 0;
586         }
587         strncpy (ptpdate, str, sizeof(ptpdate));
588         ptpdate[sizeof(ptpdate) - 1] = '\0';
589
590         memset(&tm,0,sizeof(tm));
591         strncpy (tmp, ptpdate, 4);
592         tmp[4] = 0;
593         tm.tm_year=atoi (tmp) - 1900;
594         strncpy (tmp, ptpdate + 4, 2);
595         tmp[2] = 0;
596         tm.tm_mon = atoi (tmp) - 1;
597         strncpy (tmp, ptpdate + 6, 2);
598         tmp[2] = 0;
599         tm.tm_mday = atoi (tmp);
600         strncpy (tmp, ptpdate + 9, 2);
601         tmp[2] = 0;
602         tm.tm_hour = atoi (tmp);
603         strncpy (tmp, ptpdate + 11, 2);
604         tmp[2] = 0;
605         tm.tm_min = atoi (tmp);
606         strncpy (tmp, ptpdate + 13, 2);
607         tmp[2] = 0;
608         tm.tm_sec = atoi (tmp);
609         tm.tm_isdst = -1;
610         return mktime (&tm);
611 }
612
613 static inline void
614 ptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
615 {
616         uint8_t filenamelen;
617         uint8_t capturedatelen;
618         char *capture_date;
619
620         oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
621         oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
622         oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
623         oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
624
625         /* Stupid Samsung Galaxy developers emit a 64bit objectcompressedsize */
626         if ((data[PTP_oi_filenamelen] == 0) && (data[PTP_oi_filenamelen+4] != 0)) {
627                 params->ocs64 = 1;
628                 data += 4;
629         }
630         oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
631         oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
632         oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
633         oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
634         oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
635         oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
636         oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
637         oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
638         oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
639         oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
640         oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
641
642         oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
643
644         capture_date = ptp_unpack_string(params, data,
645                 PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
646         /* subset of ISO 8601, without '.s' tenths of second and 
647          * time zone
648          */
649         oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
650         free(capture_date);
651
652         /* now the modification date ... */
653         capture_date = ptp_unpack_string(params, data,
654                 PTP_oi_filenamelen+filenamelen*2
655                 +capturedatelen*2+2,&capturedatelen);
656         oi->ModificationDate = ptp_unpack_PTPTIME(capture_date);
657         free(capture_date);
658 }
659
660 /* Custom Type Value Assignement (without Length) macro frequently used below */
661 #define CTVAL(target,func) {                    \
662         if (total - *offset < sizeof(target))   \
663                 return 0;                       \
664         target = func(&data[*offset]);          \
665         *offset += sizeof(target);              \
666 }
667
668 #define RARR(val,member,func)   {                       \
669         unsigned int n,j;                               \
670         if (total - *offset < sizeof(uint32_t))         \
671                 return 0;                               \
672         n = dtoh32a (&data[*offset]);                   \
673         *offset += sizeof(uint32_t);                    \
674                                                         \
675         if (n >= UINT_MAX/sizeof(val->a.v[0]))          \
676                 return 0;                               \
677         val->a.count = n;                               \
678         val->a.v = malloc(sizeof(val->a.v[0])*n);       \
679         if (!val->a.v) return 0;                        \
680         for (j=0;j<n;j++)                               \
681                 CTVAL(val->a.v[j].member, func);        \
682 }
683
684 static inline unsigned int
685 ptp_unpack_DPV (
686         PTPParams *params, unsigned char* data, unsigned int *offset, int total,
687         PTPPropertyValue* value, uint16_t datatype
688 ) {
689         switch (datatype) {
690         case PTP_DTC_INT8:
691                 CTVAL(value->i8,dtoh8a);
692                 break;
693         case PTP_DTC_UINT8:
694                 CTVAL(value->u8,dtoh8a);
695                 break;
696         case PTP_DTC_INT16:
697                 CTVAL(value->i16,dtoh16a);
698                 break;
699         case PTP_DTC_UINT16:
700                 CTVAL(value->u16,dtoh16a);
701                 break;
702         case PTP_DTC_INT32:
703                 CTVAL(value->i32,dtoh32a);
704                 break;
705         case PTP_DTC_UINT32:
706                 CTVAL(value->u32,dtoh32a);
707                 break;
708         case PTP_DTC_INT64:
709                 CTVAL(value->i64,dtoh64a);
710                 break;
711         case PTP_DTC_UINT64:
712                 CTVAL(value->u64,dtoh64a);
713                 break;
714
715         case PTP_DTC_UINT128:
716                 *offset += 16;
717                 /*fprintf(stderr,"unhandled unpack of uint128n");*/
718                 break;
719         case PTP_DTC_INT128:
720                 *offset += 16;
721                 /*fprintf(stderr,"unhandled unpack of int128n");*/
722                 break;
723
724
725
726         case PTP_DTC_AINT8:
727                 RARR(value,i8,dtoh8a);
728                 break;
729         case PTP_DTC_AUINT8:
730                 RARR(value,u8,dtoh8a);
731                 break;
732         case PTP_DTC_AUINT16:
733                 RARR(value,u16,dtoh16a);
734                 break;
735         case PTP_DTC_AINT16:
736                 RARR(value,i16,dtoh16a);
737                 break;
738         case PTP_DTC_AUINT32:
739                 RARR(value,u32,dtoh32a);
740                 break;
741         case PTP_DTC_AINT32:
742                 RARR(value,i32,dtoh32a);
743                 break;
744         case PTP_DTC_AUINT64:
745                 RARR(value,u64,dtoh64a);
746                 break;
747         case PTP_DTC_AINT64:
748                 RARR(value,i64,dtoh64a);
749                 break;
750         /* XXX: other int types are unimplemented */
751         /* XXX: other int arrays are unimplemented also */
752         case PTP_DTC_STR: {
753                 uint8_t len;
754                 /* XXX: max size */
755                 value->str = ptp_unpack_string(params,data,*offset,&len);
756                 *offset += len*2+1;
757                 if (!value->str)
758                         return 1;
759                 break;
760         }
761         default:
762                 return 0;
763         }
764         return 1;
765 }
766
767 /* Device Property pack/unpack */
768 #define PTP_dpd_DevicePropertyCode      0
769 #define PTP_dpd_DataType                2
770 #define PTP_dpd_GetSet                  4
771 #define PTP_dpd_FactoryDefaultValue     5
772
773 static inline int
774 ptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
775 {
776         unsigned int offset = 0, ret;
777
778         memset (dpd, 0, sizeof(*dpd));
779         dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
780         dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
781         dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
782         dpd->FormFlag=PTP_DPFF_None;
783
784         offset = PTP_dpd_FactoryDefaultValue;
785         ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
786         if (!ret) goto outofmemory;
787         if ((dpd->DataType == PTP_DTC_STR) && (offset == dpdlen))
788                 return 1;
789         ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
790         if (!ret) goto outofmemory;
791
792         /* if offset==0 then Data Type format is not supported by this
793            code or the Data Type is a string (with two empty strings as
794            values). In both cases Form Flag should be set to 0x00 and FORM is
795            not present. */
796
797         if (offset==PTP_dpd_FactoryDefaultValue)
798                 return 1;
799
800         dpd->FormFlag=dtoh8a(&data[offset]);
801         offset+=sizeof(uint8_t);
802
803         switch (dpd->FormFlag) {
804         case PTP_DPFF_Range:
805                 ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
806                 if (!ret) goto outofmemory;
807                 ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
808                 if (!ret) goto outofmemory;
809                 ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
810                 if (!ret) goto outofmemory;
811                 break;
812         case PTP_DPFF_Enumeration: {
813                 int i;
814 #define N       dpd->FORM.Enum.NumberOfValues
815                 N = dtoh16a(&data[offset]);
816                 offset+=sizeof(uint16_t);
817                 dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
818                 if (!dpd->FORM.Enum.SupportedValue)
819                         goto outofmemory;
820
821                 memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
822                 for (i=0;i<N;i++) {
823                         ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
824
825                         /* Slightly different handling here. The HP PhotoSmart 120
826                          * specifies an enumeration with N in wrong endian
827                          * 00 01 instead of 01 00, so we count the enum just until the
828                          * the end of the packet.
829                          */
830                         if (!ret) {
831                                 if (!i)
832                                         goto outofmemory;
833                                 dpd->FORM.Enum.NumberOfValues = i;
834                                 break;
835                         }
836                 }
837                 }
838         }
839 #undef N
840         return 1;
841 outofmemory:
842         ptp_free_devicepropdesc(dpd);
843         return 0;
844 }
845
846 /* Device Property pack/unpack */
847 #define PTP_dpd_Sony_DevicePropertyCode 0
848 #define PTP_dpd_Sony_DataType           2
849 #define PTP_dpd_Sony_GetSet             4
850 #define PTP_dpd_Sony_Unknown            5
851 #define PTP_dpd_Sony_FactoryDefaultValue        6
852
853 static inline int
854 ptp_unpack_Sony_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen, unsigned int *poffset)
855 {
856         unsigned int ret;
857
858         memset (dpd, 0, sizeof(*dpd));
859         dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_Sony_DevicePropertyCode]);
860         dpd->DataType=dtoh16a(&data[PTP_dpd_Sony_DataType]);
861
862 #if 0
863         dpd->GetSet=dtoh8a(&data[PTP_dpd_Sony_GetSet]);
864 #endif
865         dpd->GetSet=1;
866
867         dpd->FormFlag=PTP_DPFF_None;
868
869         *poffset = PTP_dpd_Sony_FactoryDefaultValue;
870         ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
871         if (!ret) goto outofmemory;
872         if ((dpd->DataType == PTP_DTC_STR) && (*poffset == dpdlen))
873                 return 1;
874         ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->CurrentValue, dpd->DataType);
875         if (!ret) goto outofmemory;
876
877         /* if offset==0 then Data Type format is not supported by this
878            code or the Data Type is a string (with two empty strings as
879            values). In both cases Form Flag should be set to 0x00 and FORM is
880            not present. */
881
882         if (*poffset==PTP_dpd_Sony_FactoryDefaultValue)
883                 return 1;
884
885         dpd->FormFlag=dtoh8a(&data[*poffset]);
886         *poffset+=sizeof(uint8_t);
887
888         switch (dpd->FormFlag) {
889         case PTP_DPFF_Range:
890                 ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
891                 if (!ret) goto outofmemory;
892                 ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
893                 if (!ret) goto outofmemory;
894                 ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
895                 if (!ret) goto outofmemory;
896                 break;
897         case PTP_DPFF_Enumeration: {
898                 int i;
899 #define N       dpd->FORM.Enum.NumberOfValues
900                 N = dtoh16a(&data[*poffset]);
901                 *poffset+=sizeof(uint16_t);
902                 dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
903                 if (!dpd->FORM.Enum.SupportedValue)
904                         goto outofmemory;
905
906                 memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
907                 for (i=0;i<N;i++) {
908                         ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
909
910                         /* Slightly different handling here. The HP PhotoSmart 120
911                          * specifies an enumeration with N in wrong endian
912                          * 00 01 instead of 01 00, so we count the enum just until the
913                          * the end of the packet.
914                          */
915                         if (!ret) {
916                                 if (!i)
917                                         goto outofmemory;
918                                 dpd->FORM.Enum.NumberOfValues = i;
919                                 break;
920                         }
921                 }
922                 }
923         }
924 #undef N
925         return 1;
926 outofmemory:
927         ptp_free_devicepropdesc(dpd);
928         return 0;
929 }
930
931 static inline void
932 duplicate_PropertyValue (const PTPPropertyValue *src, PTPPropertyValue *dst, uint16_t type) {
933         if (type == PTP_DTC_STR) {
934                 if (src->str)
935                         dst->str = strdup(src->str);
936                 else
937                         dst->str = NULL;
938                 return;
939         }
940
941         if (type & PTP_DTC_ARRAY_MASK) {
942                 unsigned int i;
943
944                 dst->a.count = src->a.count;
945                 dst->a.v = malloc (sizeof(src->a.v[0])*src->a.count);
946                 for (i=0;i<src->a.count;i++)
947                         duplicate_PropertyValue (&src->a.v[i], &dst->a.v[i], type & ~PTP_DTC_ARRAY_MASK);
948                 return;
949         }
950         switch (type & ~PTP_DTC_ARRAY_MASK) {
951         case PTP_DTC_INT8:      dst->i8 = src->i8; break;
952         case PTP_DTC_UINT8:     dst->u8 = src->u8; break;
953         case PTP_DTC_INT16:     dst->i16 = src->i16; break;
954         case PTP_DTC_UINT16:    dst->u16 = src->u16; break;
955         case PTP_DTC_INT32:     dst->i32 = src->i32; break;
956         case PTP_DTC_UINT32:    dst->u32 = src->u32; break;
957         case PTP_DTC_UINT64:    dst->u64 = src->u64; break;
958         case PTP_DTC_INT64:     dst->i64 = src->i64; break;
959 #if 0
960         case PTP_DTC_INT128:    dst->i128 = src->i128; break;
961         case PTP_DTC_UINT128:   dst->u128 = src->u128; break;
962 #endif
963         default:                break;
964         }
965         return;
966 }
967
968 static inline void
969 duplicate_DevicePropDesc(const PTPDevicePropDesc *src, PTPDevicePropDesc *dst) {
970         int i;
971
972         dst->DevicePropertyCode = src->DevicePropertyCode;
973         dst->DataType           = src->DataType;
974         dst->GetSet             = src->GetSet;
975         
976         duplicate_PropertyValue (&src->FactoryDefaultValue, &dst->FactoryDefaultValue, src->DataType);
977         duplicate_PropertyValue (&src->CurrentValue, &dst->CurrentValue, src->DataType);
978
979         dst->FormFlag           = src->FormFlag;
980         switch (src->FormFlag) {
981         case PTP_DPFF_Range:
982                 duplicate_PropertyValue (&src->FORM.Range.MinimumValue, &dst->FORM.Range.MinimumValue, src->DataType);
983                 duplicate_PropertyValue (&src->FORM.Range.MaximumValue, &dst->FORM.Range.MaximumValue, src->DataType);
984                 duplicate_PropertyValue (&src->FORM.Range.StepSize,     &dst->FORM.Range.StepSize,     src->DataType);
985                 break;
986         case PTP_DPFF_Enumeration:
987                 dst->FORM.Enum.NumberOfValues = src->FORM.Enum.NumberOfValues;
988                 dst->FORM.Enum.SupportedValue = malloc (sizeof(dst->FORM.Enum.SupportedValue[0])*src->FORM.Enum.NumberOfValues);
989                 for (i = 0; i<src->FORM.Enum.NumberOfValues ; i++)
990                         duplicate_PropertyValue (&src->FORM.Enum.SupportedValue[i], &dst->FORM.Enum.SupportedValue[i], src->DataType);
991                 break;
992         case PTP_DPFF_None:
993                 break;
994         }
995 }
996
997 #define PTP_opd_ObjectPropertyCode      0
998 #define PTP_opd_DataType                2
999 #define PTP_opd_GetSet                  4
1000 #define PTP_opd_FactoryDefaultValue     5
1001
1002 static inline int
1003 ptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
1004 {
1005         unsigned int offset=0, ret;
1006
1007         memset (opd, 0, sizeof(*opd));
1008         opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
1009         opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
1010         opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
1011
1012         offset = PTP_opd_FactoryDefaultValue;
1013         ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
1014         if (!ret) goto outofmemory;
1015
1016         opd->GroupCode=dtoh32a(&data[offset]);
1017         offset+=sizeof(uint32_t);
1018
1019         opd->FormFlag=dtoh8a(&data[offset]);
1020         offset+=sizeof(uint8_t);
1021
1022         switch (opd->FormFlag) {
1023         case PTP_OPFF_Range:
1024                 ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
1025                 if (!ret) goto outofmemory;
1026                 ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
1027                 if (!ret) goto outofmemory;
1028                 ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
1029                 if (!ret) goto outofmemory;
1030                 break;
1031         case PTP_OPFF_Enumeration: {
1032                 unsigned int i;
1033 #define N       opd->FORM.Enum.NumberOfValues
1034                 N = dtoh16a(&data[offset]);
1035                 offset+=sizeof(uint16_t);
1036                 opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
1037                 if (!opd->FORM.Enum.SupportedValue)
1038                         goto outofmemory;
1039
1040                 memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
1041                 for (i=0;i<N;i++) {
1042                         ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
1043
1044                         /* Slightly different handling here. The HP PhotoSmart 120
1045                          * specifies an enumeration with N in wrong endian
1046                          * 00 01 instead of 01 00, so we count the enum just until the
1047                          * the end of the packet.
1048                          */
1049                         if (!ret) {
1050                                 if (!i)
1051                                         goto outofmemory;
1052                                 opd->FORM.Enum.NumberOfValues = i;
1053                                 break;
1054                         }
1055                 }
1056 #undef N
1057                 }
1058         }
1059         return 1;
1060 outofmemory:
1061         ptp_free_objectpropdesc(opd);
1062         return 0;
1063 }
1064
1065
1066 static inline uint32_t
1067 ptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
1068 {
1069         unsigned char* dpv=NULL;
1070         uint32_t size=0;
1071         unsigned int i;
1072
1073         switch (datatype) {
1074         case PTP_DTC_INT8:
1075                 size=sizeof(int8_t);
1076                 dpv=malloc(size);
1077                 htod8a(dpv,value->i8);
1078                 break;
1079         case PTP_DTC_UINT8:
1080                 size=sizeof(uint8_t);
1081                 dpv=malloc(size);
1082                 htod8a(dpv,value->u8);
1083                 break;
1084         case PTP_DTC_INT16:
1085                 size=sizeof(int16_t);
1086                 dpv=malloc(size);
1087                 htod16a(dpv,value->i16);
1088                 break;
1089         case PTP_DTC_UINT16:
1090                 size=sizeof(uint16_t);
1091                 dpv=malloc(size);
1092                 htod16a(dpv,value->u16);
1093                 break;
1094         case PTP_DTC_INT32:
1095                 size=sizeof(int32_t);
1096                 dpv=malloc(size);
1097                 htod32a(dpv,value->i32);
1098                 break;
1099         case PTP_DTC_UINT32:
1100                 size=sizeof(uint32_t);
1101                 dpv=malloc(size);
1102                 htod32a(dpv,value->u32);
1103                 break;
1104         case PTP_DTC_INT64:
1105                 size=sizeof(int64_t);
1106                 dpv=malloc(size);
1107                 htod64a(dpv,value->i64);
1108                 break;
1109         case PTP_DTC_UINT64:
1110                 size=sizeof(uint64_t);
1111                 dpv=malloc(size);
1112                 htod64a(dpv,value->u64);
1113                 break;
1114         case PTP_DTC_AUINT8:
1115                 size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
1116                 dpv=malloc(size);
1117                 htod32a(dpv,value->a.count);
1118                 for (i=0;i<value->a.count;i++)
1119                         htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
1120                 break;
1121         case PTP_DTC_AINT8:
1122                 size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
1123                 dpv=malloc(size);
1124                 htod32a(dpv,value->a.count);
1125                 for (i=0;i<value->a.count;i++)
1126                         htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
1127                 break;
1128         case PTP_DTC_AUINT16:
1129                 size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
1130                 dpv=malloc(size);
1131                 htod32a(dpv,value->a.count);
1132                 for (i=0;i<value->a.count;i++)
1133                         htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
1134                 break;
1135         case PTP_DTC_AINT16:
1136                 size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
1137                 dpv=malloc(size);
1138                 htod32a(dpv,value->a.count);
1139                 for (i=0;i<value->a.count;i++)
1140                         htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
1141                 break;
1142         case PTP_DTC_AUINT32:
1143                 size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
1144                 dpv=malloc(size);
1145                 htod32a(dpv,value->a.count);
1146                 for (i=0;i<value->a.count;i++)
1147                         htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
1148                 break;
1149         case PTP_DTC_AINT32:
1150                 size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
1151                 dpv=malloc(size);
1152                 htod32a(dpv,value->a.count);
1153                 for (i=0;i<value->a.count;i++)
1154                         htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
1155                 break;
1156         case PTP_DTC_AUINT64:
1157                 size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
1158                 dpv=malloc(size);
1159                 htod32a(dpv,value->a.count);
1160                 for (i=0;i<value->a.count;i++)
1161                         htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
1162                 break;
1163         case PTP_DTC_AINT64:
1164                 size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
1165                 dpv=malloc(size);
1166                 htod32a(dpv,value->a.count);
1167                 for (i=0;i<value->a.count;i++)
1168                         htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
1169                 break;
1170         /* XXX: other int types are unimplemented */
1171         case PTP_DTC_STR: {
1172                 dpv=ptp_get_packed_stringcopy(params, value->str, &size);
1173                 break;
1174         }
1175         }
1176         *dpvptr=dpv;
1177         return size;
1178 }
1179
1180 #define MAX_MTP_PROPS 127
1181 static inline uint32_t
1182 ptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
1183 {
1184         unsigned char* opldata;
1185         MTPProperties *propitr;
1186         unsigned char *packedprops[MAX_MTP_PROPS];
1187         uint32_t packedpropslens[MAX_MTP_PROPS];
1188         uint32_t packedobjecthandles[MAX_MTP_PROPS];
1189         uint16_t packedpropsids[MAX_MTP_PROPS];
1190         uint16_t packedpropstypes[MAX_MTP_PROPS];
1191         uint32_t totalsize = 0;
1192         uint32_t bufp = 0;
1193         uint32_t noitems = 0;
1194         uint32_t i;
1195
1196         totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
1197         propitr = props;
1198         while (nrofprops-- && noitems < MAX_MTP_PROPS) {
1199                 /* Object Handle */
1200                 packedobjecthandles[noitems]=propitr->ObjectHandle;
1201                 totalsize += sizeof(uint32_t); /* Object ID */
1202                 /* Metadata type */
1203                 packedpropsids[noitems]=propitr->property;
1204                 totalsize += sizeof(uint16_t);
1205                 /* Data type */
1206                 packedpropstypes[noitems]= propitr->datatype;
1207                 totalsize += sizeof(uint16_t);
1208                 /* Add each property to be sent. */
1209                 packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
1210                 totalsize += packedpropslens[noitems];
1211                 noitems ++;
1212                 propitr ++;
1213         }
1214
1215         /* Allocate memory for the packed property list */
1216         opldata = malloc(totalsize);
1217
1218         htod32a(&opldata[bufp],noitems);
1219         bufp += 4;
1220
1221         /* Copy into a nice packed list */
1222         for (i = 0; i < noitems; i++) {
1223                 /* Object ID */
1224                 htod32a(&opldata[bufp],packedobjecthandles[i]);
1225                 bufp += sizeof(uint32_t);
1226                 htod16a(&opldata[bufp],packedpropsids[i]);
1227                 bufp += sizeof(uint16_t);
1228                 htod16a(&opldata[bufp],packedpropstypes[i]);
1229                 bufp += sizeof(uint16_t);
1230                 /* The copy the actual property */
1231                 memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
1232                 bufp += packedpropslens[i];
1233                 free(packedprops[i]);
1234         }
1235         *opldataptr = opldata;
1236         return totalsize;
1237 }
1238
1239 static int
1240 _compare_func(const void* x, const void *y) {
1241         const MTPProperties *px = x;
1242         const MTPProperties *py = y;
1243
1244         return px->ObjectHandle - py->ObjectHandle;
1245 }
1246
1247 static inline int
1248 ptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
1249
1250         uint32_t prop_count = dtoh32a(data);
1251         MTPProperties *props = NULL;
1252         unsigned int offset = 0, i;
1253
1254         if (prop_count == 0) {
1255                 *pprops = NULL;
1256                 return 0;
1257         }
1258         ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
1259         data += sizeof(uint32_t);
1260         len -= sizeof(uint32_t);
1261         props = malloc(prop_count * sizeof(MTPProperties));
1262         if (!props) return 0;
1263         for (i = 0; i < prop_count; i++) {
1264                 if (len <= 0) {
1265                         ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
1266                         ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL", i);
1267                         ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i);
1268                         qsort (props, i, sizeof(MTPProperties),_compare_func);
1269                         *pprops = props;
1270                         return i;
1271                 }
1272                 props[i].ObjectHandle = dtoh32a(data);
1273                 data += sizeof(uint32_t);
1274                 len -= sizeof(uint32_t);
1275
1276                 props[i].property = dtoh16a(data);
1277                 data += sizeof(uint16_t);
1278                 len -= sizeof(uint16_t);
1279
1280                 props[i].datatype = dtoh16a(data);
1281                 data += sizeof(uint16_t);
1282                 len -= sizeof(uint16_t);
1283
1284                 offset = 0;
1285                 ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype);
1286                 data += offset;
1287                 len -= offset;
1288         }
1289         qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
1290         *pprops = props;
1291         return prop_count;
1292 }
1293
1294 /*
1295     PTP USB Event container unpack
1296     Copyright (c) 2003 Nikolai Kopanygin
1297 */
1298
1299 #define PTP_ec_Length           0
1300 #define PTP_ec_Type             4
1301 #define PTP_ec_Code             6
1302 #define PTP_ec_TransId          8
1303 #define PTP_ec_Param1           12
1304 #define PTP_ec_Param2           16
1305 #define PTP_ec_Param3           20
1306
1307 static inline void
1308 ptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
1309 {
1310         unsigned int    length;
1311         int     type;
1312
1313         if (data==NULL)
1314                 return;
1315         memset(ec,0,sizeof(*ec));
1316
1317         length=dtoh32a(&data[PTP_ec_Length]);
1318         if (length > len) {
1319                 ptp_debug (params, "length %d in container, but data only %d bytes?!", length, len);
1320                 return;
1321         }
1322         type = dtoh16a(&data[PTP_ec_Type]);
1323
1324         ec->Code=dtoh16a(&data[PTP_ec_Code]);
1325         ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
1326
1327         if (type!=PTP_USB_CONTAINER_EVENT) {
1328                 ptp_debug (params, "Unknown canon event type %d (code=%x,tid=%x), please report!",type,ec->Code,ec->Transaction_ID);
1329                 return;
1330         }
1331         if (length>=(PTP_ec_Param1+4)) {
1332                 ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
1333                 ec->Nparam=1;
1334         }
1335         if (length>=(PTP_ec_Param2+4)) {
1336                 ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
1337                 ec->Nparam=2;
1338         }
1339         if (length>=(PTP_ec_Param3+4)) {
1340                 ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
1341                 ec->Nparam=3;
1342         }
1343 }
1344
1345 /*
1346     PTP Canon Folder Entry unpack
1347     Copyright (c) 2003 Nikolai Kopanygin
1348 */
1349 #define PTP_cfe_ObjectHandle            0
1350 #define PTP_cfe_ObjectFormatCode        4
1351 #define PTP_cfe_Flags                   6
1352 #define PTP_cfe_ObjectSize              7
1353 #define PTP_cfe_Time                    11
1354 #define PTP_cfe_Filename                15
1355
1356 static inline void
1357 ptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1358 {
1359         int i;
1360         if (data==NULL)
1361                 return;
1362         fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
1363         fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
1364         fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
1365         fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
1366         fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
1367         for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1368                 fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
1369 }
1370
1371 /*
1372     PTP Canon EOS Folder Entry unpack
1373 0: 00 00 08 a0     objectid
1374 4: 01 00 02 00     storageid
1375 8: 01 30 00 00     ofc
1376 12: 01 00
1377 14: 00 00
1378 16: 11 00 00 00
1379 20: 00 00 00 00
1380 24: 00 00 00 80
1381 28: 00 00 08 a0
1382 32: 4d 49 53 43-00 00 00 00 00 00 00 00     name
1383 00 00 00 00
1384 84 bc 74 46     objectime
1385
1386
1387 (normal PTP GetObjectInfo)
1388 ObjectInfo for 'IMG_0199.JPG':
1389   Object ID: 0x92740c72
1390   StorageID: 0x00020001
1391   ObjectFormat: 0x3801
1392   ProtectionStatus: 0x0000
1393   ObjectCompressedSize: 2217241
1394   ThumbFormat: 0x3808
1395   ThumbCompressedSize: 5122
1396   ThumbPixWidth: 160
1397   ThumbPixHeight: 120
1398   ImagePixWidth: 4000
1399   ImagePixHeight: 3000
1400   ImageBitDepth: 24
1401   ParentObject: 0x92740000
1402   AssociationType: 0x0000
1403   AssociationDesc: 0x00000000
1404   SequenceNumber: 0x00000000
1405   ModificationDate: 0x4d985ff0
1406   CaptureDate: 0x4d985ff0
1407
1408 0010  38 00 00 00  Size of this entry
1409 0014  72 0c 74 92  OID
1410 0018  01 00 02 00  StorageID
1411 001c  01 38 00 00  OFC
1412 0020  00 00 00 00 00 00 00 00  ? 
1413 0028  19 d5 21 00  Size
1414 002c  00 00 74 92  ?
1415 0030  70 0c 74 92  OID
1416 0034  49 4d 47 5f-30 31 39 39 2e 4a 50 47  IMG_0199.JPG
1417 0040  00 00 00 00
1418 0044  10 7c 98 4d Time
1419
1420
1421 */
1422 #define PTP_cefe_ObjectHandle           0
1423 #define PTP_cefe_StorageID              4
1424 #define PTP_cefe_ObjectFormatCode       8
1425 #define PTP_cefe_Flags                  12
1426 #define PTP_cefe_ObjectSize             20
1427 #define PTP_cefe_Filename               32
1428 #define PTP_cefe_Time                   48
1429
1430 static inline void
1431 ptp_unpack_Canon_EOS_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1432 {
1433         int i;
1434
1435         fe->ObjectHandle=dtoh32a(&data[PTP_cefe_ObjectHandle]);
1436         fe->ObjectFormatCode=dtoh16a(&data[PTP_cefe_ObjectFormatCode]);
1437         fe->Flags=dtoh8a(&data[PTP_cefe_Flags]);
1438         fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cefe_ObjectSize]);
1439         fe->Time=(time_t)dtoh32a(&data[PTP_cefe_Time]);
1440         for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1441                 fe->Filename[i]=(char)data[PTP_cefe_Filename+i];
1442 }
1443
1444
1445 static inline uint16_t
1446 ptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
1447 {
1448         /*
1449           EOS ImageFormat entries (of at least the 5DM2 and the 400D) look like this:
1450                 uint32: number of entries / generated files (1 or 2)
1451                 uint32: size of this entry in bytes (most likely allways 0x10)
1452                 uint32: image type (1 == JPG, 6 == RAW)
1453                 uint32: image size (0 == Large, 1 == Medium, 2 == Small, 0xe == S1, 0xf == S2, 0x10 == S3)
1454                 uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW)
1455           If the number of entries is 2 the last 4 uint32 repeat.
1456
1457           example:
1458                 0: 0x       1
1459                 1: 0x      10
1460                 2: 0x       6
1461                 3: 0x       1
1462                 4: 0x       4
1463
1464           The idea is to simply 'condense' these values to just one uint16 to be able to conveniently
1465           use the available enumeration facilities (look-up table). The image size and compression
1466           values fully describe the image format. Hence we generate a uint16 with the four nibles set
1467           as follows: entry 1 size | entry 1 compression | entry 2 size | entry 2 compression.
1468           The above example would result in the value 0x1400.
1469
1470           The EOS 5D Mark III (and possibly other high-end EOS as well) added the extra fancy S1, S2
1471           and S3 JPEG options. S1 replaces the old Small. -1 the S1/S2/S3 to prevent the 0x10 overflow.
1472           */
1473
1474         const unsigned char* d = *data;
1475         uint32_t n = dtoh32a( d );
1476         uint32_t l, s1, c1, s2 = 0, c2 = 0;
1477
1478         if (n != 1 && n !=2) {
1479                 ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
1480                 return 0;
1481         }
1482
1483         l = dtoh32a( d+=4 );
1484         if (l != 0x10) {
1485                 ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
1486                 return 0;
1487         }
1488
1489         d+=4; /* skip type */
1490         s1 = dtoh32a( d+=4 );
1491         c1 = dtoh32a( d+=4 );
1492
1493         if (n == 2) {
1494                 l = dtoh32a( d+=4 );
1495                 if (l != 0x10) {
1496                         ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
1497                         return 0;
1498                 }
1499                 d+=4; /* skip type */
1500                 s2 = dtoh32a( d+=4 );
1501                 c2 = dtoh32a( d+=4 );
1502         }
1503
1504         *data = (unsigned char*) d+4;
1505
1506         /* deal with S1/S2/S3 JPEG sizes, see above. */
1507         if( s1 >= 0xe )
1508                 s1--;
1509         if( s2 >= 0xe )
1510                 s2--;
1511
1512         return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
1513 }
1514
1515 static inline uint32_t
1516 ptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
1517 {
1518         uint32_t n = (value & 0xFF) ? 2 : 1;
1519         uint32_t s = 4 + 0x10 * n;
1520
1521         if( !data )
1522                 return s;
1523
1524 #define PACK_5DM3_SMALL_JPEG_SIZE( X ) (X) >= 0xd ? (X)+1 : (X)
1525
1526         htod32a(data+=0, n);
1527         htod32a(data+=4, 0x10);
1528         htod32a(data+=4, ((value >> 8) & 0xF) == 4 ? 6 : 1);
1529         htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 12) & 0xF));
1530         htod32a(data+=4, (value >> 8) & 0xF);
1531
1532         if (n==2) {
1533                 htod32a(data+=4, 0x10);
1534                 htod32a(data+=4, ((value >> 0) & 0xF) == 4 ? 6 : 1);
1535                 htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 4) & 0xF));
1536                 htod32a(data+=4, (value >> 0) & 0xF);
1537         }
1538
1539 #undef PACK_5DM3_SMALL_JPEG_SIZE
1540
1541         return s;
1542 }
1543
1544 static inline char*
1545 ptp_unpack_EOS_CustomFuncEx (PTPParams* params, unsigned char** data )
1546 {
1547         uint32_t s = dtoh32a( *data );
1548         uint32_t n = s/4, i;
1549         char* str = (char*)malloc( s*2+s/4+1 ); /* n is size in uint32, maximum %x len is 8 chars and \0*/
1550         if (!str)
1551                 return str;
1552         char* p = str;
1553
1554         for (i=0; i < n; ++i)
1555                 p += sprintf(p, "%x,", dtoh32a( *data + 4*i ));
1556
1557         return str;
1558 }
1559
1560 static inline uint32_t
1561 ptp_pack_EOS_CustomFuncEx (PTPParams* params, unsigned char* data, char* str)
1562 {
1563         uint32_t s = strtoul(str, NULL, 16);
1564         uint32_t n = s/4, i, v;
1565
1566         if (!data)
1567                 return s;
1568
1569         for (i=0; i<n; i++)
1570         {
1571                 v = strtoul(str, &str, 16);
1572                 str++; /* skip the ',' delimiter */
1573                 htod32a(data + i*4, v);
1574         }
1575
1576         return s;
1577 }
1578
1579 /*
1580     PTP EOS Changes Entry unpack
1581 */
1582 #define PTP_ece_Size            0
1583 #define PTP_ece_Type            4
1584
1585 #define PTP_ece_Prop_Subtype    8       /* only for properties */
1586 #define PTP_ece_Prop_Val_Data   0xc     /* only for properties */
1587 #define PTP_ece_Prop_Desc_Type  0xc     /* only for property descs */
1588 #define PTP_ece_Prop_Desc_Count 0x10    /* only for property descs */
1589 #define PTP_ece_Prop_Desc_Data  0x14    /* only for property descs */
1590
1591 /* for PTP_EC_CANON_EOS_RequestObjectTransfer */
1592 #define PTP_ece_OI_ObjectID     8
1593 #define PTP_ece_OI_OFC          0x0c
1594 #define PTP_ece_OI_Size         0x14
1595 #define PTP_ece_OI_Name         0x1c
1596
1597 /* for PTP_EC_CANON_EOS_ObjectAddedEx */
1598 #define PTP_ece_OA_ObjectID     8
1599 #define PTP_ece_OA_StorageID    0x0c
1600 #define PTP_ece_OA_OFC          0x10
1601 #define PTP_ece_OA_Size         0x1c
1602 #define PTP_ece_OA_Parent       0x20
1603 #define PTP_ece_OA_Name         0x28
1604
1605 static inline int
1606 ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **pce)
1607 {
1608         int     i = 0, entries = 0;
1609         unsigned char   *curdata = data;
1610         PTPCanon_changes_entry *ce;
1611
1612         if (data==NULL)
1613                 return 0;
1614         while (curdata - data < datasize) {
1615                 uint32_t        size = dtoh32a(&curdata[PTP_ece_Size]);
1616                 uint32_t        type = dtoh32a(&curdata[PTP_ece_Type]);
1617
1618                 if ((size == 8) && (type == 0))
1619                         break;
1620                 if (type == PTP_EC_CANON_EOS_OLCInfoChanged) {
1621                         unsigned int j;
1622
1623                         for (j=0;j<31;j++)
1624                                 if (dtoh32a(curdata+12) & (1<<j))
1625                                         entries++;
1626                 }
1627                 curdata += size;
1628                 entries++;
1629         }
1630         ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
1631         if (!ce) return 0;
1632
1633         curdata = data;
1634         while (curdata - data < datasize) {
1635                 uint32_t        size = dtoh32a(&curdata[PTP_ece_Size]);
1636                 uint32_t        type = dtoh32a(&curdata[PTP_ece_Type]);
1637
1638                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1639                 ce[i].u.info = NULL;
1640                 switch (type) {
1641                 case  PTP_EC_CANON_EOS_ObjectAddedEx:
1642                         ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
1643                         ce[i].u.object.oid              = dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
1644                         ce[i].u.object.oi.StorageID             = dtoh32a(&curdata[PTP_ece_OA_StorageID]);
1645                         ce[i].u.object.oi.ParentObject  = dtoh32a(&curdata[PTP_ece_OA_Parent]);
1646                         ce[i].u.object.oi.ObjectFormat  = dtoh16a(&curdata[PTP_ece_OA_OFC]);
1647                         ce[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
1648                         ce[i].u.object.oi.Filename              = strdup(((char*)&curdata[PTP_ece_OA_Name]));
1649                         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);
1650                         break;
1651                 case  PTP_EC_CANON_EOS_RequestObjectTransfer:
1652                         ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
1653                         ce[i].u.object.oid              = dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
1654                         ce[i].u.object.oi.StorageID             = 0; /* use as marker */
1655                         ce[i].u.object.oi.ObjectFormat  = dtoh16a(&curdata[PTP_ece_OI_OFC]);
1656                         ce[i].u.object.oi.ParentObject  = 0; /* check, but use as marker */
1657                         ce[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
1658                         ce[i].u.object.oi.Filename              = strdup(((char*)&curdata[PTP_ece_OI_Name]));
1659
1660                         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);
1661                         break;
1662                 case  PTP_EC_CANON_EOS_AvailListChanged: {      /* property desc */
1663                         uint32_t        proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1664                         uint32_t        propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
1665                         uint32_t        propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
1666                         unsigned char   *xdata = &curdata[PTP_ece_Prop_Desc_Data];
1667                         unsigned int    j;
1668                         PTPDevicePropDesc       *dpd;
1669
1670                         ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype);
1671                         for (j=0;j<params->nrofcanon_props;j++)
1672                                 if (params->canon_props[j].proptype == proptype)
1673                                         break;
1674                         if (j==params->nrofcanon_props) {
1675                                 ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
1676                                 break;
1677                         }
1678                         dpd = &params->canon_props[j].dpd;
1679                         /* 1 - uint16 ? 
1680                          * 3 - uint16
1681                          * 7 - string?
1682                          */
1683                         if (propxtype != 3) {
1684                                 ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled.", i, propxtype, proptype);
1685                                 for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++)
1686                                         ptp_debug (params, "    %d: %02x", j, xdata[j]);
1687                                 break;
1688                         }
1689                         if (! propxcnt)
1690                                 break;
1691                         if (propxcnt >= 2<<16) /* buggy or exploit */
1692                                 break;
1693
1694                         ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
1695                                    i, propxtype, proptype, dpd->DataType, propxcnt);
1696                         dpd->FormFlag = PTP_DPFF_Enumeration;
1697                         dpd->FORM.Enum.NumberOfValues = propxcnt;
1698                         if (dpd->FORM.Enum.SupportedValue) free (dpd->FORM.Enum.SupportedValue);
1699                         dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
1700
1701                         switch (proptype) {
1702                         case PTP_DPC_CANON_EOS_ImageFormat:
1703                         case PTP_DPC_CANON_EOS_ImageFormatCF:
1704                         case PTP_DPC_CANON_EOS_ImageFormatSD:
1705                         case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1706                                 /* special handling of ImageFormat properties */
1707                                 for (j=0;j<propxcnt;j++) {
1708                                         dpd->FORM.Enum.SupportedValue[j].u16 =
1709                                                         ptp_unpack_EOS_ImageFormat( params, &xdata );
1710                                         ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
1711                                 }
1712                                 break;
1713                         default:
1714                                 /* 'normal' enumerated types */
1715                                 switch (dpd->DataType) {
1716 #define XX( TYPE, CONV )\
1717                                         for (j=0;j<propxcnt;j++) { \
1718                                                 dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(xdata); \
1719                                                 ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(xdata)); \
1720                                                 xdata += 4; /* might only be for propxtype 3 */ \
1721                                         } \
1722                                         break;
1723
1724                                 case PTP_DTC_INT16:     XX( i16, dtoh16a );
1725                                 case PTP_DTC_UINT32:    XX( u32, dtoh32a );
1726                                 case PTP_DTC_UINT16:    XX( u16, dtoh16a );
1727                                 case PTP_DTC_UINT8:     XX( u8,  dtoh8a );
1728 #undef XX
1729                                 default:
1730                                         ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, raw values:", i, dpd->DataType, proptype, dtoh32a(xdata));
1731                                         for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, xdata+=4) /* 4 is good for propxtype 3 */
1732                                                 ptp_debug (params, "    %3d: 0x%8x", j, dtoh32a(xdata));
1733                                         break;
1734                                 }
1735                         }
1736                         break;
1737                 }
1738                 case PTP_EC_CANON_EOS_PropValueChanged:
1739                         if (size >= 0xc) {      /* property info */
1740                                 unsigned int j;
1741                                 uint32_t        proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1742                                 unsigned char   *xdata = &curdata[PTP_ece_Prop_Val_Data];
1743                                 PTPDevicePropDesc       *dpd;
1744
1745                                 ptp_debug (params, "event %d: EOS prop %04x info record, datasize is %d", i, proptype, size-PTP_ece_Prop_Val_Data);
1746                                 for (j=0;j<params->nrofcanon_props;j++)
1747                                         if (params->canon_props[j].proptype == proptype)
1748                                                 break;
1749                                 if (j<params->nrofcanon_props) {
1750                                         if (    (params->canon_props[j].size != size) ||
1751                                                 (memcmp(params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data))) {
1752                                                 params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
1753                                                 memcpy (params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data);
1754                                         }
1755                                 } else {
1756                                         if (j)
1757                                                 params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
1758                                         else
1759                                                 params->canon_props = malloc(sizeof(params->canon_props[0]));
1760                                         params->canon_props[j].type = type;
1761                                         params->canon_props[j].proptype = proptype;
1762                                         params->canon_props[j].size = size;
1763                                         params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
1764                                         memcpy(params->canon_props[j].data, xdata, size-PTP_ece_Prop_Val_Data);
1765                                         memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
1766                                         params->canon_props[j].dpd.GetSet = 1;
1767                                         params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
1768                                         params->nrofcanon_props = j+1;
1769                                 }
1770                                 dpd = &params->canon_props[j].dpd;
1771
1772                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
1773                                 ce[i].u.propid = proptype;
1774
1775                                 /* fix GetSet value */
1776                                 switch (proptype) {
1777 #define XX(x) case PTP_DPC_CANON_##x:
1778                                         XX(EOS_FocusMode)
1779                                         XX(EOS_BatteryPower)
1780                                         XX(EOS_BatterySelect)
1781                                         XX(EOS_ModelID)
1782                                         XX(EOS_PTPExtensionVersion)
1783                                         XX(EOS_DPOFVersion)
1784                                         XX(EOS_AvailableShots)
1785                                         XX(EOS_CurrentStorage)
1786                                         XX(EOS_CurrentFolder)
1787                                         XX(EOS_MyMenu)
1788                                         XX(EOS_MyMenuList)
1789                                         XX(EOS_HDDirectoryStructure)
1790                                         XX(EOS_BatteryInfo)
1791                                         XX(EOS_AdapterInfo)
1792                                         XX(EOS_LensStatus)
1793                                         XX(EOS_CardExtension)
1794                                         XX(EOS_TempStatus)
1795                                         XX(EOS_ShutterCounter)
1796                                         XX(EOS_SerialNumber)
1797                                         XX(EOS_DepthOfFieldPreview)
1798                                         XX(EOS_EVFRecordStatus)
1799                                         XX(EOS_LvAfSystem)
1800                                         XX(EOS_FocusInfoEx)
1801                                         XX(EOS_DepthOfField)
1802                                         XX(EOS_Brightness)
1803                                         XX(EOS_EFComp)
1804                                         XX(EOS_LensName)
1805                                         XX(EOS_LensID)
1806 #undef XX
1807                                                 dpd->GetSet = PTP_DPGS_Get;
1808                                                 break;
1809                                 }
1810
1811                                 /* set DataType */
1812                                 switch (proptype) {
1813                                 case PTP_DPC_CANON_EOS_CameraTime:
1814                                 case PTP_DPC_CANON_EOS_UTCTime:
1815                                 case PTP_DPC_CANON_EOS_Summertime: /* basical the DST flag */
1816                                 case PTP_DPC_CANON_EOS_AvailableShots:
1817                                 case PTP_DPC_CANON_EOS_CaptureDestination:
1818                                 case PTP_DPC_CANON_EOS_WhiteBalanceXA:
1819                                 case PTP_DPC_CANON_EOS_WhiteBalanceXB:
1820                                 case PTP_DPC_CANON_EOS_CurrentStorage:
1821                                 case PTP_DPC_CANON_EOS_CurrentFolder:
1822                                 case PTP_DPC_CANON_EOS_ShutterCounter:
1823                                 case PTP_DPC_CANON_EOS_ModelID:
1824                                 case PTP_DPC_CANON_EOS_LensID:
1825                                 case PTP_DPC_CANON_EOS_StroboFiring:
1826                                         dpd->DataType = PTP_DTC_UINT32;
1827                                         break;
1828                                 /* enumeration for AEM is never provided, but is available to set */
1829                                 case PTP_DPC_CANON_EOS_AutoExposureMode:
1830                                         dpd->DataType = PTP_DTC_UINT16;
1831                                         dpd->FormFlag = PTP_DPFF_Enumeration;
1832                                         dpd->FORM.Enum.NumberOfValues = 0;
1833                                         break;
1834                                 case PTP_DPC_CANON_EOS_Aperture:
1835                                 case PTP_DPC_CANON_EOS_ShutterSpeed:
1836                                 case PTP_DPC_CANON_EOS_ISOSpeed:
1837                                 case PTP_DPC_CANON_EOS_FocusMode:
1838                                 case PTP_DPC_CANON_EOS_ColorSpace:
1839                                 case PTP_DPC_CANON_EOS_BatteryPower:
1840                                 case PTP_DPC_CANON_EOS_BatterySelect:
1841                                 case PTP_DPC_CANON_EOS_PTPExtensionVersion:
1842                                 case PTP_DPC_CANON_EOS_DriveMode:
1843                                 case PTP_DPC_CANON_EOS_AEB:
1844                                 case PTP_DPC_CANON_EOS_BracketMode:
1845                                 case PTP_DPC_CANON_EOS_QuickReviewTime:
1846                                 case PTP_DPC_CANON_EOS_EVFMode:
1847                                 case PTP_DPC_CANON_EOS_EVFOutputDevice:
1848                                 case PTP_DPC_CANON_EOS_AutoPowerOff:
1849                                         dpd->DataType = PTP_DTC_UINT16;
1850                                         break;
1851                                 case PTP_DPC_CANON_EOS_PictureStyle:
1852                                 case PTP_DPC_CANON_EOS_WhiteBalance:
1853                                 case PTP_DPC_CANON_EOS_MeteringMode:
1854                                 case PTP_DPC_CANON_EOS_ExpCompensation: /* actually int8 if you calculate */
1855                                         dpd->DataType = PTP_DTC_UINT8;
1856                                         break;
1857                                 case PTP_DPC_CANON_EOS_Owner:
1858                                 case PTP_DPC_CANON_EOS_Artist:
1859                                 case PTP_DPC_CANON_EOS_Copyright:
1860                                 case PTP_DPC_CANON_EOS_SerialNumber:
1861                                 case PTP_DPC_CANON_EOS_LensName:
1862                                         dpd->DataType = PTP_DTC_STR;
1863                                         break;
1864                                 case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
1865                                 case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
1866                                         dpd->DataType = PTP_DTC_INT16;
1867                                         break;
1868                                 /* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
1869                                 case PTP_DPC_CANON_EOS_DPOFVersion:
1870                                         dpd->DataType = PTP_DTC_UINT16;
1871                                         ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
1872                                         for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1873                                                 ptp_debug (params, "    %d: %02x", j, xdata[j]);
1874                                         break;
1875                                 case PTP_DPC_CANON_EOS_CustomFunc1:
1876                                 case PTP_DPC_CANON_EOS_CustomFunc2:
1877                                 case PTP_DPC_CANON_EOS_CustomFunc3:
1878                                 case PTP_DPC_CANON_EOS_CustomFunc4:
1879                                 case PTP_DPC_CANON_EOS_CustomFunc5:
1880                                 case PTP_DPC_CANON_EOS_CustomFunc6:
1881                                 case PTP_DPC_CANON_EOS_CustomFunc7:
1882                                 case PTP_DPC_CANON_EOS_CustomFunc8:
1883                                 case PTP_DPC_CANON_EOS_CustomFunc9:
1884                                 case PTP_DPC_CANON_EOS_CustomFunc10:
1885                                 case PTP_DPC_CANON_EOS_CustomFunc11:
1886                                         dpd->DataType = PTP_DTC_UINT8;
1887                                         ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint8", i ,proptype, size-PTP_ece_Prop_Val_Data);
1888                                         for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1889                                                 ptp_debug (params, "    %d: %02x", j, xdata[j]);
1890                                         /* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */
1891                                         xdata += 4;
1892                                         break;
1893                                 /* yet unknown 32bit props */
1894                                 case PTP_DPC_CANON_EOS_ColorTemperature:
1895                                 case PTP_DPC_CANON_EOS_WftStatus:
1896                                 case PTP_DPC_CANON_EOS_LensStatus:
1897                                 case PTP_DPC_CANON_EOS_CardExtension:
1898                                 case PTP_DPC_CANON_EOS_TempStatus:
1899                                 case PTP_DPC_CANON_EOS_PhotoStudioMode:
1900                                 case PTP_DPC_CANON_EOS_DepthOfFieldPreview:
1901                                 case PTP_DPC_CANON_EOS_EVFSharpness:
1902                                 case PTP_DPC_CANON_EOS_EVFWBMode:
1903                                 case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
1904                                 case PTP_DPC_CANON_EOS_EVFColorTemp:
1905                                 case PTP_DPC_CANON_EOS_EVFRecordStatus:
1906                                 case PTP_DPC_CANON_EOS_ExposureSimMode:
1907                                 case PTP_DPC_CANON_EOS_LvAfSystem:
1908                                 case PTP_DPC_CANON_EOS_MovSize:
1909                                 case PTP_DPC_CANON_EOS_DepthOfField:
1910                                 case PTP_DPC_CANON_EOS_LvViewTypeSelect:
1911                                 case PTP_DPC_CANON_EOS_AloMode:
1912                                 case PTP_DPC_CANON_EOS_Brightness:
1913                                         dpd->DataType = PTP_DTC_UINT32;
1914                                         ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
1915                                         if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
1916                                                 ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
1917                                         for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
1918                                                 ptp_debug (params, "    %d: 0x%8x", j, ((uint32_t*)xdata)[j]);
1919                                         break;
1920                                 /* ImageFormat properties have to be ignored here, see special handling below */
1921                                 case PTP_DPC_CANON_EOS_ImageFormat:
1922                                 case PTP_DPC_CANON_EOS_ImageFormatCF:
1923                                 case PTP_DPC_CANON_EOS_ImageFormatSD:
1924                                 case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1925                                 case PTP_DPC_CANON_EOS_CustomFuncEx:
1926                                         break;
1927                                 default:
1928                                         ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
1929                                         for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1930                                                 ptp_debug (params, "    %d: %02x", j, xdata[j]);
1931                                         break;
1932                                 }
1933                                 switch (dpd->DataType) {
1934                                 case PTP_DTC_UINT32:
1935                                         dpd->FactoryDefaultValue.u32    = dtoh32a(xdata);
1936                                         dpd->CurrentValue.u32           = dtoh32a(xdata);
1937                                         ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
1938                                         break;
1939                                 case PTP_DTC_INT16:
1940                                         dpd->FactoryDefaultValue.i16    = dtoh16a(xdata);
1941                                         dpd->CurrentValue.i16           = dtoh16a(xdata);
1942                                         ptp_debug (params,"event %d: currentvalue of %x is %d", i, proptype, dpd->CurrentValue.i16);
1943                                         break;
1944                                 case PTP_DTC_UINT16:
1945                                         dpd->FactoryDefaultValue.u16    = dtoh16a(xdata);
1946                                         dpd->CurrentValue.u16           = dtoh16a(xdata);
1947                                         ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
1948                                         break;
1949                                 case PTP_DTC_UINT8:
1950                                         dpd->FactoryDefaultValue.u8     = dtoh8a(xdata);
1951                                         dpd->CurrentValue.u8            = dtoh8a(xdata);
1952                                         ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
1953                                         break;
1954                                 case PTP_DTC_STR: {
1955 #if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
1956                                         uint8_t len = 0;
1957                                         dpd->FactoryDefaultValue.str    = ptp_unpack_string(params, data, 0, &len);
1958                                         dpd->CurrentValue.str           = ptp_unpack_string(params, data, 0, &len);
1959 #else
1960                                         if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
1961                                         dpd->FactoryDefaultValue.str    = strdup( (char*)xdata );
1962
1963                                         if (dpd->CurrentValue.str) free (dpd->CurrentValue.str);
1964                                         dpd->CurrentValue.str           = strdup( (char*)xdata );
1965 #endif
1966                                         ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
1967                                         break;
1968                                 }
1969                                 default:
1970                                         /* debug is printed in switch above this one */
1971                                         break;
1972                                 }
1973
1974                                 /* ImageFormat and customFuncEx special handling (WARNING: dont move this in front of the dpd->DataType switch!) */
1975                                 switch (proptype) {
1976                                 case PTP_DPC_CANON_EOS_ImageFormat:
1977                                 case PTP_DPC_CANON_EOS_ImageFormatCF:
1978                                 case PTP_DPC_CANON_EOS_ImageFormatSD:
1979                                 case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1980                                         dpd->DataType = PTP_DTC_UINT16;
1981                                         dpd->FactoryDefaultValue.u16    = ptp_unpack_EOS_ImageFormat( params, &xdata );
1982                                         dpd->CurrentValue.u16           = dpd->FactoryDefaultValue.u16;
1983                                         ptp_debug (params,"event %d: decoded imageformat, currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
1984                                         break;
1985                                 case PTP_DPC_CANON_EOS_CustomFuncEx:
1986                                         dpd->DataType = PTP_DTC_STR;
1987                                         if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
1988                                         if (dpd->CurrentValue.str)        free (dpd->CurrentValue.str);
1989                                         dpd->FactoryDefaultValue.str    = ptp_unpack_EOS_CustomFuncEx( params, &data );
1990                                         dpd->CurrentValue.str           = strdup( (char*)dpd->FactoryDefaultValue.str );
1991                                         ptp_debug (params,"event %d: decoded custom function, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
1992                                         break;
1993                                 }
1994
1995                                 break;
1996                 }
1997                 /* one more information record handed to us */
1998                 case PTP_EC_CANON_EOS_OLCInfoChanged: {
1999                         uint32_t                len, curoff;
2000                         uint16_t                mask,proptype;
2001                         unsigned int            j;
2002                         PTPDevicePropDesc       *dpd;
2003
2004                         /* unclear what OLC stands for */
2005                         ptp_debug (params, "event %d: EOS event OLCInfoChanged (size %d)", i, size);
2006                         if (size >= 0x8) {      /* event info */
2007                                 unsigned int j;
2008                                 for (j=8;j<size;j++)
2009                                         ptp_debug (params, "    %d: %02x", j-8, curdata[j]);
2010                         }
2011                         len = dtoh32a(curdata+8);
2012                         if (len != size-8) {
2013                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2014                                 ptp_debug (params, "event %d: size %d, len %d", i, size, len);
2015                                 break;
2016                         }
2017                         mask = dtoh16a(curdata+8+4);
2018                         curoff = 8+4+4;
2019                         if (mask & CANON_EOS_OLC_BUTTON) {
2020                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2021                                 ce[i].u.info = malloc(strlen("Button 1234567"));
2022                                 sprintf(ce[i].u.info, "Button %d",  dtoh16a(curdata+curoff));
2023                                 i++;
2024                                 curoff += 2;
2025                         }
2026                         
2027                         if (mask & CANON_EOS_OLC_SHUTTERSPEED) {
2028                                 /* 6 bytes: 01 01 98 10 00 60 */
2029                                 /* this seesm to be the shutter speed record */
2030                                 proptype = PTP_DPC_CANON_EOS_ShutterSpeed;
2031                                 for (j=0;j<params->nrofcanon_props;j++)
2032                                         if (params->canon_props[j].proptype == proptype)
2033                                                 break;
2034                                 if (j == params->nrofcanon_props)
2035                                         ptp_debug (params, "event %d: shutterspeed not found yet, handle this", i);
2036
2037                                 dpd = &params->canon_props[j].dpd;
2038                                 dpd->CurrentValue.u16 = curdata[curoff+5]; /* just use last byte */
2039
2040                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
2041                                 ce[i].u.propid = proptype;
2042                                 curoff += 6;
2043                                 i++;
2044                         }
2045                         if (mask & CANON_EOS_OLC_APERTURE) {
2046                                 /* 5 bytes: 01 01 5b 30 30 */
2047                                 /* this seesm to be the aperture record */
2048                                 proptype = PTP_DPC_CANON_EOS_Aperture;
2049                                 for (j=0;j<params->nrofcanon_props;j++)
2050                                         if (params->canon_props[j].proptype == proptype)
2051                                                 break;
2052                                 if (j == params->nrofcanon_props)
2053                                         ptp_debug (params, "event %d: shutterspeed not found yet, handle this", i);
2054
2055                                 dpd = &params->canon_props[j].dpd;
2056                                 dpd->CurrentValue.u16 = curdata[curoff+4]; /* just use last byte */
2057
2058                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
2059                                 ce[i].u.propid = proptype;
2060                                 curoff += 5;
2061                                 i++;
2062                         }
2063                         if (mask & CANON_EOS_OLC_ISO) {
2064                                 /* 5 bytes: 01 01 00 78 */
2065                                 /* this seesm to be the aperture record */
2066                                 proptype = PTP_DPC_CANON_EOS_ISOSpeed;
2067                                 for (j=0;j<params->nrofcanon_props;j++)
2068                                         if (params->canon_props[j].proptype == proptype)
2069                                                 break;
2070                                 if (j == params->nrofcanon_props)
2071                                         ptp_debug (params, "event %d: shutterspeed not found yet, handle this", i);
2072
2073                                 dpd = &params->canon_props[j].dpd;
2074                                 dpd->CurrentValue.u16 = curdata[curoff+3]; /* just use last byte */
2075
2076                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
2077                                 ce[i].u.propid = proptype;
2078                                 curoff += 4;
2079                                 i++;
2080                         }
2081                         if (mask & 0x0010) {
2082                                 /* mask 0x0010: 4 bytes, 04 00 00 00 observed */
2083                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2084                                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0010 content 01234567")+1); 
2085                                 sprintf(ce[i].u.info,"OLCInfo event 0x0010 content %02x%02x%02x%02x",
2086                                         curdata[curoff],
2087                                         curdata[curoff+1],
2088                                         curdata[curoff+2],
2089                                         curdata[curoff+3]
2090                                 );
2091                                 curoff += 4;
2092                                 i++;
2093                         }
2094                         if (mask & 0x0020) {
2095                                 /* mask 0x0020: 6 bytes, 00 00 00 00 00 00 observed */
2096                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2097                                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0020 content 0123456789ab")+1); 
2098                                 sprintf(ce[i].u.info,"OLCInfo event 0x0020 content %02x%02x%02x%02x%02x%02x",
2099                                         curdata[curoff],
2100                                         curdata[curoff+1],
2101                                         curdata[curoff+2],
2102                                         curdata[curoff+3],
2103                                         curdata[curoff+4],
2104                                         curdata[curoff+5]
2105                                 );
2106                                 curoff += 6;
2107                                 i++;
2108                         }
2109                         if (mask & 0x0040) {
2110                                 /* mask 0x0040: 7 bytes, 01 01 00 00 00 00 00 observed */
2111                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2112                                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0040 content 0123456789abcd")+1); 
2113                                 sprintf(ce[i].u.info,"OLCInfo event 0x0040 content %02x%02x%02x%02x%02x%02x%02x",
2114                                         curdata[curoff],
2115                                         curdata[curoff+1],
2116                                         curdata[curoff+2],
2117                                         curdata[curoff+3],
2118                                         curdata[curoff+4],
2119                                         curdata[curoff+5],
2120                                         curdata[curoff+6]
2121                                 );
2122                                 curoff += 7;
2123                                 i++;
2124                         }
2125                         if (mask & 0x0080) {
2126                                 /* mask 0x0080: 4 bytes, 00 00 00 00 observed */
2127                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2128                                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0080 content 01234567")+1); 
2129                                 sprintf(ce[i].u.info,"OLCInfo event 0x0080 content %02x%02x%02x%02x",
2130                                         curdata[curoff],
2131                                         curdata[curoff+1],
2132                                         curdata[curoff+2],
2133                                         curdata[curoff+3]
2134                                 );
2135                                 curoff += 4;
2136                                 i++;
2137                         }
2138                         if (mask & 0x0100) {
2139                                 /* mask 0x0100: 6 bytes, 00 00 00 00 00 00 (before focus) and 00 00 00 00 01 00 (on focus) observed */
2140                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2141                                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0100 content 0123456789ab")+1); 
2142                                 sprintf(ce[i].u.info,"OLCInfo event 0x0100 content %02x%02x%02x%02x%02x%02x",
2143                                         curdata[curoff],
2144                                         curdata[curoff+1],
2145                                         curdata[curoff+2],
2146                                         curdata[curoff+3],
2147                                         curdata[curoff+4],
2148                                         curdata[curoff+5]
2149                                 );
2150                                 curoff += 6;
2151                                 i++;
2152                         }
2153                         if (mask & 0x0200) {
2154                                 /* mask 0x0200: 7 bytes, 00 00 00 00 00 00 00 observed */
2155                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2156                                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0200 content 0123456789abcd")+1); 
2157                                 sprintf(ce[i].u.info,"OLCInfo event 0x0200 content %02x%02x%02x%02x%02x%02x%02x",
2158                                         curdata[curoff],
2159                                         curdata[curoff+1],
2160                                         curdata[curoff+2],
2161                                         curdata[curoff+3],
2162                                         curdata[curoff+4],
2163                                         curdata[curoff+5],
2164                                         curdata[curoff+6]
2165                                 );
2166                                 curoff += 7;
2167                                 i++;
2168                         }
2169                         if (mask & 0x0400) {
2170                                 /* mask 0x0400: 7 bytes, 00 00 00 00 00 00 00 observed */
2171                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2172                                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0400 content 0123456789abcd")+1); 
2173                                 sprintf(ce[i].u.info,"OLCInfo event 0x0400 content %02x%02x%02x%02x%02x%02x%02x",
2174                                         curdata[curoff],
2175                                         curdata[curoff+1],
2176                                         curdata[curoff+2],
2177                                         curdata[curoff+3],
2178                                         curdata[curoff+4],
2179                                         curdata[curoff+5],
2180                                         curdata[curoff+6]
2181                                 );
2182                                 curoff += 7;
2183                                 i++;
2184                         }
2185                         if (mask & 0x0800) {
2186                                 /* mask 0x0800: 8 bytes, 00 00 00 00 00 00 00 00 and 19 01 00 00 00 00 00 00 and others observed */
2187                                 /*   might be mask of focus points selected */
2188                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2189                                 ce[i].u.info = malloc(strlen("OLCInfo event 0x0800 content 0123456789abcdef")+1); 
2190                                 sprintf(ce[i].u.info,"OLCInfo event 0x0800 content %02x%02x%02x%02x%02x%02x%02x%02x",
2191                                         curdata[curoff],
2192                                         curdata[curoff+1],
2193                                         curdata[curoff+2],
2194                                         curdata[curoff+3],
2195                                         curdata[curoff+4],
2196                                         curdata[curoff+5],
2197                                         curdata[curoff+6],
2198                                         curdata[curoff+7]
2199                                 );
2200                                 curoff += 8;
2201                                 i++;
2202                         }
2203                         if (mask & 0x1000) {
2204                                 /* mask 0x1000: 1 byte, 00 observed */
2205                                 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2206                                 ce[i].u.info = malloc(strlen("OLCInfo event 0x1000 content 01")+1); 
2207                                 sprintf(ce[i].u.info,"OLCInfo event 0x1000 content %02x",
2208                                         curdata[curoff]
2209                                 );
2210                                 curoff += 1;
2211                                 i++;
2212                         }
2213                         /* handle more masks */
2214                         ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2215                         ce[i].u.info = malloc(strlen("OLCInfo event mask 0123456789")+1);
2216                         sprintf(ce[i].u.info, "OLCInfo event mask=%x",  mask);
2217                         break;
2218                 }
2219                 case PTP_EC_CANON_EOS_CameraStatusChanged:
2220                         ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS;
2221                         ce[i].u.status =  dtoh32a(curdata+8);
2222                         ptp_debug (params, "event %d: EOS event CameraStatusChanged (size %d) = %d", i, size, dtoh32a(curdata+8));
2223                         params->eos_camerastatus = dtoh32a(curdata+8);
2224                         break;
2225                 case 0: /* end marker */
2226                         if (size == 8) /* no output */
2227                                 break;
2228                         ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
2229                         break;
2230                 case PTP_EC_CANON_EOS_BulbExposureTime:
2231                         ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2232                         ce[i].u.info = malloc(strlen("BulbExposureTime 123456789"));
2233                         sprintf (ce[i].u.info, "BulbExposureTime %d",  dtoh32a(curdata+8));
2234                         break;
2235                 default:
2236                         switch (type) {
2237 #define XX(x)           case PTP_EC_CANON_EOS_##x:                                                              \
2238                                 ptp_debug (params, "event %d: unhandled EOS event "#x" (size %d)", i, size);    \
2239                                 ce[i].u.info = malloc(strlen("unhandled EOS event "#x" (size 123456789)"));     \
2240                                 sprintf (ce[i].u.info, "unhandled EOS event "#x" (size %d)",  size);            \
2241                                 break;
2242                         XX(RequestGetEvent)
2243                         XX(ObjectRemoved)
2244                         XX(RequestGetObjectInfoEx)
2245                         XX(StorageStatusChanged)
2246                         XX(StorageInfoChanged)
2247                         XX(ObjectInfoChangedEx)
2248                         XX(ObjectContentChanged)
2249                         XX(WillSoonShutdown)
2250                         XX(ShutdownTimerUpdated)
2251                         XX(RequestCancelTransfer)
2252                         XX(RequestObjectTransferDT)
2253                         XX(RequestCancelTransferDT)
2254                         XX(StoreAdded)
2255                         XX(StoreRemoved)
2256                         XX(BulbExposureTime)
2257                         XX(RecordingTime)
2258                         XX(RequestObjectTransferTS)
2259                         XX(AfResult)
2260 #undef XX
2261                         default:
2262                                 ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
2263                                 break;
2264                         }
2265                         if (size >= 0x8) {      /* event info */
2266                                 unsigned int j;
2267                                 for (j=8;j<size;j++)
2268                                         ptp_debug (params, "    %d: %02x", j, curdata[j]);
2269                         }
2270                         ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2271                         break;
2272                 }
2273                 curdata += size;
2274                 if ((size == 8) && (type == 0))
2275                         break;
2276                 i++;
2277         }
2278         if (!i) {
2279                 free (ce);
2280                 ce = NULL;
2281         }
2282         *pce = ce;
2283         return i;
2284 }
2285
2286 /*
2287     PTP USB Event container unpack for Nikon events.
2288 */
2289 #define PTP_nikon_ec_Length             0
2290 #define PTP_nikon_ec_Code               2
2291 #define PTP_nikon_ec_Param1             4
2292 #define PTP_nikon_ec_Size               6
2293 static inline void
2294 ptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, unsigned int *cnt)
2295 {
2296         unsigned int i;
2297
2298         *ec = NULL;
2299         if (data == NULL)
2300                 return;
2301         if (len < PTP_nikon_ec_Code)
2302                 return;
2303         *cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
2304         if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
2305                 return;
2306         if (!*cnt)
2307                 return;
2308
2309         *ec = malloc(sizeof(PTPContainer)*(*cnt));
2310         
2311         for (i=0;i<*cnt;i++) {
2312                 memset(&(*ec)[i],0,sizeof(PTPContainer));
2313                 (*ec)[i].Code   = dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
2314                 (*ec)[i].Param1 = dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
2315                 (*ec)[i].Nparam = 1;
2316         }
2317 }
2318
2319
2320 static inline uint32_t
2321 ptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
2322         int i, len = 0;
2323         uint8_t retlen;
2324         unsigned char *curdata;
2325
2326         len =   2*(strlen(text->title)+1)+1+
2327                 2*(strlen(text->line[0])+1)+1+
2328                 2*(strlen(text->line[1])+1)+1+
2329                 2*(strlen(text->line[2])+1)+1+
2330                 2*(strlen(text->line[3])+1)+1+
2331                 2*(strlen(text->line[4])+1)+1+
2332                 4*2+2*4+2+4+2+5*4*2;
2333         *data = malloc(len);
2334         if (!*data) return 0;
2335
2336         curdata = *data;
2337         htod16a(curdata,100);curdata+=2;
2338         htod16a(curdata,1);curdata+=2;
2339         htod16a(curdata,0);curdata+=2;
2340         htod16a(curdata,1000);curdata+=2;
2341
2342         htod32a(curdata,0);curdata+=4;
2343         htod32a(curdata,0);curdata+=4;
2344
2345         htod16a(curdata,6);curdata+=2;
2346         htod32a(curdata,0);curdata+=4;
2347
2348         ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
2349         htod16a(curdata,0x10);curdata+=2;
2350         
2351         for (i=0;i<5;i++) {
2352                 ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
2353                 htod16a(curdata,0x10);curdata+=2;
2354                 htod16a(curdata,0x01);curdata+=2;
2355                 htod16a(curdata,0x02);curdata+=2;
2356                 htod16a(curdata,0x06);curdata+=2;
2357         }
2358         return len;
2359 }
2360
2361 #define ptp_canon_dir_version   0x00
2362 #define ptp_canon_dir_ofc       0x02
2363 #define ptp_canon_dir_unk1      0x04
2364 #define ptp_canon_dir_objectid  0x08
2365 #define ptp_canon_dir_parentid  0x0c
2366 #define ptp_canon_dir_previd    0x10    /* in same dir */
2367 #define ptp_canon_dir_nextid    0x14    /* in same dir */
2368 #define ptp_canon_dir_nextchild 0x18    /* down one dir */
2369 #define ptp_canon_dir_storageid 0x1c    /* only in storage entry */
2370 #define ptp_canon_dir_name      0x20
2371 #define ptp_canon_dir_flags     0x2c
2372 #define ptp_canon_dir_size      0x30
2373 #define ptp_canon_dir_unixtime  0x34
2374 #define ptp_canon_dir_year      0x38
2375 #define ptp_canon_dir_month     0x39
2376 #define ptp_canon_dir_mday      0x3a
2377 #define ptp_canon_dir_hour      0x3b
2378 #define ptp_canon_dir_minute    0x3c
2379 #define ptp_canon_dir_second    0x3d
2380 #define ptp_canon_dir_unk2      0x3e
2381 #define ptp_canon_dir_thumbsize 0x40
2382 #define ptp_canon_dir_width     0x44
2383 #define ptp_canon_dir_height    0x48
2384
2385 static inline uint16_t
2386 ptp_unpack_canon_directory (
2387         PTPParams               *params,
2388         unsigned char           *dir,
2389         uint32_t                cnt,
2390         PTPObjectHandles        *handles,
2391         PTPObjectInfo           **oinfos,       /* size(handles->n) */
2392         uint32_t                **flags         /* size(handles->n) */
2393 ) {
2394         unsigned int    i, j, nrofobs = 0, curob = 0;
2395
2396 #define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
2397         for (i=0;i<cnt;i++)
2398                 if (ISOBJECT(dir+i*0x4c)) nrofobs++;
2399         handles->n = nrofobs;
2400         handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs);
2401         if (!handles->Handler) return PTP_RC_GeneralError;
2402         *oinfos = calloc(sizeof((*oinfos)[0]),nrofobs);
2403         if (!*oinfos) return PTP_RC_GeneralError;
2404         *flags  = calloc(sizeof((*flags)[0]),nrofobs);
2405         if (!*flags) return PTP_RC_GeneralError;
2406
2407         /* Migrate data into objects ids, handles into
2408          * the object handler array.
2409          */
2410         curob = 0;
2411         for (i=0;i<cnt;i++) {
2412                 unsigned char   *cur = dir+i*0x4c;
2413                 PTPObjectInfo   *oi = (*oinfos)+curob;
2414
2415                 if (!ISOBJECT(cur))
2416                         continue;
2417
2418                 handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
2419                 oi->StorageID           = 0xffffffff;
2420                 oi->ObjectFormat        = dtoh16a(cur + ptp_canon_dir_ofc);
2421                 oi->ParentObject        = dtoh32a(cur + ptp_canon_dir_parentid);
2422                 oi->Filename            = strdup((char*)(cur + ptp_canon_dir_name));
2423                 oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
2424                 oi->ThumbCompressedSize = dtoh32a(cur + ptp_canon_dir_thumbsize);
2425                 oi->ImagePixWidth       = dtoh32a(cur + ptp_canon_dir_width);
2426                 oi->ImagePixHeight      = dtoh32a(cur + ptp_canon_dir_height);
2427                 oi->CaptureDate         = oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
2428                 (*flags)[curob]         = dtoh32a(cur + ptp_canon_dir_flags);
2429                 curob++;
2430         }
2431         /* Walk over Storage ID entries and distribute the IDs to
2432          * the parent objects. */
2433         for (i=0;i<cnt;i++) {
2434                 unsigned char   *cur = dir+i*0x4c;
2435                 uint32_t        nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
2436
2437                 if (ISOBJECT(cur))
2438                         continue;
2439                 for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
2440                 if (j == handles->n) continue;
2441                 (*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
2442         }
2443         /* Walk over all objects and distribute the storage ids */
2444         while (1) {
2445                 unsigned int changed = 0;
2446                 for (i=0;i<cnt;i++) {
2447                         unsigned char   *cur = dir+i*0x4c;
2448                         uint32_t        oid = dtoh32a(cur + ptp_canon_dir_objectid);
2449                         uint32_t        nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
2450                         uint32_t        nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
2451                         uint32_t        storageid;
2452
2453                         if (!ISOBJECT(cur))
2454                                 continue;
2455                         for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
2456                         if (j == handles->n) {
2457                                 /*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
2458                                 continue;
2459                         }
2460                         storageid = (*oinfos)[j].StorageID;
2461                         if (storageid == 0xffffffff) continue;
2462                         if (nextoid != 0xffffffff) {
2463                                 for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
2464                                 if (j == handles->n) {
2465                                         /*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
2466                                         continue;
2467                                 }
2468                                 if ((*oinfos)[j].StorageID == 0xffffffff) {
2469                                         (*oinfos)[j].StorageID = storageid;
2470                                         changed++;
2471                                 }
2472                         }
2473                         if (nextchild != 0xffffffff) {
2474                                 for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
2475                                 if (j == handles->n) {
2476                                         /*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
2477                                         continue;
2478                                 }
2479                                 if ((*oinfos)[j].StorageID == 0xffffffff) {
2480                                         (*oinfos)[j].StorageID = storageid;
2481                                         changed++;
2482                                 }
2483                         }
2484                 }
2485                 /* Check if we:
2486                  * - changed no entry (nothing more to do)
2487                  * - changed all of them at once (usually happens)
2488                  * break if we do.
2489                  */
2490                 if (!changed || (changed==nrofobs-1))
2491                         break;
2492         }
2493 #undef ISOBJECT
2494         return PTP_RC_OK;
2495 }