libmtp: ptp-pack.c Source File

libmtp 1.1.23

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