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 = ¶ms->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 (¶ms->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 = ¶ms->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