1/* currently this file is included into ptp.c */
2
3#ifdef HAVE_ICONV
4#include <iconv.h>
5#endif
6
7extern void
8ptp_debug (PTPParams *params, const char *format, ...);
9
10static inline uint16_t
11htod16p (PTPParams *params, uint16_t var)
12{
13	return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
14}
15
16static inline uint32_t
17htod32p (PTPParams *params, uint32_t var)
18{
19	return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
20}
21
22static inline void
23htod16ap (PTPParams *params, unsigned char *a, uint16_t val)
24{
25	if (params->byteorder==PTP_DL_LE)
26		htole16a(a,val);
27	else
28		htobe16a(a,val);
29}
30
31static inline void
32htod32ap (PTPParams *params, unsigned char *a, uint32_t val)
33{
34	if (params->byteorder==PTP_DL_LE)
35		htole32a(a,val);
36	else
37		htobe32a(a,val);
38}
39
40static inline void
41htod64ap (PTPParams *params, unsigned char *a, uint64_t val)
42{
43	if (params->byteorder==PTP_DL_LE)
44		htole64a(a,val);
45	else
46		htobe64a(a,val);
47}
48
49static inline uint16_t
50dtoh16p (PTPParams *params, uint16_t var)
51{
52	return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
53}
54
55static inline uint32_t
56dtoh32p (PTPParams *params, uint32_t var)
57{
58	return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
59}
60
61static inline uint64_t
62dtoh64p (PTPParams *params, uint64_t var)
63{
64	return ((params->byteorder==PTP_DL_LE)?le64toh(var):be64toh(var));
65}
66
67static inline uint16_t
68dtoh16ap (PTPParams *params, const unsigned char *a)
69{
70	return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
71}
72
73static inline uint32_t
74dtoh32ap (PTPParams *params, const unsigned char *a)
75{
76	return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
77}
78
79static inline uint64_t
80dtoh64ap (PTPParams *params, const unsigned char *a)
81{
82	return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a));
83}
84
85#define htod8a(a,x)	*(uint8_t*)(a) = x
86#define htod16a(a,x)	htod16ap(params,a,x)
87#define htod32a(a,x)	htod32ap(params,a,x)
88#define htod64a(a,x)	htod64ap(params,a,x)
89#define htod16(x)	htod16p(params,x)
90#define htod32(x)	htod32p(params,x)
91#define htod64(x)	htod64p(params,x)
92
93#define dtoh8a(x)	(*(uint8_t*)(x))
94#define dtoh16a(a)	dtoh16ap(params,a)
95#define dtoh32a(a)	dtoh32ap(params,a)
96#define dtoh64a(a)	dtoh64ap(params,a)
97#define dtoh16(x)	dtoh16p(params,x)
98#define dtoh32(x)	dtoh32p(params,x)
99#define dtoh64(x)	dtoh64p(params,x)
100
101
102static inline char*
103ptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
104{
105	uint8_t length;
106	uint16_t string[PTP_MAXSTRLEN+1];
107	/* allow for UTF-8: max of 3 bytes per UCS-2 char, plus final null */
108	char loclstr[PTP_MAXSTRLEN*3+1];
109	size_t nconv, srclen, destlen;
110	char *src, *dest;
111
112	length = dtoh8a(&data[offset]);	/* PTP_MAXSTRLEN == 255, 8 bit len */
113	*len = length;
114	if (length == 0)		/* nothing to do? */
115		return(NULL);
116
117	/* copy to string[] to ensure correct alignment for iconv(3) */
118	memcpy(string, &data[offset+1], length * sizeof(string[0]));
119	string[length] = 0x0000U;   /* be paranoid!  add a terminator. */
120	loclstr[0] = '\0';
121
122	/* convert from camera UCS-2 to our locale */
123	src = (char *)string;
124	srclen = length * sizeof(string[0]);
125	dest = loclstr;
126	destlen = sizeof(loclstr)-1;
127	nconv = (size_t)-1;
128#ifdef HAVE_ICONV
129	nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen,
130			&dest, &destlen);
131#endif
132	if (nconv == (size_t) -1) { /* do it the hard way */
133		int i;
134		/* try the old way, in case iconv is broken */
135		for (i=0;i<length;i++) {
136			if (dtoh16a(&data[offset+1+2*i])>127)
137				loclstr[i] = '?';
138			else
139				loclstr[i] = dtoh16a(&data[offset+1+2*i]);
140		}
141		dest = loclstr+length;
142	}
143	*dest = '\0';
144	loclstr[sizeof(loclstr)-1] = '\0';   /* be safe? */
145	return(strdup(loclstr));
146}
147
148static inline int
149ucs2strlen(uint16_t const * const unicstr)
150{
151	int length;
152
153	/* Unicode strings are terminated with 2 * 0x00 */
154	for(length = 0; unicstr[length] != 0x0000U; length ++);
155	return length;
156}
157
158
159static inline void
160ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
161{
162	int packedlen;
163	uint16_t ucs2str[PTP_MAXSTRLEN+1];
164	char *ucs2strp = (char *) ucs2str;
165	size_t convlen = strlen(string);
166
167	/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
168	memset(ucs2strp, 0, sizeof(ucs2str));  /* XXX: necessary? */
169#ifdef HAVE_ICONV
170	{
171		size_t nconv;
172		size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
173		char *stringp = string;
174
175		nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
176			&ucs2strp, &convmax);
177		if (nconv == (size_t) -1)
178			ucs2str[0] = 0x0000U;
179	}
180#else
181	{
182		int i;
183		for (i=0;i<convlen;i++) {
184			ucs2str[i] = string[i];
185		}
186		ucs2str[convlen] = 0;
187	}
188#endif
189	/*
190	 * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
191	 *      why do we need ucs2strlen()?
192	 */
193	packedlen = ucs2strlen(ucs2str);
194	if (packedlen > PTP_MAXSTRLEN-1) {
195		*len=0;
196		return;
197	}
198
199	/* number of characters including terminating 0 (PTP standard confirmed) */
200	htod8a(&data[offset],packedlen+1);
201	memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
202	htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
203
204	/* The returned length is in number of characters */
205	*len = (uint8_t) packedlen+1;
206}
207
208static inline unsigned char *
209ptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
210{
211	uint8_t packed[PTP_MAXSTRLEN*2+3], len;
212	size_t plen;
213	unsigned char *retcopy = NULL;
214
215	if (string == NULL)
216	  ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
217	else
218	  ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
219
220	/* returned length is in characters, then one byte for string length */
221	plen = len*2 + 1;
222
223	retcopy = malloc(plen);
224	if (!retcopy) {
225		*packed_size = 0;
226		return NULL;
227	}
228	memcpy(retcopy, packed, plen);
229	*packed_size = plen;
230	return (retcopy);
231}
232
233static inline uint32_t
234ptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
235{
236	uint32_t n, i=0;
237
238	n=dtoh32a(&data[offset]);
239	*array = malloc (n*sizeof(uint32_t));
240	while (n>i) {
241		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
242		i++;
243	}
244	return n;
245}
246
247static inline uint32_t
248ptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
249{
250	uint32_t i=0;
251
252	*data = malloc ((arraylen+1)*sizeof(uint32_t));
253	htod32a(&(*data)[0],arraylen);
254	for (i=0;i<arraylen;i++)
255		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
256	return (arraylen+1)*sizeof(uint32_t);
257}
258
259static inline uint32_t
260ptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
261{
262	uint32_t n, i=0;
263
264	n=dtoh32a(&data[offset]);
265	*array = malloc (n*sizeof(uint16_t));
266	while (n>i) {
267		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
268		i++;
269	}
270	return n;
271}
272
273/* DeviceInfo pack/unpack */
274
275#define PTP_di_StandardVersion		 0
276#define PTP_di_VendorExtensionID	 2
277#define PTP_di_VendorExtensionVersion	 6
278#define PTP_di_VendorExtensionDesc	 8
279#define PTP_di_FunctionalMode		 8
280#define PTP_di_OperationsSupported	10
281
282static inline void
283ptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
284{
285	uint8_t len;
286	unsigned int totallen;
287
288	if (!data) return;
289	if (datalen < 12) return;
290	di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
291	di->VendorExtensionID =
292		dtoh32a(&data[PTP_di_VendorExtensionID]);
293	di->VendorExtensionVersion =
294		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
295	di->VendorExtensionDesc =
296		ptp_unpack_string(params, data,
297		PTP_di_VendorExtensionDesc, &len);
298	totallen=len*2+1;
299	di->FunctionalMode =
300		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
301	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
302		PTP_di_OperationsSupported+totallen,
303		&di->OperationsSupported);
304	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
305	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
306		PTP_di_OperationsSupported+totallen,
307		&di->EventsSupported);
308	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
309	di->DevicePropertiesSupported_len =
310		ptp_unpack_uint16_t_array(params, data,
311		PTP_di_OperationsSupported+totallen,
312		&di->DevicePropertiesSupported);
313	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
314	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
315		PTP_di_OperationsSupported+totallen,
316		&di->CaptureFormats);
317	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
318	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
319		PTP_di_OperationsSupported+totallen,
320		&di->ImageFormats);
321	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
322	di->Manufacturer = ptp_unpack_string(params, data,
323		PTP_di_OperationsSupported+totallen,
324		&len);
325	totallen+=len*2+1;
326	di->Model = ptp_unpack_string(params, data,
327		PTP_di_OperationsSupported+totallen,
328		&len);
329	totallen+=len*2+1;
330	di->DeviceVersion = ptp_unpack_string(params, data,
331		PTP_di_OperationsSupported+totallen,
332		&len);
333	totallen+=len*2+1;
334	di->SerialNumber = ptp_unpack_string(params, data,
335		PTP_di_OperationsSupported+totallen,
336		&len);
337}
338
339static void
340ptp_free_DI (PTPDeviceInfo *di) {
341	if (di->SerialNumber) free (di->SerialNumber);
342	if (di->DeviceVersion) free (di->DeviceVersion);
343	if (di->Model) free (di->Model);
344	if (di->Manufacturer) free (di->Manufacturer);
345	if (di->ImageFormats) free (di->ImageFormats);
346	if (di->CaptureFormats) free (di->CaptureFormats);
347	if (di->VendorExtensionDesc) free (di->VendorExtensionDesc);
348	if (di->OperationsSupported) free (di->OperationsSupported);
349	if (di->EventsSupported) free (di->EventsSupported);
350	if (di->DevicePropertiesSupported) free (di->DevicePropertiesSupported);
351}
352
353/* EOS Device Info unpack */
354static inline void
355ptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
356{
357	int totallen = 4;
358	if (datalen < 8) return;
359
360	/* uint32_t struct len - ignore */
361	di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
362		totallen, &di->EventsSupported);
363	if (!di->EventsSupported) return;
364	totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
365	if (totallen >= datalen) return;
366
367	di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
368		totallen, &di->DevicePropertiesSupported);
369	if (!di->DevicePropertiesSupported) return;
370	totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
371	if (totallen >= datalen) return;
372
373	di->unk_len = ptp_unpack_uint32_t_array(params, data,
374		totallen, &di->unk);
375	if (!di->unk) return;
376	totallen += di->unk_len*sizeof(uint32_t)+4;
377	return;
378}
379
380/* ObjectHandles array pack/unpack */
381
382#define PTP_oh				 0
383
384static inline void
385ptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
386{
387	if (len) {
388		oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
389	} else {
390		oh->n = 0;
391		oh->Handler = NULL;
392	}
393}
394
395/* StoreIDs array pack/unpack */
396
397#define PTP_sids			 0
398
399static inline void
400ptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
401{
402	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
403	&sids->Storage);
404}
405
406/* StorageInfo pack/unpack */
407
408#define PTP_si_StorageType		 0
409#define PTP_si_FilesystemType		 2
410#define PTP_si_AccessCapability		 4
411#define PTP_si_MaxCapability		 6
412#define PTP_si_FreeSpaceInBytes		14
413#define PTP_si_FreeSpaceInImages	22
414#define PTP_si_StorageDescription	26
415
416static inline void
417ptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
418{
419	uint8_t storagedescriptionlen;
420
421	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
422	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
423	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
424	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
425	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
426	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
427	si->StorageDescription=ptp_unpack_string(params, data,
428		PTP_si_StorageDescription, &storagedescriptionlen);
429	si->VolumeLabel=ptp_unpack_string(params, data,
430		PTP_si_StorageDescription+storagedescriptionlen*2+1,
431		&storagedescriptionlen);
432}
433
434/* ObjectInfo pack/unpack */
435
436#define PTP_oi_StorageID		 0
437#define PTP_oi_ObjectFormat		 4
438#define PTP_oi_ProtectionStatus		 6
439#define PTP_oi_ObjectCompressedSize	 8
440#define PTP_oi_ThumbFormat		12
441#define PTP_oi_ThumbCompressedSize	14
442#define PTP_oi_ThumbPixWidth		18
443#define PTP_oi_ThumbPixHeight		22
444#define PTP_oi_ImagePixWidth		26
445#define PTP_oi_ImagePixHeight		30
446#define PTP_oi_ImageBitDepth		34
447#define PTP_oi_ParentObject		38
448#define PTP_oi_AssociationType		42
449#define PTP_oi_AssociationDesc		44
450#define PTP_oi_SequenceNumber		48
451#define PTP_oi_filenamelen		52
452#define PTP_oi_Filename			53
453
454/* the max length assuming zero length dates. We have need 3 */
455/* bytes for these. */
456#define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
457
458static inline uint32_t
459ptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
460{
461	unsigned char* oidata;
462	uint8_t filenamelen;
463	uint8_t capturedatelen=0;
464	/* let's allocate some memory first; correct assuming zero length dates */
465	oidata=malloc(PTP_oi_MaxLen);
466	/* the caller should free it after use! */
467#if 0
468	char *capture_date="20020101T010101"; /* XXX Fake date */
469#endif
470	memset (oidata, 0, PTP_oi_MaxLen);
471	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
472	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
473	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
474	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
475	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
476	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
477	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
478	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
479	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
480	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
481	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
482	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
483	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
484	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
485	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
486
487	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
488/*
489	filenamelen=(uint8_t)strlen(oi->Filename);
490	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
491	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
492		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
493	}
494*/
495	/*
496	 *XXX Fake date.
497	 * for example Kodak sets Capture date on the basis of EXIF data.
498	 * Spec says that this field is from perspective of Initiator.
499	 */
500#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
501	capturedatelen=strlen(capture_date);
502	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
503		capturedatelen+1);
504	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
505		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
506	}
507	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
508		capturedatelen+1);
509	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
510		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
511		  capture_date[i];
512	}
513#endif
514	/* XXX this function should return dataset length */
515
516	*oidataptr=oidata;
517	return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3);
518}
519
520static time_t
521ptp_unpack_PTPTIME (const char *str) {
522	char ptpdate[40];
523	char tmp[5];
524	int  ptpdatelen;
525	struct tm tm;
526
527	if (!str)
528		return 0;
529	ptpdatelen = strlen(str);
530	if (ptpdatelen >= sizeof (ptpdate)) {
531		/*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
532		return 0;
533	}
534	strcpy (ptpdate, str);
535	if (ptpdatelen<15) {
536		/*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
537		return 0;
538	}
539
540	memset(&tm,0,sizeof(tm));
541	strncpy (tmp, ptpdate, 4);
542	tmp[4] = 0;
543	tm.tm_year=atoi (tmp) - 1900;
544	strncpy (tmp, ptpdate + 4, 2);
545	tmp[2] = 0;
546	tm.tm_mon = atoi (tmp) - 1;
547	strncpy (tmp, ptpdate + 6, 2);
548	tmp[2] = 0;
549	tm.tm_mday = atoi (tmp);
550	strncpy (tmp, ptpdate + 9, 2);
551	tmp[2] = 0;
552	tm.tm_hour = atoi (tmp);
553	strncpy (tmp, ptpdate + 11, 2);
554	tmp[2] = 0;
555	tm.tm_min = atoi (tmp);
556	strncpy (tmp, ptpdate + 13, 2);
557	tmp[2] = 0;
558	tm.tm_sec = atoi (tmp);
559
560	tm.tm_isdst = -1;
561
562	return mktime (&tm);
563}
564
565static inline void
566ptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
567{
568	uint8_t filenamelen;
569	uint8_t capturedatelen;
570	char *capture_date;
571
572	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
573	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
574	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
575	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
576	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
577	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
578	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
579	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
580	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
581	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
582	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
583	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
584	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
585	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
586	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
587	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
588
589	capture_date = ptp_unpack_string(params, data,
590		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
591	/* subset of ISO 8601, without '.s' tenths of second and
592	 * time zone
593	 */
594	oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
595	free(capture_date);
596
597	/* now the modification date ... */
598	capture_date = ptp_unpack_string(params, data,
599		PTP_oi_filenamelen+filenamelen*2
600		+capturedatelen*2+2,&capturedatelen);
601	oi->ModificationDate = ptp_unpack_PTPTIME(capture_date);
602	free(capture_date);
603}
604
605/* Custom Type Value Assignement (without Length) macro frequently used below */
606#define CTVAL(target,func) {			\
607	if (total - *offset < sizeof(target))	\
608		return 0;			\
609	target = func(&data[*offset]);		\
610	*offset += sizeof(target);		\
611}
612
613#define RARR(val,member,func)	{			\
614	int n,j;					\
615	if (total - *offset < sizeof(uint32_t))		\
616		return 0;				\
617	n = dtoh32a (&data[*offset]);			\
618	*offset += sizeof(uint32_t);			\
619							\
620	val->a.count = n;				\
621	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
622	if (!val->a.v) return 0;			\
623	for (j=0;j<n;j++)				\
624		CTVAL(val->a.v[j].member, func);	\
625}
626
627static inline int
628ptp_unpack_DPV (
629	PTPParams *params, unsigned char* data, int *offset, int total,
630	PTPPropertyValue* value, uint16_t datatype
631) {
632	switch (datatype) {
633	case PTP_DTC_INT8:
634		CTVAL(value->i8,dtoh8a);
635		break;
636	case PTP_DTC_UINT8:
637		CTVAL(value->u8,dtoh8a);
638		break;
639	case PTP_DTC_INT16:
640		CTVAL(value->i16,dtoh16a);
641		break;
642	case PTP_DTC_UINT16:
643		CTVAL(value->u16,dtoh16a);
644		break;
645	case PTP_DTC_INT32:
646		CTVAL(value->i32,dtoh32a);
647		break;
648	case PTP_DTC_UINT32:
649		CTVAL(value->u32,dtoh32a);
650		break;
651	case PTP_DTC_INT64:
652		CTVAL(value->i64,dtoh64a);
653		break;
654	case PTP_DTC_UINT64:
655		CTVAL(value->u64,dtoh64a);
656		break;
657
658	case PTP_DTC_UINT128:
659		*offset += 16;
660		/*fprintf(stderr,"unhandled unpack of uint128n");*/
661		break;
662	case PTP_DTC_INT128:
663		*offset += 16;
664		/*fprintf(stderr,"unhandled unpack of int128n");*/
665		break;
666
667
668
669	case PTP_DTC_AINT8:
670		RARR(value,i8,dtoh8a);
671		break;
672	case PTP_DTC_AUINT8:
673		RARR(value,u8,dtoh8a);
674		break;
675	case PTP_DTC_AUINT16:
676		RARR(value,u16,dtoh16a);
677		break;
678	case PTP_DTC_AINT16:
679		RARR(value,i16,dtoh16a);
680		break;
681	case PTP_DTC_AUINT32:
682		RARR(value,u32,dtoh32a);
683		break;
684	case PTP_DTC_AINT32:
685		RARR(value,i32,dtoh32a);
686		break;
687	case PTP_DTC_AUINT64:
688		RARR(value,u64,dtoh64a);
689		break;
690	case PTP_DTC_AINT64:
691		RARR(value,i64,dtoh64a);
692		break;
693	/* XXX: other int types are unimplemented */
694	/* XXX: other int arrays are unimplemented also */
695	case PTP_DTC_STR: {
696		uint8_t len;
697		/* XXX: max size */
698		value->str = ptp_unpack_string(params,data,*offset,&len);
699		*offset += len*2+1;
700		if (!value->str)
701			return 1;
702		break;
703	}
704	default:
705		return 0;
706	}
707	return 1;
708}
709
710/* Device Property pack/unpack */
711
712#define PTP_dpd_DevicePropertyCode	0
713#define PTP_dpd_DataType		2
714#define PTP_dpd_GetSet			4
715#define PTP_dpd_FactoryDefaultValue	5
716
717static inline int
718ptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
719{
720	int offset=0, ret;
721
722	memset (dpd, 0, sizeof(*dpd));
723	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
724	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
725	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
726	dpd->FormFlag=PTP_DPFF_None;
727
728	offset = PTP_dpd_FactoryDefaultValue;
729	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
730	if (!ret) goto outofmemory;
731	if ((dpd->DataType == PTP_DTC_STR) && (offset == dpdlen))
732		return 1;
733	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
734	if (!ret) goto outofmemory;
735
736	/* if offset==0 then Data Type format is not supported by this
737	   code or the Data Type is a string (with two empty strings as
738	   values). In both cases Form Flag should be set to 0x00 and FORM is
739	   not present. */
740
741	if (offset==PTP_dpd_FactoryDefaultValue)
742		return 1;
743
744	dpd->FormFlag=dtoh8a(&data[offset]);
745	offset+=sizeof(uint8_t);
746
747	switch (dpd->FormFlag) {
748	case PTP_DPFF_Range:
749		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
750		if (!ret) goto outofmemory;
751		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
752		if (!ret) goto outofmemory;
753		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
754		if (!ret) goto outofmemory;
755		break;
756	case PTP_DPFF_Enumeration: {
757		int i;
758#define N	dpd->FORM.Enum.NumberOfValues
759		N = dtoh16a(&data[offset]);
760		offset+=sizeof(uint16_t);
761		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
762		if (!dpd->FORM.Enum.SupportedValue)
763			goto outofmemory;
764
765		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
766		for (i=0;i<N;i++) {
767			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
768
769			/* Slightly different handling here. The HP PhotoSmart 120
770			 * specifies an enumeration with N in wrong endian
771			 * 00 01 instead of 01 00, so we count the enum just until the
772			 * the end of the packet.
773			 */
774			if (!ret) {
775				if (!i)
776					goto outofmemory;
777				dpd->FORM.Enum.NumberOfValues = i;
778				break;
779			}
780		}
781		}
782	}
783#undef N
784	return 1;
785outofmemory:
786	ptp_free_devicepropdesc(dpd);
787	return 0;
788}
789
790/* (MTP) Object Property pack/unpack */
791#define PTP_opd_ObjectPropertyCode	0
792#define PTP_opd_DataType		2
793#define PTP_opd_GetSet			4
794#define PTP_opd_FactoryDefaultValue	5
795
796static inline int
797ptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
798{
799	int offset=0, ret;
800
801	memset (opd, 0, sizeof(*opd));
802	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
803	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
804	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
805
806	offset = PTP_opd_FactoryDefaultValue;
807	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
808	if (!ret) goto outofmemory;
809
810	opd->GroupCode=dtoh32a(&data[offset]);
811	offset+=sizeof(uint32_t);
812
813	opd->FormFlag=dtoh8a(&data[offset]);
814	offset+=sizeof(uint8_t);
815
816	switch (opd->FormFlag) {
817	case PTP_OPFF_Range:
818		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
819		if (!ret) goto outofmemory;
820		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
821		if (!ret) goto outofmemory;
822		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
823		if (!ret) goto outofmemory;
824		break;
825	case PTP_OPFF_Enumeration: {
826		int i;
827#define N	opd->FORM.Enum.NumberOfValues
828		N = dtoh16a(&data[offset]);
829		offset+=sizeof(uint16_t);
830		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
831		if (!opd->FORM.Enum.SupportedValue)
832			goto outofmemory;
833
834		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
835		for (i=0;i<N;i++) {
836			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
837
838			/* Slightly different handling here. The HP PhotoSmart 120
839			 * specifies an enumeration with N in wrong endian
840			 * 00 01 instead of 01 00, so we count the enum just until the
841			 * the end of the packet.
842			 */
843			if (!ret) {
844				if (!i)
845					goto outofmemory;
846				opd->FORM.Enum.NumberOfValues = i;
847				break;
848			}
849		}
850#undef N
851		}
852	}
853	return 1;
854outofmemory:
855	ptp_free_objectpropdesc(opd);
856	return 0;
857}
858
859
860static inline uint32_t
861ptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
862{
863	unsigned char* dpv=NULL;
864	uint32_t size=0;
865	int	i;
866
867	switch (datatype) {
868	case PTP_DTC_INT8:
869		size=sizeof(int8_t);
870		dpv=malloc(size);
871		htod8a(dpv,value->i8);
872		break;
873	case PTP_DTC_UINT8:
874		size=sizeof(uint8_t);
875		dpv=malloc(size);
876		htod8a(dpv,value->u8);
877		break;
878	case PTP_DTC_INT16:
879		size=sizeof(int16_t);
880		dpv=malloc(size);
881		htod16a(dpv,value->i16);
882		break;
883	case PTP_DTC_UINT16:
884		size=sizeof(uint16_t);
885		dpv=malloc(size);
886		htod16a(dpv,value->u16);
887		break;
888	case PTP_DTC_INT32:
889		size=sizeof(int32_t);
890		dpv=malloc(size);
891		htod32a(dpv,value->i32);
892		break;
893	case PTP_DTC_UINT32:
894		size=sizeof(uint32_t);
895		dpv=malloc(size);
896		htod32a(dpv,value->u32);
897		break;
898	case PTP_DTC_INT64:
899		size=sizeof(int64_t);
900		dpv=malloc(size);
901		htod64a(dpv,value->i64);
902		break;
903	case PTP_DTC_UINT64:
904		size=sizeof(uint64_t);
905		dpv=malloc(size);
906		htod64a(dpv,value->u64);
907		break;
908	case PTP_DTC_AUINT8:
909		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
910		dpv=malloc(size);
911		htod32a(dpv,value->a.count);
912		for (i=0;i<value->a.count;i++)
913			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
914		break;
915	case PTP_DTC_AINT8:
916		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
917		dpv=malloc(size);
918		htod32a(dpv,value->a.count);
919		for (i=0;i<value->a.count;i++)
920			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
921		break;
922	case PTP_DTC_AUINT16:
923		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
924		dpv=malloc(size);
925		htod32a(dpv,value->a.count);
926		for (i=0;i<value->a.count;i++)
927			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
928		break;
929	case PTP_DTC_AINT16:
930		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
931		dpv=malloc(size);
932		htod32a(dpv,value->a.count);
933		for (i=0;i<value->a.count;i++)
934			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
935		break;
936	case PTP_DTC_AUINT32:
937		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
938		dpv=malloc(size);
939		htod32a(dpv,value->a.count);
940		for (i=0;i<value->a.count;i++)
941			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
942		break;
943	case PTP_DTC_AINT32:
944		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
945		dpv=malloc(size);
946		htod32a(dpv,value->a.count);
947		for (i=0;i<value->a.count;i++)
948			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
949		break;
950	case PTP_DTC_AUINT64:
951		size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
952		dpv=malloc(size);
953		htod32a(dpv,value->a.count);
954		for (i=0;i<value->a.count;i++)
955			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
956		break;
957	case PTP_DTC_AINT64:
958		size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
959		dpv=malloc(size);
960		htod32a(dpv,value->a.count);
961		for (i=0;i<value->a.count;i++)
962			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
963		break;
964	/* XXX: other int types are unimplemented */
965	case PTP_DTC_STR: {
966		dpv=ptp_get_packed_stringcopy(params, value->str, &size);
967		break;
968	}
969	}
970	*dpvptr=dpv;
971	return size;
972}
973
974#define MAX_MTP_PROPS 127
975static inline uint32_t
976ptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
977{
978	unsigned char* opldata;
979	MTPProperties *propitr;
980	unsigned char *packedprops[MAX_MTP_PROPS];
981	uint32_t packedpropslens[MAX_MTP_PROPS];
982	uint32_t packedobjecthandles[MAX_MTP_PROPS];
983	uint16_t packedpropsids[MAX_MTP_PROPS];
984	uint16_t packedpropstypes[MAX_MTP_PROPS];
985	uint32_t totalsize = 0;
986	uint32_t bufp = 0;
987	uint32_t noitems = 0;
988	uint32_t i;
989
990	totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
991	propitr = props;
992	while (nrofprops-- && noitems < MAX_MTP_PROPS) {
993		/* Object Handle */
994		packedobjecthandles[noitems]=propitr->ObjectHandle;
995		totalsize += sizeof(uint32_t); /* Object ID */
996		/* Metadata type */
997		packedpropsids[noitems]=propitr->property;
998		totalsize += sizeof(uint16_t);
999		/* Data type */
1000		packedpropstypes[noitems]= propitr->datatype;
1001		totalsize += sizeof(uint16_t);
1002		/* Add each property to be sent. */
1003	        packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
1004		totalsize += packedpropslens[noitems];
1005		noitems ++;
1006		propitr ++;
1007	}
1008
1009	/* Allocate memory for the packed property list */
1010	opldata = malloc(totalsize);
1011
1012	htod32a(&opldata[bufp],noitems);
1013	bufp += 4;
1014
1015	/* Copy into a nice packed list */
1016	for (i = 0; i < noitems; i++) {
1017		/* Object ID */
1018		htod32a(&opldata[bufp],packedobjecthandles[i]);
1019		bufp += sizeof(uint32_t);
1020		htod16a(&opldata[bufp],packedpropsids[i]);
1021		bufp += sizeof(uint16_t);
1022		htod16a(&opldata[bufp],packedpropstypes[i]);
1023		bufp += sizeof(uint16_t);
1024		/* The copy the actual property */
1025		memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
1026		bufp += packedpropslens[i];
1027		free(packedprops[i]);
1028	}
1029	*opldataptr = opldata;
1030	return totalsize;
1031}
1032
1033static int
1034_compare_func(const void* x, const void *y) {
1035	const MTPProperties *px = x;
1036	const MTPProperties *py = y;
1037
1038	return px->ObjectHandle - py->ObjectHandle;
1039}
1040
1041static inline int
1042ptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
1043{
1044	uint32_t prop_count = dtoh32a(data);
1045	MTPProperties *props = NULL;
1046	int offset = 0, i;
1047
1048	if (prop_count == 0) {
1049		*pprops = NULL;
1050		return 0;
1051	}
1052	ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
1053	data += sizeof(uint32_t);
1054	len -= sizeof(uint32_t);
1055	props = malloc(prop_count * sizeof(MTPProperties));
1056	if (!props) return 0;
1057	for (i = 0; i < prop_count; i++) {
1058		if (len <= 0) {
1059			ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
1060			ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL", i);
1061			ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i);
1062			qsort (props, i, sizeof(MTPProperties),_compare_func);
1063			*pprops = props;
1064			return i;
1065		}
1066		props[i].ObjectHandle = dtoh32a(data);
1067		data += sizeof(uint32_t);
1068		len -= sizeof(uint32_t);
1069
1070		props[i].property = dtoh16a(data);
1071		data += sizeof(uint16_t);
1072		len -= sizeof(uint16_t);
1073
1074		props[i].datatype = dtoh16a(data);
1075		data += sizeof(uint16_t);
1076		len -= sizeof(uint16_t);
1077
1078		offset = 0;
1079		ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype);
1080		data += offset;
1081		len -= offset;
1082	}
1083	qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
1084	*pprops = props;
1085	return prop_count;
1086}
1087
1088/*
1089    PTP USB Event container unpack
1090    Copyright (c) 2003 Nikolai Kopanygin
1091*/
1092
1093#define PTP_ec_Length		0
1094#define PTP_ec_Type		4
1095#define PTP_ec_Code		6
1096#define PTP_ec_TransId		8
1097#define PTP_ec_Param1		12
1098#define PTP_ec_Param2		16
1099#define PTP_ec_Param3		20
1100
1101static inline void
1102ptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
1103{
1104	int	length;
1105	int	type;
1106
1107	if (data==NULL)
1108		return;
1109	memset(ec,0,sizeof(*ec));
1110	length=dtoh32a(&data[PTP_ec_Length]);
1111	type = dtoh16a(&data[PTP_ec_Type]);
1112
1113	ec->Code=dtoh16a(&data[PTP_ec_Code]);
1114	ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
1115
1116	if (type!=PTP_USB_CONTAINER_EVENT) {
1117		ptp_debug (params, "Unknown canon event type %d (code=%x,tid=%x), please report!",type,ec->Code,ec->Transaction_ID);
1118		return;
1119	}
1120	if (length>=(PTP_ec_Param1+4)) {
1121		ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
1122		ec->Nparam=1;
1123	}
1124	if (length>=(PTP_ec_Param2+4)) {
1125		ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
1126		ec->Nparam=2;
1127	}
1128	if (length>=(PTP_ec_Param3+4)) {
1129		ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
1130		ec->Nparam=3;
1131	}
1132}
1133
1134/*
1135    PTP Canon Folder Entry unpack
1136    Copyright (c) 2003 Nikolai Kopanygin
1137*/
1138#define PTP_cfe_ObjectHandle		0
1139#define PTP_cfe_ObjectFormatCode	4
1140#define PTP_cfe_Flags			6
1141#define PTP_cfe_ObjectSize		7
1142#define PTP_cfe_Time			11
1143#define PTP_cfe_Filename		15
1144
1145static inline void
1146ptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1147{
1148	int i;
1149	if (data==NULL)
1150		return;
1151	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
1152	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
1153	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
1154	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
1155	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
1156	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1157		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
1158}
1159
1160static inline uint16_t
1161ptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
1162{
1163	/*
1164	  EOS ImageFormat entries (of at least the 5DMII and the 400D ) look like this:
1165		uint32: number of entries / generated files (1 or 2)
1166		uint32: size of this entry in bytes (most likely allways 0x10)
1167		uint32: image type (1 == JPG, 6 == RAW)
1168		uint32: image size (0 == Large, 1 == Medium, 2 == Small)
1169		uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW)
1170	  If number of entries is 2 the last uint32 repeat.
1171
1172	  example:
1173		0: 0x       1
1174		1: 0x      10
1175		2: 0x       6
1176		3: 0x       1
1177		4: 0x       4
1178
1179	  The idea is to simply 'condense' these values to just one uint16 to be able to conveniontly
1180	  use the available enumeration facilities (look-up table). The image size and compression
1181	  values fully describe the image format. Hence we generate a uint16 with the four nibles set
1182	  as follows: entry 1 size | entry 1 compression | entry 2 size | entry 2 compression.
1183	  The above example would result in the value 0x1400.
1184	  */
1185
1186	const unsigned char* d = *data;
1187	uint32_t n = dtoh32a( d );
1188	uint32_t l, s1, c1, s2 = 0, c2 = 0;
1189
1190	if (n != 1 && n !=2) {
1191		ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
1192		return 0;
1193	}
1194
1195	l = dtoh32a( d+=4 );
1196	if (l != 0x10) {
1197		ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
1198		return 0;
1199	}
1200
1201	d+=4; /* skip type */
1202	s1 = dtoh32a( d+=4 );
1203	c1 = dtoh32a( d+=4 );
1204
1205	if (n == 2) {
1206		l = dtoh32a( d+=4 );
1207		if (l != 0x10) {
1208			ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
1209			return 0;
1210		}
1211		d+=4; /* skip type */
1212		s2 = dtoh32a( d+=4 );
1213		c2 = dtoh32a( d+=4 );
1214	}
1215
1216	*data = (unsigned char*) d+4;
1217
1218	return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
1219}
1220
1221static inline uint32_t
1222ptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
1223{
1224	uint32_t n = (value & 0xFF) ? 2 : 1;
1225	uint32_t s = 4 + 0x10 * n;
1226
1227	if( !data )
1228		return s;
1229
1230	htod32a(data+=0, n);
1231	htod32a(data+=4, 0x10);
1232	htod32a(data+=4, ((value >> 8) & 0xF) == 4 ? 6 : 1);
1233	htod32a(data+=4, (value >> 12) & 0xF);
1234	htod32a(data+=4, (value >> 8) & 0xF);
1235
1236	if (n==2) {
1237		htod32a(data+=4, 0x10);
1238		htod32a(data+=4, ((value >> 0) & 0xF) == 4 ? 6 : 1);
1239		htod32a(data+=4, (value >> 4) & 0xF);
1240		htod32a(data+=4, (value >> 0) & 0xF);
1241	}
1242
1243	return s;
1244}
1245
1246/*
1247    PTP EOS Changes Entry unpack
1248*/
1249#define PTP_ece_Size		0
1250#define PTP_ece_Type		4
1251
1252#define PTP_ece_Prop_Subtype	8	/* only for properties */
1253#define PTP_ece_Prop_Val_Data	0xc	/* only for properties */
1254#define PTP_ece_Prop_Desc_Type	0xc	/* only for property descs */
1255#define PTP_ece_Prop_Desc_Count	0x10	/* only for property descs */
1256#define PTP_ece_Prop_Desc_Data	0x14	/* only for property descs */
1257
1258/* for PTP_EC_CANON_EOS_RequestObjectTransfer */
1259#define PTP_ece_OI_ObjectID	8
1260#define PTP_ece_OI_OFC		0x0c
1261#define PTP_ece_OI_Size		0x14
1262#define PTP_ece_OI_Name		0x1c
1263
1264/* for PTP_EC_CANON_EOS_ObjectAddedEx */
1265#define PTP_ece_OA_ObjectID	8
1266#define PTP_ece_OA_StorageID	0x0c
1267#define PTP_ece_OA_OFC		0x10
1268#define PTP_ece_OA_Size		0x1c
1269#define PTP_ece_OA_Parent	0x20
1270#define PTP_ece_OA_Name		0x28
1271
1272static inline int
1273ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **ce)
1274{
1275	int	i = 0, entries = 0;
1276	unsigned char	*curdata = data;
1277
1278	if (data==NULL)
1279		return 0;
1280	while (curdata - data < datasize) {
1281		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1282		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1283
1284		curdata += size;
1285		if ((size == 8) && (type == 0))
1286			break;
1287		entries++;
1288	}
1289	*ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
1290	if (!*ce) return 0;
1291
1292	curdata = data;
1293	while (curdata - data < datasize) {
1294		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1295		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1296
1297		(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1298		switch (type) {
1299		case  PTP_EC_CANON_EOS_ObjectAddedEx:
1300			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
1301			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
1302			(*ce)[i].u.object.oi.StorageID 		= dtoh32a(&curdata[PTP_ece_OA_StorageID]);
1303			(*ce)[i].u.object.oi.ParentObject	= dtoh32a(&curdata[PTP_ece_OA_Parent]);
1304			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OA_OFC]);
1305			(*ce)[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
1306			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OA_Name]));
1307			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);
1308			break;
1309		case  PTP_EC_CANON_EOS_RequestObjectTransfer:
1310			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
1311			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
1312			(*ce)[i].u.object.oi.StorageID 		= 0; /* use as marker */
1313			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OI_OFC]);
1314			(*ce)[i].u.object.oi.ParentObject	= 0; /* check, but use as marker */
1315			(*ce)[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
1316			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OI_Name]));
1317
1318			ptp_debug (params, "event %d: request object transfer oid %08lx, ofc %04x, size %d, filename %s", i, (*ce)[i].u.object.oid, (*ce)[i].u.object.oi.ObjectFormat, (*ce)[i].u.object.oi.ObjectCompressedSize, (*ce)[i].u.object.oi.Filename);
1319			break;
1320		case  PTP_EC_CANON_EOS_AvailListChanged: {	/* property desc */
1321			uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1322			uint32_t	propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
1323			uint32_t	propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
1324			unsigned char	*data = &curdata[PTP_ece_Prop_Desc_Data];
1325			int		j;
1326			PTPDevicePropDesc	*dpd;
1327
1328			ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype);
1329			for (j=0;j<params->nrofcanon_props;j++)
1330				if (params->canon_props[j].proptype == proptype)
1331					break;
1332			if (j==params->nrofcanon_props) {
1333				ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
1334				break;
1335			}
1336			dpd = &params->canon_props[j].dpd;
1337			/* 1 - uint16 ?
1338			 * 3 - uint16
1339			 * 7 - string?
1340			 */
1341			if (propxtype != 3) {
1342				ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled.", i, propxtype, proptype);
1343				for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++)
1344					ptp_debug (params, "    %d: %02x", j, data[j]);
1345				break;
1346			}
1347			if (! propxcnt)
1348				break;
1349
1350			ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
1351				   i, propxtype, proptype, dpd->DataType, propxcnt);
1352			dpd->FormFlag = PTP_DPFF_Enumeration;
1353			dpd->FORM.Enum.NumberOfValues = propxcnt;
1354			dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
1355
1356			switch (proptype) {
1357			case PTP_DPC_CANON_EOS_ImageFormat:
1358			case PTP_DPC_CANON_EOS_ImageFormatCF:
1359			case PTP_DPC_CANON_EOS_ImageFormatSD:
1360			case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1361				/* special handling of ImageFormat properties */
1362				for (j=0;j<propxcnt;j++) {
1363					dpd->FORM.Enum.SupportedValue[j].u16 =
1364							dtoh16( ptp_unpack_EOS_ImageFormat( params, &data ) );
1365					ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
1366				}
1367				break;
1368			default:
1369				/* 'normal' enumerated types */
1370				switch (dpd->DataType) {
1371#define XX( TYPE, CONV )\
1372					for (j=0;j<propxcnt;j++) { \
1373						dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(data); \
1374						ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(data)); \
1375						data += 4; /* might only be for propxtype 3 */ \
1376					} \
1377					break;
1378
1379				case PTP_DTC_INT16:	XX( i16, dtoh16a );
1380				case PTP_DTC_UINT32:	XX( u32, dtoh32a );
1381				case PTP_DTC_UINT16:	XX( u16, dtoh16a );
1382				case PTP_DTC_UINT8:	XX( u8,  dtoh8a );
1383#undef XX
1384				default:
1385					ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, raw values:", i, dpd->DataType, proptype, dtoh32a(data));
1386					for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, data+=4) /* 4 is good for propxtype 3 */
1387						ptp_debug (params, "    %3d: 0x%8x", j, dtoh32a(data));
1388					break;
1389				}
1390			}
1391			break;
1392		}
1393		case PTP_EC_CANON_EOS_PropValueChanged:
1394			if (size >= 0xc) {	/* property info */
1395				int j;
1396				uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1397				unsigned char	*data = &curdata[PTP_ece_Prop_Val_Data];
1398				PTPDevicePropDesc	*dpd;
1399
1400				ptp_debug (params, "event %d: EOS prop %04x info record, datasize is %d", i, proptype, size-PTP_ece_Prop_Val_Data);
1401				for (j=0;j<params->nrofcanon_props;j++)
1402					if (params->canon_props[j].proptype == proptype)
1403						break;
1404				if (j<params->nrofcanon_props) {
1405					if (	(params->canon_props[j].size != size) ||
1406						(memcmp(params->canon_props[j].data,data,size-PTP_ece_Prop_Val_Data))) {
1407						params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
1408						memcpy (params->canon_props[j].data,data,size-PTP_ece_Prop_Val_Data);
1409					}
1410				} else {
1411					if (j)
1412						params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
1413					else
1414						params->canon_props = malloc(sizeof(params->canon_props[0]));
1415					params->canon_props[j].type = type;
1416					params->canon_props[j].proptype = proptype;
1417					params->canon_props[j].size = size;
1418					params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
1419					memcpy(params->canon_props[j].data, data, size-PTP_ece_Prop_Val_Data);
1420					memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
1421					params->canon_props[j].dpd.GetSet = 1;
1422					params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
1423					params->nrofcanon_props = j+1;
1424				}
1425				dpd = &params->canon_props[j].dpd;
1426
1427				/* fix GetSet value */
1428				switch (proptype) {
1429#define XX(x) case PTP_DPC_CANON_##x:
1430					XX(EOS_FocusMode)
1431					XX(EOS_BatteryPower)
1432					XX(EOS_BatterySelect)
1433					XX(EOS_ModelID)
1434					XX(EOS_PTPExtensionVersion)
1435					XX(EOS_DPOFVersion)
1436					XX(EOS_AvailableShots)
1437					XX(EOS_CurrentStorage)
1438					XX(EOS_CurrentFolder)
1439					XX(EOS_MyMenu)
1440					XX(EOS_MyMenuList)
1441					XX(EOS_HDDirectoryStructure)
1442					XX(EOS_BatteryInfo)
1443					XX(EOS_AdapterInfo)
1444					XX(EOS_LensStatus)
1445					XX(EOS_CardExtension)
1446					XX(EOS_TempStatus)
1447					XX(EOS_ShutterCounter)
1448					XX(EOS_SerialNumber)
1449					XX(EOS_DepthOfFieldPreview)
1450					XX(EOS_EVFRecordStatus)
1451					XX(EOS_LvAfSystem)
1452					XX(EOS_FocusInfoEx)
1453					XX(EOS_DepthOfField)
1454					XX(EOS_Brightness)
1455					XX(EOS_EFComp)
1456					XX(EOS_LensName)
1457					XX(EOS_LensID)
1458#undef XX
1459						dpd->GetSet = PTP_DPGS_Get;
1460						break;
1461				}
1462
1463				/* set DataType */
1464				switch (proptype) {
1465				case PTP_DPC_CANON_EOS_CameraTime:
1466				case PTP_DPC_CANON_EOS_EVFOutputDevice:
1467				case PTP_DPC_CANON_EOS_AvailableShots:
1468				case PTP_DPC_CANON_EOS_CaptureDestination:
1469				case PTP_DPC_CANON_EOS_WhiteBalanceXA:
1470				case PTP_DPC_CANON_EOS_WhiteBalanceXB:
1471				case PTP_DPC_CANON_EOS_QuickReviewTime:
1472				case PTP_DPC_CANON_EOS_CurrentStorage:
1473				case PTP_DPC_CANON_EOS_CurrentFolder:
1474				case PTP_DPC_CANON_EOS_ShutterCounter:
1475				case PTP_DPC_CANON_EOS_ModelID:
1476				case PTP_DPC_CANON_EOS_LensID:
1477				case PTP_DPC_CANON_EOS_StroboFiring:
1478					dpd->DataType = PTP_DTC_UINT32;
1479					break;
1480				case PTP_DPC_CANON_EOS_Aperture:
1481				case PTP_DPC_CANON_EOS_ShutterSpeed:
1482				case PTP_DPC_CANON_EOS_ISOSpeed:
1483				case PTP_DPC_CANON_EOS_FocusMode:
1484				case PTP_DPC_CANON_EOS_AutoExposureMode:
1485				case PTP_DPC_CANON_EOS_ColorSpace:
1486				case PTP_DPC_CANON_EOS_BatteryPower:
1487				case PTP_DPC_CANON_EOS_PTPExtensionVersion:
1488				case PTP_DPC_CANON_EOS_DriveMode:
1489				case PTP_DPC_CANON_EOS_AEB:
1490					dpd->DataType = PTP_DTC_UINT16;
1491					break;
1492				case PTP_DPC_CANON_EOS_PictureStyle:
1493				case PTP_DPC_CANON_EOS_WhiteBalance:
1494				case PTP_DPC_CANON_EOS_MeteringMode:
1495				case PTP_DPC_CANON_EOS_ExpCompensation: /* actually int8 if you calculate */
1496					dpd->DataType = PTP_DTC_UINT8;
1497					break;
1498				case PTP_DPC_CANON_EOS_Owner:
1499				case PTP_DPC_CANON_EOS_Artist:
1500				case PTP_DPC_CANON_EOS_Copyright:
1501				case PTP_DPC_CANON_EOS_SerialNumber:
1502				case PTP_DPC_CANON_EOS_LensName:
1503					dpd->DataType = PTP_DTC_STR;
1504					break;
1505				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
1506				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
1507					dpd->DataType = PTP_DTC_INT16;
1508					break;
1509				/* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
1510				case PTP_DPC_CANON_EOS_BatterySelect:
1511				case 0xd114:
1512				case PTP_DPC_CANON_EOS_DPOFVersion:
1513				case PTP_DPC_CANON_EOS_BracketMode:
1514					dpd->DataType = PTP_DTC_UINT16;
1515					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
1516					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1517						ptp_debug (params, "    %d: %02x", j, data[j]);
1518					break;
1519				case PTP_DPC_CANON_EOS_CustomFunc1:
1520				case PTP_DPC_CANON_EOS_CustomFunc2:
1521				case PTP_DPC_CANON_EOS_CustomFunc3:
1522				case PTP_DPC_CANON_EOS_CustomFunc4:
1523				case PTP_DPC_CANON_EOS_CustomFunc5:
1524				case PTP_DPC_CANON_EOS_CustomFunc6:
1525				case PTP_DPC_CANON_EOS_CustomFunc7:
1526				case PTP_DPC_CANON_EOS_CustomFunc8:
1527				case PTP_DPC_CANON_EOS_CustomFunc9:
1528				case PTP_DPC_CANON_EOS_CustomFunc10:
1529				case PTP_DPC_CANON_EOS_CustomFunc11:
1530					dpd->DataType = PTP_DTC_UINT8;
1531					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint8", i ,proptype, size-PTP_ece_Prop_Val_Data);
1532					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1533						ptp_debug (params, "    %d: %02x", j, data[j]);
1534					/* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */
1535					data += 4;
1536					break;
1537				/* yet unknown 32bit props */
1538				case PTP_DPC_CANON_EOS_ColorTemperature:
1539				case PTP_DPC_CANON_EOS_WftStatus:
1540				case PTP_DPC_CANON_EOS_LensStatus:
1541				case PTP_DPC_CANON_EOS_CardExtension:
1542				case PTP_DPC_CANON_EOS_TempStatus:
1543				case PTP_DPC_CANON_EOS_PhotoStudioMode:
1544				case PTP_DPC_CANON_EOS_EVFMode:
1545				case PTP_DPC_CANON_EOS_DepthOfFieldPreview:
1546				case PTP_DPC_CANON_EOS_EVFSharpness:
1547				case PTP_DPC_CANON_EOS_EVFWBMode:
1548				case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
1549				case PTP_DPC_CANON_EOS_EVFColorTemp:
1550				case PTP_DPC_CANON_EOS_EVFRecordStatus:
1551				case PTP_DPC_CANON_EOS_ExposureSimMode:
1552				case PTP_DPC_CANON_EOS_LvAfSystem:
1553				case PTP_DPC_CANON_EOS_MovSize:
1554				case PTP_DPC_CANON_EOS_DepthOfField:
1555				case PTP_DPC_CANON_EOS_LvViewTypeSelect:
1556				case PTP_DPC_CANON_EOS_ImageFormat:
1557				case PTP_DPC_CANON_EOS_ImageFormatCF:
1558				case PTP_DPC_CANON_EOS_ImageFormatSD:
1559				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1560				case PTP_DPC_CANON_EOS_CustomFuncEx:
1561//					dpd->DataType = PTP_DTC_UINT32;
1562					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
1563					if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
1564						ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
1565					for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
1566						ptp_debug (params, "    %d: 0x%8x", j, ((uint32_t*)data)[j]);
1567					break;
1568				default:
1569					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
1570					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1571						ptp_debug (params, "    %d: %02x", j, data[j]);
1572					break;
1573				}
1574				switch (dpd->DataType) {
1575				case PTP_DTC_UINT32:
1576					dpd->FactoryDefaultValue.u32	= dtoh32a(data);
1577					dpd->CurrentValue.u32		= dtoh32a(data);
1578					ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
1579					break;
1580				case PTP_DTC_UINT16:
1581					dpd->FactoryDefaultValue.u16	= dtoh16a(data);
1582					dpd->CurrentValue.u16		= dtoh16a(data);
1583					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
1584					break;
1585				case PTP_DTC_UINT8:
1586					dpd->FactoryDefaultValue.u8	= dtoh8a(data);
1587					dpd->CurrentValue.u8		= dtoh8a(data);
1588					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
1589					break;
1590				case PTP_DTC_STR: {
1591#if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
1592					uint8_t len = 0;
1593					dpd->FactoryDefaultValue.str	= ptp_unpack_string(params, data, 0, &len);
1594					dpd->CurrentValue.str		= ptp_unpack_string(params, data, 0, &len);
1595#else
1596					dpd->FactoryDefaultValue.str	= strdup( (char*)data );
1597					dpd->CurrentValue.str		= strdup( (char*)data );
1598#endif
1599					ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
1600					break;
1601				}
1602				default:
1603					/* debug is printed in switch above this one */
1604					break;
1605				}
1606
1607				/* ImageFormat special handling */
1608				switch (proptype) {
1609				case PTP_DPC_CANON_EOS_ImageFormat:
1610				case PTP_DPC_CANON_EOS_ImageFormatCF:
1611				case PTP_DPC_CANON_EOS_ImageFormatSD:
1612				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1613					dpd->DataType = PTP_DTC_UINT16;
1614					dpd->FactoryDefaultValue.u16	= ptp_unpack_EOS_ImageFormat( params, &data );
1615					dpd->CurrentValue.u16		= dpd->FactoryDefaultValue.u16;
1616					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
1617					break;
1618				}
1619
1620				break;
1621		}
1622		case 0: /* end marker */
1623			if (size == 8) /* no output */
1624				break;
1625			ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
1626			break;
1627		default:
1628			switch (type) {
1629#define XX(x)		case PTP_EC_CANON_EOS_##x: ptp_debug (params, "event %d: unhandled EOS event "#x" (size %d)", i, size);break;
1630			XX(RequestGetEvent)
1631			XX(ObjectRemoved)
1632			XX(RequestGetObjectInfoEx)
1633			XX(StorageStatusChanged)
1634			XX(StorageInfoChanged)
1635			XX(ObjectInfoChangedEx)
1636			XX(ObjectContentChanged)
1637			XX(CameraStatusChanged)
1638			XX(WillSoonShutdown)
1639			XX(ShutdownTimerUpdated)
1640			XX(RequestCancelTransfer)
1641			XX(RequestObjectTransferDT)
1642			XX(RequestCancelTransferDT)
1643			XX(StoreAdded)
1644			XX(StoreRemoved)
1645			XX(BulbExposureTime)
1646			XX(RecordingTime)
1647			XX(RequestObjectTransferTS)
1648			XX(AfResult)
1649#undef XX
1650			default:
1651				ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
1652				break;
1653			}
1654			if (size >= 0x8) {	/* event info */
1655				int j;
1656				for (j=8;j<size;j++)
1657					ptp_debug (params, "    %d: %02x", j, curdata[j]);
1658			}
1659			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1660			break;
1661		}
1662		curdata += size;
1663		i++;
1664		if ((size == 8) && (type == 0))
1665			break;
1666	}
1667
1668	return entries;
1669}
1670
1671/*
1672    PTP USB Event container unpack for Nikon events.
1673*/
1674#define PTP_nikon_ec_Length		0
1675#define PTP_nikon_ec_Code		2
1676#define PTP_nikon_ec_Param1		4
1677#define PTP_nikon_ec_Size		6
1678static inline void
1679ptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, int *cnt)
1680{
1681	int i;
1682
1683	*ec = NULL;
1684	if (data == NULL)
1685		return;
1686	if (len < PTP_nikon_ec_Code)
1687		return;
1688	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
1689	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
1690		return;
1691	*ec = malloc(sizeof(PTPContainer)*(*cnt));
1692
1693	for (i=0;i<*cnt;i++) {
1694		memset(&(*ec)[i],0,sizeof(PTPContainer));
1695		(*ec)[i].Code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
1696		(*ec)[i].Param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
1697		(*ec)[i].Nparam	= 1;
1698	}
1699}
1700
1701
1702static inline uint32_t
1703ptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
1704	int i, len = 0;
1705	uint8_t	retlen;
1706	unsigned char *curdata;
1707
1708	len =	2*(strlen(text->title)+1)+1+
1709		2*(strlen(text->line[0])+1)+1+
1710		2*(strlen(text->line[1])+1)+1+
1711		2*(strlen(text->line[2])+1)+1+
1712		2*(strlen(text->line[3])+1)+1+
1713		2*(strlen(text->line[4])+1)+1+
1714		4*2+2*4+2+4+2+5*4*2;
1715	*data = malloc(len);
1716	if (!*data) return 0;
1717
1718	curdata = *data;
1719	htod16a(curdata,100);curdata+=2;
1720	htod16a(curdata,1);curdata+=2;
1721	htod16a(curdata,0);curdata+=2;
1722	htod16a(curdata,1000);curdata+=2;
1723
1724	htod32a(curdata,0);curdata+=4;
1725	htod32a(curdata,0);curdata+=4;
1726
1727	htod16a(curdata,6);curdata+=2;
1728	htod32a(curdata,0);curdata+=4;
1729
1730	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1731	htod16a(curdata,0x10);curdata+=2;
1732
1733	for (i=0;i<5;i++) {
1734		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1735		htod16a(curdata,0x10);curdata+=2;
1736		htod16a(curdata,0x01);curdata+=2;
1737		htod16a(curdata,0x02);curdata+=2;
1738		htod16a(curdata,0x06);curdata+=2;
1739	}
1740	return len;
1741}
1742
1743#define ptp_canon_dir_version	0x00
1744#define ptp_canon_dir_ofc	0x02
1745#define ptp_canon_dir_unk1	0x04
1746#define ptp_canon_dir_objectid	0x08
1747#define ptp_canon_dir_parentid	0x0c
1748#define ptp_canon_dir_previd	0x10	/* in same dir */
1749#define ptp_canon_dir_nextid	0x14	/* in same dir */
1750#define ptp_canon_dir_nextchild	0x18	/* down one dir */
1751#define ptp_canon_dir_storageid	0x1c	/* only in storage entry */
1752#define ptp_canon_dir_name	0x20
1753#define ptp_canon_dir_flags	0x2c
1754#define ptp_canon_dir_size	0x30
1755#define ptp_canon_dir_unixtime	0x34
1756#define ptp_canon_dir_year	0x38
1757#define ptp_canon_dir_month	0x39
1758#define ptp_canon_dir_mday	0x3a
1759#define ptp_canon_dir_hour	0x3b
1760#define ptp_canon_dir_minute	0x3c
1761#define ptp_canon_dir_second	0x3d
1762#define ptp_canon_dir_unk2	0x3e
1763#define ptp_canon_dir_thumbsize	0x40
1764#define ptp_canon_dir_width	0x44
1765#define ptp_canon_dir_height	0x48
1766
1767static inline uint16_t
1768ptp_unpack_canon_directory (
1769	PTPParams		*params,
1770	unsigned char		*dir,
1771	uint32_t		cnt,
1772	PTPObjectHandles	*handles,
1773	PTPObjectInfo		**oinfos,	/* size(handles->n) */
1774	uint32_t		**flags		/* size(handles->n) */
1775) {
1776	unsigned int	i, j, nrofobs = 0, curob = 0;
1777
1778#define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
1779	for (i=0;i<cnt;i++)
1780		if (ISOBJECT(dir+i*0x4c)) nrofobs++;
1781	handles->n = nrofobs;
1782	handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs);
1783	if (!handles->Handler) return PTP_RC_GeneralError;
1784	*oinfos = calloc(sizeof((*oinfos)[0]),nrofobs);
1785	if (!*oinfos) return PTP_RC_GeneralError;
1786	*flags  = calloc(sizeof((*flags)[0]),nrofobs);
1787	if (!*flags) return PTP_RC_GeneralError;
1788
1789	/* Migrate data into objects ids, handles into
1790	 * the object handler array.
1791	 */
1792	curob = 0;
1793	for (i=0;i<cnt;i++) {
1794		unsigned char	*cur = dir+i*0x4c;
1795		PTPObjectInfo	*oi = (*oinfos)+curob;
1796
1797		if (!ISOBJECT(cur))
1798			continue;
1799
1800		handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
1801		oi->StorageID		= 0xffffffff;
1802		oi->ObjectFormat	= dtoh16a(cur + ptp_canon_dir_ofc);
1803		oi->ParentObject	= dtoh32a(cur + ptp_canon_dir_parentid);
1804		oi->Filename		= strdup((char*)(cur + ptp_canon_dir_name));
1805		oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
1806		oi->ThumbCompressedSize	= dtoh32a(cur + ptp_canon_dir_thumbsize);
1807		oi->ImagePixWidth	= dtoh32a(cur + ptp_canon_dir_width);
1808		oi->ImagePixHeight	= dtoh32a(cur + ptp_canon_dir_height);
1809		oi->CaptureDate		= oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
1810		(*flags)[curob]		= dtoh32a(cur + ptp_canon_dir_flags);
1811		curob++;
1812	}
1813	/* Walk over Storage ID entries and distribute the IDs to
1814	 * the parent objects. */
1815	for (i=0;i<cnt;i++) {
1816		unsigned char	*cur = dir+i*0x4c;
1817		uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
1818
1819		if (ISOBJECT(cur))
1820			continue;
1821		for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
1822		if (j == handles->n) continue;
1823		(*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
1824	}
1825	/* Walk over all objects and distribute the storage ids */
1826	while (1) {
1827		int changed = 0;
1828		for (i=0;i<cnt;i++) {
1829			unsigned char	*cur = dir+i*0x4c;
1830			uint32_t	oid = dtoh32a(cur + ptp_canon_dir_objectid);
1831			uint32_t	nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
1832			uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
1833			uint32_t	storageid;
1834
1835			if (!ISOBJECT(cur))
1836				continue;
1837			for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
1838			if (j == handles->n) {
1839				/*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
1840				continue;
1841			}
1842	 		storageid = (*oinfos)[j].StorageID;
1843			if (storageid == 0xffffffff) continue;
1844			if (nextoid != 0xffffffff) {
1845				for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
1846				if (j == handles->n) {
1847					/*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
1848					continue;
1849				}
1850				if ((*oinfos)[j].StorageID == 0xffffffff) {
1851					(*oinfos)[j].StorageID = storageid;
1852					changed++;
1853				}
1854			}
1855			if (nextchild != 0xffffffff) {
1856				for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
1857				if (j == handles->n) {
1858					/*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
1859					continue;
1860				}
1861				if ((*oinfos)[j].StorageID == 0xffffffff) {
1862					(*oinfos)[j].StorageID = storageid;
1863					changed++;
1864				}
1865			}
1866		}
1867		/* Check if we:
1868		 * - changed no entry (nothing more to do)
1869		 * - changed all of them at once (usually happens)
1870		 * break if we do.
1871		 */
1872		if (!changed || (changed==nrofobs-1))
1873			break;
1874	}
1875#undef ISOBJECT
1876	return PTP_RC_OK;
1877}
1878