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