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>
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.
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.
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
25 /* currently this file is included into ptp.c */
31 # define UINT_MAX 0xFFFFFFFF
37 static inline uint16_t
38 htod16p (PTPParams *params, uint16_t var)
40 return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
43 static inline uint32_t
44 htod32p (PTPParams *params, uint32_t var)
46 return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
50 htod16ap (PTPParams *params, unsigned char *a, uint16_t val)
52 if (params->byteorder==PTP_DL_LE)
59 htod32ap (PTPParams *params, unsigned char *a, uint32_t val)
61 if (params->byteorder==PTP_DL_LE)
68 htod64ap (PTPParams *params, unsigned char *a, uint64_t val)
70 if (params->byteorder==PTP_DL_LE)
76 static inline uint16_t
77 dtoh16p (PTPParams *params, uint16_t var)
79 return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
82 static inline uint32_t
83 dtoh32p (PTPParams *params, uint32_t var)
85 return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
88 static inline uint64_t
89 dtoh64p (PTPParams *params, uint64_t var)
91 return ((params->byteorder==PTP_DL_LE)?le64toh(var):be64toh(var));
94 static inline uint16_t
95 dtoh16ap (PTPParams *params, const unsigned char *a)
97 return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
100 static inline uint32_t
101 dtoh32ap (PTPParams *params, const unsigned char *a)
103 return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
106 static inline uint64_t
107 dtoh64ap (PTPParams *params, const unsigned char *a)
109 return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a));
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)
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)
130 ptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
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;
139 length = dtoh8a(&data[offset]); /* PTP_MAXSTRLEN == 255, 8 bit len */
141 if (length == 0) /* nothing to do? */
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. */
149 /* convert from camera UCS-2 to our locale */
150 src = (char *)string;
151 srclen = length * sizeof(string[0]);
153 destlen = sizeof(loclstr)-1;
156 if (params->cd_ucs2_to_locale != (iconv_t)-1)
157 nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen, &dest, &destlen);
159 if (nconv == (size_t) -1) { /* do it the hard way */
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)
166 loclstr[i] = dtoh16a(&data[offset+1+2*i]);
168 dest = loclstr+length;
171 loclstr[sizeof(loclstr)-1] = '\0'; /* be safe? */
172 return(strdup(loclstr));
176 ucs2strlen(uint16_t const * const unicstr)
180 /* Unicode strings are terminated with 2 * 0x00 */
181 for(length = 0; unicstr[length] != 0x0000U; length ++);
187 ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
190 uint16_t ucs2str[PTP_MAXSTRLEN+1];
191 char *ucs2strp = (char *) ucs2str;
192 size_t convlen = strlen(string);
194 /* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
195 memset(ucs2strp, 0, sizeof(ucs2str)); /* XXX: necessary? */
197 if (params->cd_locale_to_ucs2 != (iconv_t)-1) {
199 size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
200 char *stringp = string;
202 nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
203 &ucs2strp, &convmax);
204 if (nconv == (size_t) -1)
205 ucs2str[0] = 0x0000U;
211 for (i=0;i<convlen;i++) {
212 ucs2str[i] = string[i];
214 ucs2str[convlen] = 0;
217 * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
218 * why do we need ucs2strlen()?
220 packedlen = ucs2strlen(ucs2str);
221 if (packedlen > PTP_MAXSTRLEN-1) {
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 */
231 /* The returned length is in number of characters */
232 *len = (uint8_t) packedlen+1;
235 static inline unsigned char *
236 ptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
238 uint8_t packed[PTP_MAXSTRLEN*2+3], len;
240 unsigned char *retcopy = NULL;
243 ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
245 ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
247 /* returned length is in characters, then one byte for string length */
250 retcopy = malloc(plen);
255 memcpy(retcopy, packed, plen);
260 static inline uint32_t
261 ptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
266 n=dtoh32a(&data[offset]);
267 if (n >= UINT_MAX/sizeof(uint32_t))
271 *array = malloc (n*sizeof(uint32_t));
273 (*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
277 static inline uint32_t
278 ptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
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);
289 static inline uint32_t
290 ptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
295 n=dtoh32a(&data[offset]);
296 if (n >= UINT_MAX/sizeof(uint16_t))
300 *array = malloc (n*sizeof(uint16_t));
302 (*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
306 /* DeviceInfo pack/unpack */
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
316 ptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
319 unsigned int totallen;
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);
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,
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,
359 di->Model = ptp_unpack_string(params, data,
360 PTP_di_OperationsSupported+totallen,
363 di->DeviceVersion = ptp_unpack_string(params, data,
364 PTP_di_OperationsSupported+totallen,
367 di->SerialNumber = ptp_unpack_string(params, data,
368 PTP_di_OperationsSupported+totallen,
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);
386 /* EOS Device Info unpack */
388 ptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
390 unsigned int totallen = 4;
392 memset (di,0, sizeof(*di));
393 if (datalen < 8) return;
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;
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;
408 di->unk_len = ptp_unpack_uint32_t_array(params, data,
410 if (!di->unk) return;
411 totallen += di->unk_len*sizeof(uint32_t)+4;
416 ptp_free_EOS_DI (PTPCanonEOSDeviceInfo *di)
418 free (di->EventsSupported);
419 free (di->DevicePropertiesSupported);
423 /* ObjectHandles array pack/unpack */
428 ptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
431 oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
438 /* StoreIDs array pack/unpack */
443 ptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
447 sids->Storage = NULL;
450 sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
454 /* StorageInfo pack/unpack */
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
465 ptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
467 uint8_t storagedescriptionlen;
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);
482 /* ObjectInfo pack/unpack */
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
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
506 static inline uint32_t
507 ptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
509 unsigned char* oidata;
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);
515 /* the caller should free it after use! */
517 char *capture_date="20020101T010101"; /* XXX Fake date */
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);
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);
538 ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
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];
548 * for example Kodak sets Capture date on the basis of EXIF data.
549 * Spec says that this field is from perspective of Initiator.
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],
555 for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
556 data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
558 htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
560 for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
561 data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
565 /* XXX this function should return dataset length */
566 return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3)+params->ocs64*4;
570 ptp_unpack_PTPTIME (const char *str) {
578 ptpdatelen = strlen(str);
579 if (ptpdatelen >= sizeof (ptpdate)) {
580 /*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
584 /*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
587 strncpy (ptpdate, str, sizeof(ptpdate));
588 ptpdate[sizeof(ptpdate) - 1] = '\0';
590 memset(&tm,0,sizeof(tm));
591 strncpy (tmp, ptpdate, 4);
593 tm.tm_year=atoi (tmp) - 1900;
594 strncpy (tmp, ptpdate + 4, 2);
596 tm.tm_mon = atoi (tmp) - 1;
597 strncpy (tmp, ptpdate + 6, 2);
599 tm.tm_mday = atoi (tmp);
600 strncpy (tmp, ptpdate + 9, 2);
602 tm.tm_hour = atoi (tmp);
603 strncpy (tmp, ptpdate + 11, 2);
605 tm.tm_min = atoi (tmp);
606 strncpy (tmp, ptpdate + 13, 2);
608 tm.tm_sec = atoi (tmp);
614 ptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
617 uint8_t capturedatelen;
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]);
625 /* Stupid Samsung Galaxy developers emit a 64bit objectcompressedsize */
626 if ((data[PTP_oi_filenamelen] == 0) && (data[PTP_oi_filenamelen+4] != 0)) {
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]);
642 oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
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
649 oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
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);
660 /* Custom Type Value Assignement (without Length) macro frequently used below */
661 #define CTVAL(target,func) { \
662 if (total - *offset < sizeof(target)) \
664 target = func(&data[*offset]); \
665 *offset += sizeof(target); \
668 #define RARR(val,member,func) { \
670 if (total - *offset < sizeof(uint32_t)) \
672 n = dtoh32a (&data[*offset]); \
673 *offset += sizeof(uint32_t); \
675 if (n >= UINT_MAX/sizeof(val->a.v[0])) \
678 val->a.v = malloc(sizeof(val->a.v[0])*n); \
679 if (!val->a.v) return 0; \
681 CTVAL(val->a.v[j].member, func); \
684 static inline unsigned int
686 PTPParams *params, unsigned char* data, unsigned int *offset, int total,
687 PTPPropertyValue* value, uint16_t datatype
691 CTVAL(value->i8,dtoh8a);
694 CTVAL(value->u8,dtoh8a);
697 CTVAL(value->i16,dtoh16a);
700 CTVAL(value->u16,dtoh16a);
703 CTVAL(value->i32,dtoh32a);
706 CTVAL(value->u32,dtoh32a);
709 CTVAL(value->i64,dtoh64a);
712 CTVAL(value->u64,dtoh64a);
715 case PTP_DTC_UINT128:
717 /*fprintf(stderr,"unhandled unpack of uint128n");*/
721 /*fprintf(stderr,"unhandled unpack of int128n");*/
727 RARR(value,i8,dtoh8a);
730 RARR(value,u8,dtoh8a);
732 case PTP_DTC_AUINT16:
733 RARR(value,u16,dtoh16a);
736 RARR(value,i16,dtoh16a);
738 case PTP_DTC_AUINT32:
739 RARR(value,u32,dtoh32a);
742 RARR(value,i32,dtoh32a);
744 case PTP_DTC_AUINT64:
745 RARR(value,u64,dtoh64a);
748 RARR(value,i64,dtoh64a);
750 /* XXX: other int types are unimplemented */
751 /* XXX: other int arrays are unimplemented also */
755 value->str = ptp_unpack_string(params,data,*offset,&len);
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
774 ptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
776 unsigned int offset = 0, ret;
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;
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))
789 ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
790 if (!ret) goto outofmemory;
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
797 if (offset==PTP_dpd_FactoryDefaultValue)
800 dpd->FormFlag=dtoh8a(&data[offset]);
801 offset+=sizeof(uint8_t);
803 switch (dpd->FormFlag) {
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;
812 case PTP_DPFF_Enumeration: {
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)
821 memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
823 ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
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.
833 dpd->FORM.Enum.NumberOfValues = i;
842 ptp_free_devicepropdesc(dpd);
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
854 ptp_unpack_Sony_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen, unsigned int *poffset)
858 memset (dpd, 0, sizeof(*dpd));
859 dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_Sony_DevicePropertyCode]);
860 dpd->DataType=dtoh16a(&data[PTP_dpd_Sony_DataType]);
863 dpd->GetSet=dtoh8a(&data[PTP_dpd_Sony_GetSet]);
867 dpd->FormFlag=PTP_DPFF_None;
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))
874 ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->CurrentValue, dpd->DataType);
875 if (!ret) goto outofmemory;
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
882 if (*poffset==PTP_dpd_Sony_FactoryDefaultValue)
885 dpd->FormFlag=dtoh8a(&data[*poffset]);
886 *poffset+=sizeof(uint8_t);
888 switch (dpd->FormFlag) {
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;
897 case PTP_DPFF_Enumeration: {
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)
906 memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
908 ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
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.
918 dpd->FORM.Enum.NumberOfValues = i;
927 ptp_free_devicepropdesc(dpd);
932 duplicate_PropertyValue (const PTPPropertyValue *src, PTPPropertyValue *dst, uint16_t type) {
933 if (type == PTP_DTC_STR) {
935 dst->str = strdup(src->str);
941 if (type & PTP_DTC_ARRAY_MASK) {
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);
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;
960 case PTP_DTC_INT128: dst->i128 = src->i128; break;
961 case PTP_DTC_UINT128: dst->u128 = src->u128; break;
969 duplicate_DevicePropDesc(const PTPDevicePropDesc *src, PTPDevicePropDesc *dst) {
972 dst->DevicePropertyCode = src->DevicePropertyCode;
973 dst->DataType = src->DataType;
974 dst->GetSet = src->GetSet;
976 duplicate_PropertyValue (&src->FactoryDefaultValue, &dst->FactoryDefaultValue, src->DataType);
977 duplicate_PropertyValue (&src->CurrentValue, &dst->CurrentValue, src->DataType);
979 dst->FormFlag = src->FormFlag;
980 switch (src->FormFlag) {
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);
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);
997 #define PTP_opd_ObjectPropertyCode 0
998 #define PTP_opd_DataType 2
999 #define PTP_opd_GetSet 4
1000 #define PTP_opd_FactoryDefaultValue 5
1003 ptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
1005 unsigned int offset=0, ret;
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]);
1012 offset = PTP_opd_FactoryDefaultValue;
1013 ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
1014 if (!ret) goto outofmemory;
1016 opd->GroupCode=dtoh32a(&data[offset]);
1017 offset+=sizeof(uint32_t);
1019 opd->FormFlag=dtoh8a(&data[offset]);
1020 offset+=sizeof(uint8_t);
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;
1031 case PTP_OPFF_Enumeration: {
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)
1040 memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
1042 ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
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.
1052 opd->FORM.Enum.NumberOfValues = i;
1061 ptp_free_objectpropdesc(opd);
1066 static inline uint32_t
1067 ptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
1069 unsigned char* dpv=NULL;
1075 size=sizeof(int8_t);
1077 htod8a(dpv,value->i8);
1080 size=sizeof(uint8_t);
1082 htod8a(dpv,value->u8);
1085 size=sizeof(int16_t);
1087 htod16a(dpv,value->i16);
1089 case PTP_DTC_UINT16:
1090 size=sizeof(uint16_t);
1092 htod16a(dpv,value->u16);
1095 size=sizeof(int32_t);
1097 htod32a(dpv,value->i32);
1099 case PTP_DTC_UINT32:
1100 size=sizeof(uint32_t);
1102 htod32a(dpv,value->u32);
1105 size=sizeof(int64_t);
1107 htod64a(dpv,value->i64);
1109 case PTP_DTC_UINT64:
1110 size=sizeof(uint64_t);
1112 htod64a(dpv,value->u64);
1114 case PTP_DTC_AUINT8:
1115 size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
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);
1122 size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
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);
1128 case PTP_DTC_AUINT16:
1129 size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
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);
1135 case PTP_DTC_AINT16:
1136 size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
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);
1142 case PTP_DTC_AUINT32:
1143 size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
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);
1149 case PTP_DTC_AINT32:
1150 size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
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);
1156 case PTP_DTC_AUINT64:
1157 size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
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);
1163 case PTP_DTC_AINT64:
1164 size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
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);
1170 /* XXX: other int types are unimplemented */
1172 dpv=ptp_get_packed_stringcopy(params, value->str, &size);
1180 #define MAX_MTP_PROPS 127
1181 static inline uint32_t
1182 ptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
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;
1193 uint32_t noitems = 0;
1196 totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
1198 while (nrofprops-- && noitems < MAX_MTP_PROPS) {
1200 packedobjecthandles[noitems]=propitr->ObjectHandle;
1201 totalsize += sizeof(uint32_t); /* Object ID */
1203 packedpropsids[noitems]=propitr->property;
1204 totalsize += sizeof(uint16_t);
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];
1215 /* Allocate memory for the packed property list */
1216 opldata = malloc(totalsize);
1218 htod32a(&opldata[bufp],noitems);
1221 /* Copy into a nice packed list */
1222 for (i = 0; i < noitems; i++) {
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]);
1235 *opldataptr = opldata;
1240 _compare_func(const void* x, const void *y) {
1241 const MTPProperties *px = x;
1242 const MTPProperties *py = y;
1244 return px->ObjectHandle - py->ObjectHandle;
1248 ptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
1250 uint32_t prop_count = dtoh32a(data);
1251 MTPProperties *props = NULL;
1252 unsigned int offset = 0, i;
1254 if (prop_count == 0) {
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++) {
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);
1272 props[i].ObjectHandle = dtoh32a(data);
1273 data += sizeof(uint32_t);
1274 len -= sizeof(uint32_t);
1276 props[i].property = dtoh16a(data);
1277 data += sizeof(uint16_t);
1278 len -= sizeof(uint16_t);
1280 props[i].datatype = dtoh16a(data);
1281 data += sizeof(uint16_t);
1282 len -= sizeof(uint16_t);
1285 ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype);
1289 qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
1295 PTP USB Event container unpack
1296 Copyright (c) 2003 Nikolai Kopanygin
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
1308 ptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
1310 unsigned int length;
1315 memset(ec,0,sizeof(*ec));
1317 length=dtoh32a(&data[PTP_ec_Length]);
1319 ptp_debug (params, "length %d in container, but data only %d bytes?!", length, len);
1322 type = dtoh16a(&data[PTP_ec_Type]);
1324 ec->Code=dtoh16a(&data[PTP_ec_Code]);
1325 ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
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);
1331 if (length>=(PTP_ec_Param1+4)) {
1332 ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
1335 if (length>=(PTP_ec_Param2+4)) {
1336 ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
1339 if (length>=(PTP_ec_Param3+4)) {
1340 ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
1346 PTP Canon Folder Entry unpack
1347 Copyright (c) 2003 Nikolai Kopanygin
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
1357 ptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
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]);
1372 PTP Canon EOS Folder Entry unpack
1373 0: 00 00 08 a0 objectid
1374 4: 01 00 02 00 storageid
1382 32: 4d 49 53 43-00 00 00 00 00 00 00 00 name
1384 84 bc 74 46 objectime
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
1395 ThumbCompressedSize: 5122
1399 ImagePixHeight: 3000
1401 ParentObject: 0x92740000
1402 AssociationType: 0x0000
1403 AssociationDesc: 0x00000000
1404 SequenceNumber: 0x00000000
1405 ModificationDate: 0x4d985ff0
1406 CaptureDate: 0x4d985ff0
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
1415 0030 70 0c 74 92 OID
1416 0034 49 4d 47 5f-30 31 39 39 2e 4a 50 47 IMG_0199.JPG
1418 0044 10 7c 98 4d Time
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
1431 ptp_unpack_Canon_EOS_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
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];
1445 static inline uint16_t
1446 ptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
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.
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.
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.
1474 const unsigned char* d = *data;
1475 uint32_t n = dtoh32a( d );
1476 uint32_t l, s1, c1, s2 = 0, c2 = 0;
1478 if (n != 1 && n !=2) {
1479 ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
1483 l = dtoh32a( d+=4 );
1485 ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
1489 d+=4; /* skip type */
1490 s1 = dtoh32a( d+=4 );
1491 c1 = dtoh32a( d+=4 );
1494 l = dtoh32a( d+=4 );
1496 ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
1499 d+=4; /* skip type */
1500 s2 = dtoh32a( d+=4 );
1501 c2 = dtoh32a( d+=4 );
1504 *data = (unsigned char*) d+4;
1506 /* deal with S1/S2/S3 JPEG sizes, see above. */
1512 return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
1515 static inline uint32_t
1516 ptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
1518 uint32_t n = (value & 0xFF) ? 2 : 1;
1519 uint32_t s = 4 + 0x10 * n;
1524 #define PACK_5DM3_SMALL_JPEG_SIZE( X ) (X) >= 0xd ? (X)+1 : (X)
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);
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);
1539 #undef PACK_5DM3_SMALL_JPEG_SIZE
1545 ptp_unpack_EOS_CustomFuncEx (PTPParams* params, unsigned char** data )
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*/
1554 for (i=0; i < n; ++i)
1555 p += sprintf(p, "%x,", dtoh32a( *data + 4*i ));
1560 static inline uint32_t
1561 ptp_pack_EOS_CustomFuncEx (PTPParams* params, unsigned char* data, char* str)
1563 uint32_t s = strtoul(str, NULL, 16);
1564 uint32_t n = s/4, i, v;
1571 v = strtoul(str, &str, 16);
1572 str++; /* skip the ',' delimiter */
1573 htod32a(data + i*4, v);
1580 PTP EOS Changes Entry unpack
1582 #define PTP_ece_Size 0
1583 #define PTP_ece_Type 4
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 */
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
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
1606 ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **pce)
1608 int i = 0, entries = 0;
1609 unsigned char *curdata = data;
1610 PTPCanon_changes_entry *ce;
1614 while (curdata - data < datasize) {
1615 uint32_t size = dtoh32a(&curdata[PTP_ece_Size]);
1616 uint32_t type = dtoh32a(&curdata[PTP_ece_Type]);
1618 if ((size == 8) && (type == 0))
1620 if (type == PTP_EC_CANON_EOS_OLCInfoChanged) {
1624 if (dtoh32a(curdata+12) & (1<<j))
1630 ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
1634 while (curdata - data < datasize) {
1635 uint32_t size = dtoh32a(&curdata[PTP_ece_Size]);
1636 uint32_t type = dtoh32a(&curdata[PTP_ece_Type]);
1638 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1639 ce[i].u.info = NULL;
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);
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]));
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);
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];
1668 PTPDevicePropDesc *dpd;
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)
1674 if (j==params->nrofcanon_props) {
1675 ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
1678 dpd = ¶ms->canon_props[j].dpd;
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]);
1691 if (propxcnt >= 2<<16) /* buggy or exploit */
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);
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);
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 */ \
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 );
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));
1738 case PTP_EC_CANON_EOS_PropValueChanged:
1739 if (size >= 0xc) { /* property info */
1741 uint32_t proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1742 unsigned char *xdata = &curdata[PTP_ece_Prop_Val_Data];
1743 PTPDevicePropDesc *dpd;
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)
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);
1757 params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
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 (¶ms->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;
1770 dpd = ¶ms->canon_props[j].dpd;
1772 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
1773 ce[i].u.propid = proptype;
1775 /* fix GetSet value */
1777 #define XX(x) case PTP_DPC_CANON_##x:
1779 XX(EOS_BatteryPower)
1780 XX(EOS_BatterySelect)
1782 XX(EOS_PTPExtensionVersion)
1784 XX(EOS_AvailableShots)
1785 XX(EOS_CurrentStorage)
1786 XX(EOS_CurrentFolder)
1789 XX(EOS_HDDirectoryStructure)
1793 XX(EOS_CardExtension)
1795 XX(EOS_ShutterCounter)
1796 XX(EOS_SerialNumber)
1797 XX(EOS_DepthOfFieldPreview)
1798 XX(EOS_EVFRecordStatus)
1801 XX(EOS_DepthOfField)
1807 dpd->GetSet = PTP_DPGS_Get;
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;
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;
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;
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;
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;
1864 case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
1865 case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
1866 dpd->DataType = PTP_DTC_INT16;
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]);
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 */
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]);
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:
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]);
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);
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);
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);
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);
1955 #if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
1957 dpd->FactoryDefaultValue.str = ptp_unpack_string(params, data, 0, &len);
1958 dpd->CurrentValue.str = ptp_unpack_string(params, data, 0, &len);
1960 if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
1961 dpd->FactoryDefaultValue.str = strdup( (char*)xdata );
1963 if (dpd->CurrentValue.str) free (dpd->CurrentValue.str);
1964 dpd->CurrentValue.str = strdup( (char*)xdata );
1966 ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
1970 /* debug is printed in switch above this one */
1974 /* ImageFormat and customFuncEx special handling (WARNING: dont move this in front of the dpd->DataType switch!) */
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);
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);
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;
2002 PTPDevicePropDesc *dpd;
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 */
2008 for (j=8;j<size;j++)
2009 ptp_debug (params, " %d: %02x", j-8, curdata[j]);
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);
2017 mask = dtoh16a(curdata+8+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));
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)
2034 if (j == params->nrofcanon_props)
2035 ptp_debug (params, "event %d: shutterspeed not found yet, handle this", i);
2037 dpd = ¶ms->canon_props[j].dpd;
2038 dpd->CurrentValue.u16 = curdata[curoff+5]; /* just use last byte */
2040 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
2041 ce[i].u.propid = proptype;
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)
2052 if (j == params->nrofcanon_props)
2053 ptp_debug (params, "event %d: shutterspeed not found yet, handle this", i);
2055 dpd = ¶ms->canon_props[j].dpd;
2056 dpd->CurrentValue.u16 = curdata[curoff+4]; /* just use last byte */
2058 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
2059 ce[i].u.propid = proptype;
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)
2070 if (j == params->nrofcanon_props)
2071 ptp_debug (params, "event %d: shutterspeed not found yet, handle this", i);
2073 dpd = ¶ms->canon_props[j].dpd;
2074 dpd->CurrentValue.u16 = curdata[curoff+3]; /* just use last byte */
2076 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
2077 ce[i].u.propid = proptype;
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",
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",
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",
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",
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",
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",
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",
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",
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",
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);
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);
2225 case 0: /* end marker */
2226 if (size == 8) /* no output */
2228 ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
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));
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); \
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)
2256 XX(BulbExposureTime)
2258 XX(RequestObjectTransferTS)
2262 ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
2265 if (size >= 0x8) { /* event info */
2267 for (j=8;j<size;j++)
2268 ptp_debug (params, " %d: %02x", j, curdata[j]);
2270 ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2274 if ((size == 8) && (type == 0))
2287 PTP USB Event container unpack for Nikon events.
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
2294 ptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, unsigned int *cnt)
2301 if (len < PTP_nikon_ec_Code)
2303 *cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
2304 if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
2309 *ec = malloc(sizeof(PTPContainer)*(*cnt));
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;
2320 static inline uint32_t
2321 ptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
2324 unsigned char *curdata;
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;
2337 htod16a(curdata,100);curdata+=2;
2338 htod16a(curdata,1);curdata+=2;
2339 htod16a(curdata,0);curdata+=2;
2340 htod16a(curdata,1000);curdata+=2;
2342 htod32a(curdata,0);curdata+=4;
2343 htod32a(curdata,0);curdata+=4;
2345 htod16a(curdata,6);curdata+=2;
2346 htod32a(curdata,0);curdata+=4;
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;
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;
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
2385 static inline uint16_t
2386 ptp_unpack_canon_directory (
2390 PTPObjectHandles *handles,
2391 PTPObjectInfo **oinfos, /* size(handles->n) */
2392 uint32_t **flags /* size(handles->n) */
2394 unsigned int i, j, nrofobs = 0, curob = 0;
2396 #define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
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;
2407 /* Migrate data into objects ids, handles into
2408 * the object handler array.
2411 for (i=0;i<cnt;i++) {
2412 unsigned char *cur = dir+i*0x4c;
2413 PTPObjectInfo *oi = (*oinfos)+curob;
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);
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);
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);
2443 /* Walk over all objects and distribute the storage ids */
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);
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");*/
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");*/
2468 if ((*oinfos)[j].StorageID == 0xffffffff) {
2469 (*oinfos)[j].StorageID = storageid;
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");*/
2479 if ((*oinfos)[j].StorageID == 0xffffffff) {
2480 (*oinfos)[j].StorageID = storageid;
2486 * - changed no entry (nothing more to do)
2487 * - changed all of them at once (usually happens)
2490 if (!changed || (changed==nrofobs-1))