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