• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* currently this file is included into ptp.c */
2 
3 #ifdef HAVE_ICONV
4 #include <iconv.h>
5 #endif
6 
7 extern void
8 ptp_debug (PTPParams *params, const char *format, ...);
9 
10 static inline uint16_t
htod16p(PTPParams * params,uint16_t var)11 htod16p (PTPParams *params, uint16_t var)
12 {
13 	return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
14 }
15 
16 static inline uint32_t
htod32p(PTPParams * params,uint32_t var)17 htod32p (PTPParams *params, uint32_t var)
18 {
19 	return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
20 }
21 
22 static inline void
htod16ap(PTPParams * params,unsigned char * a,uint16_t val)23 htod16ap (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 
31 static inline void
htod32ap(PTPParams * params,unsigned char * a,uint32_t val)32 htod32ap (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 
40 static inline void
htod64ap(PTPParams * params,unsigned char * a,uint64_t val)41 htod64ap (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 
49 static inline uint16_t
dtoh16p(PTPParams * params,uint16_t var)50 dtoh16p (PTPParams *params, uint16_t var)
51 {
52 	return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
53 }
54 
55 static inline uint32_t
dtoh32p(PTPParams * params,uint32_t var)56 dtoh32p (PTPParams *params, uint32_t var)
57 {
58 	return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
59 }
60 
61 static inline uint64_t
dtoh64p(PTPParams * params,uint64_t var)62 dtoh64p (PTPParams *params, uint64_t var)
63 {
64 	return ((params->byteorder==PTP_DL_LE)?le64toh(var):be64toh(var));
65 }
66 
67 static inline uint16_t
dtoh16ap(PTPParams * params,const unsigned char * a)68 dtoh16ap (PTPParams *params, const unsigned char *a)
69 {
70 	return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
71 }
72 
73 static inline uint32_t
dtoh32ap(PTPParams * params,const unsigned char * a)74 dtoh32ap (PTPParams *params, const unsigned char *a)
75 {
76 	return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
77 }
78 
79 static inline uint64_t
dtoh64ap(PTPParams * params,const unsigned char * a)80 dtoh64ap (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 
102 static inline char*
ptp_unpack_string(PTPParams * params,unsigned char * data,uint16_t offset,uint8_t * len)103 ptp_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 
148 static inline int
ucs2strlen(uint16_t const * const unicstr)149 ucs2strlen(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 
159 static inline void
ptp_pack_string(PTPParams * params,char * string,unsigned char * data,uint16_t offset,uint8_t * len)160 ptp_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 
208 static inline unsigned char *
ptp_get_packed_stringcopy(PTPParams * params,char * string,uint32_t * packed_size)209 ptp_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 
233 static inline uint32_t
ptp_unpack_uint32_t_array(PTPParams * params,unsigned char * data,uint16_t offset,uint32_t ** array)234 ptp_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 
247 static inline uint32_t
ptp_pack_uint32_t_array(PTPParams * params,uint32_t * array,uint32_t arraylen,unsigned char ** data)248 ptp_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 
259 static inline uint32_t
ptp_unpack_uint16_t_array(PTPParams * params,unsigned char * data,uint16_t offset,uint16_t ** array)260 ptp_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 
282 static inline void
ptp_unpack_DI(PTPParams * params,unsigned char * data,PTPDeviceInfo * di,unsigned int datalen)283 ptp_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 
339 static void
ptp_free_DI(PTPDeviceInfo * di)340 ptp_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 */
354 static inline void
ptp_unpack_EOS_DI(PTPParams * params,unsigned char * data,PTPCanonEOSDeviceInfo * di,unsigned int datalen)355 ptp_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 
384 static inline void
ptp_unpack_OH(PTPParams * params,unsigned char * data,PTPObjectHandles * oh,unsigned int len)385 ptp_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 
399 static inline void
ptp_unpack_SIDs(PTPParams * params,unsigned char * data,PTPStorageIDs * sids,unsigned int len)400 ptp_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 
416 static inline void
ptp_unpack_SI(PTPParams * params,unsigned char * data,PTPStorageInfo * si,unsigned int len)417 ptp_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 
458 static inline uint32_t
ptp_pack_OI(PTPParams * params,PTPObjectInfo * oi,unsigned char ** oidataptr)459 ptp_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 
520 static time_t
ptp_unpack_PTPTIME(const char * str)521 ptp_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 
565 static inline void
ptp_unpack_OI(PTPParams * params,unsigned char * data,PTPObjectInfo * oi,unsigned int len)566 ptp_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 
627 static inline int
ptp_unpack_DPV(PTPParams * params,unsigned char * data,int * offset,int total,PTPPropertyValue * value,uint16_t datatype)628 ptp_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 
717 static inline int
ptp_unpack_DPD(PTPParams * params,unsigned char * data,PTPDevicePropDesc * dpd,unsigned int dpdlen)718 ptp_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;
785 outofmemory:
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 
796 static inline int
ptp_unpack_OPD(PTPParams * params,unsigned char * data,PTPObjectPropDesc * opd,unsigned int opdlen)797 ptp_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;
854 outofmemory:
855 	ptp_free_objectpropdesc(opd);
856 	return 0;
857 }
858 
859 
860 static inline uint32_t
ptp_pack_DPV(PTPParams * params,PTPPropertyValue * value,unsigned char ** dpvptr,uint16_t datatype)861 ptp_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
975 static inline uint32_t
ptp_pack_OPL(PTPParams * params,MTPProperties * props,int nrofprops,unsigned char ** opldataptr)976 ptp_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 
1033 static int
_compare_func(const void * x,const void * y)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 
1041 static inline int
ptp_unpack_OPL(PTPParams * params,unsigned char * data,MTPProperties ** pprops,unsigned int len)1042 ptp_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 
1101 static inline void
ptp_unpack_EC(PTPParams * params,unsigned char * data,PTPContainer * ec,unsigned int len)1102 ptp_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 
1145 static inline void
ptp_unpack_Canon_FE(PTPParams * params,unsigned char * data,PTPCANONFolderEntry * fe)1146 ptp_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 
1160 static inline uint16_t
ptp_unpack_EOS_ImageFormat(PTPParams * params,unsigned char ** data)1161 ptp_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 
1221 static inline uint32_t
ptp_pack_EOS_ImageFormat(PTPParams * params,unsigned char * data,uint16_t value)1222 ptp_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 
1272 static inline int
ptp_unpack_CANON_changes(PTPParams * params,unsigned char * data,int datasize,PTPCanon_changes_entry ** ce)1273 ptp_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
1678 static inline void
ptp_unpack_Nikon_EC(PTPParams * params,unsigned char * data,unsigned int len,PTPContainer ** ec,int * cnt)1679 ptp_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 
1702 static inline uint32_t
ptp_pack_EK_text(PTPParams * params,PTPEKTextParams * text,unsigned char ** data)1703 ptp_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 
1767 static inline uint16_t
ptp_unpack_canon_directory(PTPParams * params,unsigned char * dir,uint32_t cnt,PTPObjectHandles * handles,PTPObjectInfo ** oinfos,uint32_t ** flags)1768 ptp_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