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