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