Code Sync up from tizen_2.4
[platform/upstream/libmtp.git] / src / ptp.c
1 /* ptp.c
2  *
3  * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
4  * Copyright (C) 2003-2012 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 #define _BSD_SOURCE
26 #include "config.h"
27 #include "ptp.h"
28
29 #ifdef HAVE_LIBXML2
30 # include <libxml/parser.h>
31 #endif
32
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 #ifdef ENABLE_NLS
40 #  include <libintl.h>
41 #  undef _
42 #  define _(String) dgettext (PACKAGE, String)
43 #  ifdef gettext_noop
44 #    define N_(String) gettext_noop (String)
45 #  else
46 #    define N_(String) (String)
47 #  endif
48 #else
49 #  define textdomain(String) (String)
50 #  define gettext(String) (String)
51 #  define dgettext(Domain,Message) (Message)
52 #  define dcgettext(Domain,Message,Type) (Message)
53 #  define bindtextdomain(Domain,Directory) (Domain)
54 #  define _(String) (String)
55 #  define N_(String) (String)
56 #endif
57
58 #define CHECK_PTP_RC(result)    {uint16_t r=(result); if (r!=PTP_RC_OK) return r;}
59
60 #define PTP_CNT_INIT(cnt) {memset(&cnt,0,sizeof(cnt));}
61
62 static uint16_t ptp_exit_recv_memory_handler (PTPDataHandler*,unsigned char**,unsigned long*);
63 static uint16_t ptp_init_recv_memory_handler(PTPDataHandler*);
64 static uint16_t ptp_init_send_memory_handler(PTPDataHandler*,unsigned char*,unsigned long len);
65 static uint16_t ptp_exit_send_memory_handler (PTPDataHandler *handler);
66
67 void
68 ptp_debug (PTPParams *params, const char *format, ...)
69 {
70         va_list args;
71
72         va_start (args, format);
73         if (params->debug_func!=NULL)
74                 params->debug_func (params->data, format, args);
75         else
76         {
77                 vfprintf (stderr, format, args);
78                 fprintf (stderr,"\n");
79                 fflush (stderr);
80         }
81         va_end (args);
82 }
83
84 void
85 ptp_error (PTPParams *params, const char *format, ...)
86 {
87         va_list args;
88
89         va_start (args, format);
90         if (params->error_func!=NULL)
91                 params->error_func (params->data, format, args);
92         else
93         {
94                 vfprintf (stderr, format, args);
95                 fprintf (stderr,"\n");
96                 fflush (stderr);
97         }
98         va_end (args);
99 }
100
101 /* Pack / unpack functions */
102
103 #include "ptp-pack.c"
104
105 /* major PTP functions */
106
107 /* Transaction data phase description */
108 #define PTP_DP_NODATA           0x0000  /* no data phase */
109 #define PTP_DP_SENDDATA         0x0001  /* sending data */
110 #define PTP_DP_GETDATA          0x0002  /* receiving data */
111 #define PTP_DP_DATA_MASK        0x00ff  /* data phase mask */
112
113 /**
114  * ptp_transaction:
115  * params:      PTPParams*
116  *              PTPContainer* ptp       - general ptp container
117  *              uint16_t flags          - lower 8 bits - data phase description
118  *              unsigned int sendlen    - senddata phase data length
119  *              char** data             - send or receive data buffer pointer
120  *              int* recvlen            - receive data length
121  *
122  * Performs PTP transaction. ptp is a PTPContainer with appropriate fields
123  * filled in (i.e. operation code and parameters). It's up to caller to do
124  * so.
125  * The flags decide thether the transaction has a data phase and what is its
126  * direction (send or receive).
127  * If transaction is sending data the sendlen should contain its length in
128  * bytes, otherwise it's ignored.
129  * The data should contain an address of a pointer to data going to be sent
130  * or is filled with such a pointer address if data are received depending
131  * od dataphase direction (send or received) or is beeing ignored (no
132  * dataphase).
133  * The memory for a pointer should be preserved by the caller, if data are
134  * beeing retreived the appropriate amount of memory is beeing allocated
135  * (the caller should handle that!).
136  *
137  * Return values: Some PTP_RC_* code.
138  * Upon success PTPContainer* ptp contains PTP Response Phase container with
139  * all fields filled in.
140  **/
141 uint16_t
142 ptp_transaction_new (PTPParams* params, PTPContainer* ptp,
143                      uint16_t flags, uint64_t sendlen,
144                      PTPDataHandler *handler
145 ) {
146         int             tries;
147         uint16_t        cmd;
148
149         if ((params==NULL) || (ptp==NULL))
150                 return PTP_ERROR_BADPARAM;
151
152         cmd = ptp->Code;
153         ptp->Transaction_ID=params->transaction_id++;
154         ptp->SessionID=params->session_id;
155         /* send request */
156         CHECK_PTP_RC(params->sendreq_func (params, ptp));
157         /* is there a dataphase? */
158         switch (flags&PTP_DP_DATA_MASK) {
159         case PTP_DP_SENDDATA:
160                 {
161                         uint16_t ret;
162                         ret = params->senddata_func(params, ptp,
163                                                     sendlen, handler);
164                         if (ret == PTP_ERROR_CANCEL) {
165                                 ret = params->cancelreq_func(params,
166                                                              params->transaction_id-1);
167                                 if (ret == PTP_RC_OK)
168                                         ret = PTP_ERROR_CANCEL;
169                         }
170                         if (ret != PTP_RC_OK)
171                                 return ret;
172                 }
173                 break;
174         case PTP_DP_GETDATA:
175                 {
176                         uint16_t ret;
177                         ret = params->getdata_func(params, ptp, handler);
178                         if (ret == PTP_ERROR_CANCEL) {
179                                 ret = params->cancelreq_func(params,
180                                                              params->transaction_id-1);
181                                 if (ret == PTP_RC_OK)
182                                         ret = PTP_ERROR_CANCEL;
183                         }
184                         if (ret != PTP_RC_OK)
185                                 return ret;
186                 }
187                 break;
188         case PTP_DP_NODATA:
189                 break;
190         default:
191                 return PTP_ERROR_BADPARAM;
192         }
193         tries = 3;
194         while (tries--) {
195                 uint16_t ret;
196                 /* get response */
197                 ret = params->getresp_func(params, ptp);
198                 if (ret == PTP_ERROR_RESP_EXPECTED) {
199                         ptp_debug (params,"PTP: response expected but not got, retrying.");
200                         tries++;
201                         continue;
202                 }
203                 if (ret != PTP_RC_OK)
204                         return ret;
205
206                 if (ptp->Transaction_ID < params->transaction_id-1) {
207                         tries++;
208                         ptp_debug (params,
209                                 "PTP: Sequence number mismatch %d vs expected %d, suspecting old reply.",
210                                 ptp->Transaction_ID, params->transaction_id-1
211                         );
212                         continue;
213                 }
214                 if (ptp->Transaction_ID != params->transaction_id-1) {
215                         /* try to clean up potential left overs from previous session */
216                         if ((cmd == PTP_OC_OpenSession) && tries)
217                                 continue;
218                         ptp_error (params,
219                                 "PTP: Sequence number mismatch %d vs expected %d.",
220                                 ptp->Transaction_ID, params->transaction_id-1
221                         );
222                         return PTP_ERROR_BADPARAM;
223                 }
224                 break;
225         }
226         return ptp->Code;
227 }
228
229 /* memory data get/put handler */
230 typedef struct {
231         unsigned char   *data;
232         unsigned long   size, curoff;
233 } PTPMemHandlerPrivate;
234
235 static uint16_t
236 memory_getfunc(PTPParams* params, void* private,
237                unsigned long wantlen, unsigned char *data,
238                unsigned long *gotlen
239 ) {
240         PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private;
241         unsigned long tocopy = wantlen;
242
243         if (priv->curoff + tocopy > priv->size)
244                 tocopy = priv->size - priv->curoff;
245         memcpy (data, priv->data + priv->curoff, tocopy);
246         priv->curoff += tocopy;
247         *gotlen = tocopy;
248         return PTP_RC_OK;
249 }
250
251 static uint16_t
252 memory_putfunc(PTPParams* params, void* private,
253                unsigned long sendlen, unsigned char *data,
254                unsigned long *putlen
255 ) {
256         PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private;
257
258         if (priv->curoff + sendlen > priv->size) {
259                 priv->data = realloc (priv->data, priv->curoff+sendlen);
260                 if (!priv->data)
261                         return PTP_RC_GeneralError;
262                 priv->size = priv->curoff + sendlen;
263         }
264         memcpy (priv->data + priv->curoff, data, sendlen);
265         priv->curoff += sendlen;
266         *putlen = sendlen;
267         return PTP_RC_OK;
268 }
269
270 /* init private struct for receiving data. */
271 static uint16_t
272 ptp_init_recv_memory_handler(PTPDataHandler *handler) {
273         PTPMemHandlerPrivate* priv;
274         priv = malloc (sizeof(PTPMemHandlerPrivate));
275         if (!priv)
276                 return PTP_RC_GeneralError;
277         handler->priv = priv;
278         handler->getfunc = memory_getfunc;
279         handler->putfunc = memory_putfunc;
280         priv->data = NULL;
281         priv->size = 0;
282         priv->curoff = 0;
283         return PTP_RC_OK;
284 }
285
286 /* init private struct and put data in for sending data.
287  * data is still owned by caller.
288  */
289 static uint16_t
290 ptp_init_send_memory_handler(PTPDataHandler *handler,
291         unsigned char *data, unsigned long len
292 ) {
293         PTPMemHandlerPrivate* priv;
294         priv = malloc (sizeof(PTPMemHandlerPrivate));
295         if (!priv)
296                 return PTP_RC_GeneralError;
297         handler->priv = priv;
298         handler->getfunc = memory_getfunc;
299         handler->putfunc = memory_putfunc;
300         priv->data = data;
301         priv->size = len;
302         priv->curoff = 0;
303         return PTP_RC_OK;
304 }
305
306 /* free private struct + data */
307 static uint16_t
308 ptp_exit_send_memory_handler (PTPDataHandler *handler) {
309         PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->priv;
310         /* data is owned by caller */
311         free (priv);
312         return PTP_RC_OK;
313 }
314
315 /* hand over our internal data to caller */
316 static uint16_t
317 ptp_exit_recv_memory_handler (PTPDataHandler *handler,
318         unsigned char **data, unsigned long *size
319 ) {
320         PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->priv;
321         *data = priv->data;
322         *size = priv->size;
323         free (priv);
324         return PTP_RC_OK;
325 }
326
327 /* fd data get/put handler */
328 typedef struct {
329         int fd;
330 } PTPFDHandlerPrivate;
331
332 static uint16_t
333 fd_getfunc(PTPParams* params, void* private,
334                unsigned long wantlen, unsigned char *data,
335                unsigned long *gotlen
336 ) {
337         PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)private;
338         int             got;
339
340         got = read (priv->fd, data, wantlen);
341         if (got != -1)
342                 *gotlen = got;
343         else
344                 return PTP_RC_GeneralError;
345         return PTP_RC_OK;
346 }
347
348 static uint16_t
349 fd_putfunc(PTPParams* params, void* private,
350                unsigned long sendlen, unsigned char *data,
351                unsigned long *putlen
352 ) {
353         int             written;
354         PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)private;
355
356         written = write (priv->fd, data, sendlen);
357         if (written != -1)
358                 *putlen = written;
359         else
360                 return PTP_RC_GeneralError;
361         return PTP_RC_OK;
362 }
363
364 static uint16_t
365 ptp_init_fd_handler(PTPDataHandler *handler, int fd) {
366         PTPFDHandlerPrivate* priv;
367         priv = malloc (sizeof(PTPFDHandlerPrivate));
368         if (!priv)
369                 return PTP_RC_GeneralError;
370         handler->priv = priv;
371         handler->getfunc = fd_getfunc;
372         handler->putfunc = fd_putfunc;
373         priv->fd = fd;
374         return PTP_RC_OK;
375 }
376
377 static uint16_t
378 ptp_exit_fd_handler (PTPDataHandler *handler) {
379         PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)handler->priv;
380         free (priv);
381         return PTP_RC_OK;
382 }
383
384 /* Old style transaction, based on memory */
385 uint16_t
386 ptp_transaction (PTPParams* params, PTPContainer* ptp,
387                 uint16_t flags, uint64_t sendlen,
388                 unsigned char **data, unsigned int *recvlen
389 ) {
390         PTPDataHandler  handler;
391         uint16_t        ret;
392
393         switch (flags & PTP_DP_DATA_MASK) {
394         case PTP_DP_SENDDATA:
395                 ret = ptp_init_send_memory_handler (&handler, *data, sendlen);
396                 if (ret != PTP_RC_OK) return ret;
397                 break;
398         case PTP_DP_GETDATA:
399                 ret = ptp_init_recv_memory_handler (&handler);
400                 if (ret != PTP_RC_OK) return ret;
401                 break;
402         default:break;
403         }
404         ret = ptp_transaction_new (params, ptp, flags, sendlen, &handler);
405         switch (flags & PTP_DP_DATA_MASK) {
406         case PTP_DP_SENDDATA:
407                 ptp_exit_send_memory_handler (&handler);
408                 break;
409         case PTP_DP_GETDATA: {
410                 unsigned long len;
411                 ptp_exit_recv_memory_handler (&handler, data, &len);
412                 if (recvlen)
413                         *recvlen = len;
414                 break;
415         }
416         default:break;
417         }
418         return ret;
419 }
420
421
422 /**
423  * PTP operation functions
424  *
425  * all ptp_ functions should take integer parameters
426  * in host byte order!
427  **/
428
429
430 /**
431  * ptp_getdeviceinfo:
432  * params:      PTPParams*
433  *
434  * Gets device info dataset and fills deviceinfo structure.
435  *
436  * Return values: Some PTP_RC_* code.
437  **/
438 uint16_t
439 ptp_getdeviceinfo (PTPParams* params, PTPDeviceInfo* deviceinfo)
440 {
441         uint16_t        ret;
442         unsigned long   len;
443         PTPContainer    ptp;
444         unsigned char*  di=NULL;
445         PTPDataHandler  handler;
446
447         ptp_init_recv_memory_handler (&handler);
448         PTP_CNT_INIT(ptp);
449         ptp.Code=PTP_OC_GetDeviceInfo;
450         ptp.Nparam=0;
451         len=0;
452         ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
453         ptp_exit_recv_memory_handler (&handler, &di, &len);
454         if (!di) ret = PTP_RC_GeneralError;
455         if (ret == PTP_RC_OK) ptp_unpack_DI(params, di, deviceinfo, len);
456         free(di);
457         return ret;
458 }
459
460 uint16_t
461 ptp_canon_eos_getdeviceinfo (PTPParams* params, PTPCanonEOSDeviceInfo*di)
462 {
463         uint16_t        ret;
464         PTPContainer    ptp;
465         PTPDataHandler  handler;
466         unsigned long   len;
467         unsigned char   *data;
468
469         ptp_init_recv_memory_handler (&handler);
470         PTP_CNT_INIT(ptp);
471         ptp.Code=PTP_OC_CANON_EOS_GetDeviceInfoEx;
472         ptp.Nparam=0;
473         len=0;
474         data=NULL;
475         ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
476         ptp_exit_recv_memory_handler (&handler, &data, &len);
477         if (ret == PTP_RC_OK) ptp_unpack_EOS_DI(params, data, di, len);
478         free (data);
479         return ret;
480 }
481
482 #ifdef HAVE_LIBXML2
483 static int
484 traverse_tree (PTPParams *params, int depth, xmlNodePtr node) {
485         xmlNodePtr      next;
486         xmlChar         *xchar;
487         int n;
488         char            *xx;
489
490
491         if (!node) return 0;
492         xx = malloc (depth * 4 + 1);
493         memset (xx, ' ', depth*4);
494         xx[depth*4] = 0;
495
496         n = xmlChildElementCount (node);
497
498         next = node;
499         do {
500                 fprintf(stderr,"%snode %s\n", xx,next->name);
501                 fprintf(stderr,"%selements %d\n", xx,n);
502                 xchar = xmlNodeGetContent (next);
503                 fprintf(stderr,"%scontent %s\n", xx,xchar);
504                 traverse_tree (params, depth+1,xmlFirstElementChild (next));
505         } while ((next = xmlNextElementSibling (next)));
506         free (xx);
507         return PTP_RC_OK;
508 }
509
510 static int
511 parse_9301_cmd_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) {
512         xmlNodePtr next;
513         int     cnt;
514
515         cnt = 0;
516         next = xmlFirstElementChild (node);
517         while (next) {
518                 cnt++;
519                 next = xmlNextElementSibling (next);
520         }
521         di->OperationsSupported_len = cnt;
522         di->OperationsSupported = malloc (cnt*sizeof(di->OperationsSupported[0]));
523         cnt = 0;
524         next = xmlFirstElementChild (node);
525         while (next) {
526                 unsigned int p;
527
528                 sscanf((char*)next->name, "c%04x", &p);
529                 ptp_debug( params, "cmd %s / 0x%04x", next->name, p);
530                 di->OperationsSupported[cnt++] = p;
531                 next = xmlNextElementSibling (next);
532         }
533         return PTP_RC_OK;
534 }
535
536 static int
537 parse_9301_value (PTPParams *params, const char *str, uint16_t type, PTPPropertyValue *propval) {
538         switch (type) {
539         case 6: { /*UINT32*/
540                 unsigned int x;
541                 if (!sscanf(str,"%08x", &x)) {
542                         ptp_debug( params, "could not parse uint32 %s", str);
543                         return PTP_RC_GeneralError;
544                 }
545                 ptp_debug( params, "\t%d", x);
546                 propval->u32 = x;
547                 break;
548         }
549         case 5: { /*INT32*/
550                 int x;
551                 if (!sscanf(str,"%08x", &x)) {
552                         ptp_debug( params, "could not parse int32 %s", str);
553                         return PTP_RC_GeneralError;
554                 }
555                 ptp_debug( params, "\t%d", x);
556                 propval->i32 = x;
557                 break;
558         }
559         case 4: { /*UINT16*/
560                 unsigned int x;
561                 if (!sscanf(str,"%04x", &x)) {
562                         ptp_debug( params, "could not parse uint16 %s", str);
563                         return PTP_RC_GeneralError;
564                 }
565                 ptp_debug( params, "\t%d", x);
566                 propval->u16 = x;
567                 break;
568         }
569         case 3: { /*INT16*/
570                 int x;
571                 if (!sscanf(str,"%04x", &x)) {
572                         ptp_debug( params, "could not parse int16 %s", str);
573                         return PTP_RC_GeneralError;
574                 }
575                 ptp_debug( params, "\t%d", x);
576                 propval->i16 = x;
577                 break;
578         }
579         case 2: { /*UINT8*/
580                 unsigned int x;
581                 if (!sscanf(str,"%02x", &x)) {
582                         ptp_debug( params, "could not parse uint8 %s", str);
583                         return PTP_RC_GeneralError;
584                 }
585                 ptp_debug( params, "\t%d", x);
586                 propval->u8 = x;
587                 break;
588         }
589         case 1: { /*INT8*/
590                 int x;
591                 if (!sscanf(str,"%02x", &x)) {
592                         ptp_debug( params, "could not parse int8 %s", str);
593                         return PTP_RC_GeneralError;
594                 }
595                 ptp_debug( params, "\t%d", x);
596                 propval->i8 = x;
597                 break;
598         }
599         case 65535: { /* string */
600                 int len;
601
602                 /* ascii ptp string, 1 byte length, little endian 16 bit chars */
603                 if (sscanf(str,"%02x", &len)) {
604                         int i;
605                         char *xstr = malloc(len+1);
606                         for (i=0;i<len;i++) {
607                                 int xc;
608                                 if (sscanf(str+2+i*4,"%04x", &xc)) {
609                                         int cx;
610
611                                         cx = ((xc>>8) & 0xff) | ((xc & 0xff) << 8);
612                                         xstr[i] = cx;
613                                 }
614                                 xstr[len] = 0;
615                         }
616                         ptp_debug( params, "\t%s", xstr);
617                         propval->str = xstr;
618                         break;
619                 }
620                 ptp_debug( params, "string %s not parseable!", str);
621                 return PTP_RC_GeneralError;
622         }
623         case 7: /*INT64*/
624         case 8: /*UINT64*/
625         case 9: /*INT128*/
626         case 10: /*UINT128*/
627         default:
628                 ptp_debug( params, "unhandled data type %d!", type);
629                 return PTP_RC_GeneralError;
630         }
631         return PTP_RC_OK;
632 }
633
634 static int
635 parse_9301_propdesc (PTPParams *params, xmlNodePtr next, PTPDevicePropDesc *dpd) {
636         int type = -1;
637
638         if (!next)
639                 return PTP_RC_GeneralError;
640
641         ptp_debug (params, "parse_9301_propdesc");
642         dpd->FormFlag   = PTP_DPFF_None;
643         dpd->GetSet     = PTP_DPGS_Get;
644         do {
645                 if (!strcmp((char*)next->name,"type")) {        /* propdesc.DataType */
646                         if (!sscanf((char*)xmlNodeGetContent (next), "%04x", &type)) {
647                                 ptp_debug( params, "\ttype %s not parseable?",xmlNodeGetContent (next));
648                                 return 0;
649                         }
650                         ptp_debug( params, "type 0x%x", type);
651                         dpd->DataType = type;
652                         continue;
653                 }
654                 if (!strcmp((char*)next->name,"attribute")) {   /* propdesc.GetSet */
655                         int attr;
656
657                         if (!sscanf((char*)xmlNodeGetContent (next), "%02x", &attr)) {
658                                 ptp_debug( params, "\tattr %s not parseable",xmlNodeGetContent (next));
659                                 return 0;
660                         }
661                         ptp_debug( params, "attribute 0x%x", attr);
662                         dpd->GetSet = attr;
663                         continue;
664                 }
665                 if (!strcmp((char*)next->name,"default")) {     /* propdesc.FactoryDefaultValue */
666                         ptp_debug( params, "default value");
667                         parse_9301_value (params, (char*)xmlNodeGetContent (next), type, &dpd->FactoryDefaultValue);
668                         continue;
669                 }
670                 if (!strcmp((char*)next->name,"value")) {       /* propdesc.CurrentValue */
671                         ptp_debug( params, "current value");
672                         parse_9301_value (params, (char*)xmlNodeGetContent (next), type, &dpd->CurrentValue);
673                         continue;
674                 }
675                 if (!strcmp((char*)next->name,"enum")) {        /* propdesc.FORM.Enum */
676                         int n,i;
677                         char *s;
678
679                         ptp_debug( params, "enum");
680                         dpd->FormFlag = PTP_DPFF_Enumeration;
681                         s = (char*)xmlNodeGetContent (next);
682                         n = 0;
683                         do {
684                                 s = strchr(s,' ');
685                                 if (s) s++;
686                                 n++;
687                         } while (s);
688                         dpd->FORM.Enum.NumberOfValues = n;
689                         dpd->FORM.Enum.SupportedValue = malloc (n * sizeof(PTPPropertyValue));
690                         s = (char*)xmlNodeGetContent (next);
691                         i = 0;
692                         do {
693                                 parse_9301_value (params, s, type, &dpd->FORM.Enum.SupportedValue[i]); /* should turn ' ' into \0? */
694                                 i++;
695                                 s = strchr(s,' ');
696                                 if (s) s++;
697                         } while (s && (i<n));
698                         continue;
699                 }
700                 if (!strcmp((char*)next->name,"range")) {       /* propdesc.FORM.Enum */
701                         char *s = (char*)xmlNodeGetContent (next);
702                         dpd->FormFlag = PTP_DPFF_Range;
703                         ptp_debug( params, "range");
704                         parse_9301_value (params, s, type, &dpd->FORM.Range.MinimumValue); /* should turn ' ' into \0? */
705                         s = strchr(s,' ');
706                         if (!s) continue;
707                         s++;
708                         parse_9301_value (params, s, type, &dpd->FORM.Range.MaximumValue); /* should turn ' ' into \0? */
709                         s = strchr(s,' ');
710                         if (!s) continue;
711                         s++;
712                         parse_9301_value (params, s, type, &dpd->FORM.Range.StepSize); /* should turn ' ' into \0? */
713
714                         continue;
715                 }
716                 ptp_debug (params, "\tpropdescvar: %s", next->name);
717                 traverse_tree (params, 3, next);
718         } while ((next = xmlNextElementSibling (next)));
719         return PTP_RC_OK;
720 }
721
722 static int
723 parse_9301_prop_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) {
724         xmlNodePtr      next;
725         int             cnt;
726         unsigned int    i;
727
728         cnt = 0;
729         next = xmlFirstElementChild (node);
730         while (next) {
731                 cnt++;
732                 next = xmlNextElementSibling (next);
733         }
734
735         di->DevicePropertiesSupported_len = cnt;
736         di->DevicePropertiesSupported = malloc (cnt*sizeof(di->DevicePropertiesSupported[0]));
737         cnt = 0;
738         next = xmlFirstElementChild (node);
739         while (next) {
740                 unsigned int p;
741                 PTPDevicePropDesc       dpd;
742
743                 sscanf((char*)next->name, "p%04x", &p);
744                 ptp_debug( params, "prop %s / 0x%04x", next->name, p);
745                 parse_9301_propdesc (params, xmlFirstElementChild (next), &dpd);
746                 dpd.DevicePropertyCode = p;
747                 di->DevicePropertiesSupported[cnt++] = p;
748
749                 /* add to cache of device propdesc */
750                 for (i=0;i<params->nrofdeviceproperties;i++)
751                         if (params->deviceproperties[i].desc.DevicePropertyCode == p)
752                                 break;
753                 if (i == params->nrofdeviceproperties) {
754                         if (!i)
755                                 params->deviceproperties = malloc(sizeof(params->deviceproperties[0]));
756                         else
757                                 params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0]));
758                         memset(&params->deviceproperties[i],0,sizeof(params->deviceproperties[0]));
759                         params->nrofdeviceproperties++;
760                 } else {
761                         ptp_free_devicepropdesc (&params->deviceproperties[i].desc);
762                 }
763                 /* FIXME: free old entry */
764                 /* we are not using dpd, so copy it directly to the cache */
765                 time( &params->deviceproperties[i].timestamp);
766                 params->deviceproperties[i].desc = dpd;
767
768                 next = xmlNextElementSibling (next);
769         }
770         return PTP_RC_OK;
771 }
772
773 static int
774 parse_9301_event_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) {
775         xmlNodePtr next;
776         int     cnt;
777
778         cnt = 0;
779         next = xmlFirstElementChild (node);
780         while (next) {
781                 cnt++;
782                 next = xmlNextElementSibling (next);
783         }
784         di->EventsSupported_len = cnt;
785         di->EventsSupported = malloc (cnt*sizeof(di->EventsSupported[0]));
786         cnt = 0;
787         next = xmlFirstElementChild (node);
788         while (next) {
789                 unsigned int p;
790
791                 sscanf((char*)next->name, "e%04x", &p);
792                 ptp_debug( params, "event %s / 0x%04x", next->name, p);
793                 di->EventsSupported[cnt++] = p;
794                 next = xmlNextElementSibling (next);
795         }
796         return PTP_RC_OK;
797 }
798
799 static int
800 parse_9301_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) {
801         xmlNodePtr      next;
802
803         next = xmlFirstElementChild (node);
804         while (next) {
805                 if (!strcmp ((char*)next->name, "cmd")) {
806                         parse_9301_cmd_tree (params, next, di);
807                         next = xmlNextElementSibling (next);
808                         continue;
809                 }
810                 if (!strcmp ((char*)next->name, "prop")) {
811                         parse_9301_prop_tree (params, next, di);
812                         next = xmlNextElementSibling (next);
813                         continue;
814                 }
815                 if (!strcmp ((char*)next->name, "event")) {
816                         parse_9301_event_tree (params, next, di);
817                         next = xmlNextElementSibling (next);
818                         continue;
819                 }
820                 fprintf (stderr,"9301: unhandled type %s\n", next->name);
821                 next = xmlNextElementSibling (next);
822         }
823         /*traverse_tree (0, node);*/
824         return PTP_RC_OK;
825 }
826
827 static uint16_t
828 ptp_olympus_parse_output_xml(PTPParams* params, char*data, int len, xmlNodePtr *code) {
829         xmlDocPtr       docin;
830         xmlNodePtr      docroot, output, next;
831         int             result, xcode;
832
833         *code = NULL;
834
835         docin = xmlReadMemory ((char*)data, len, "http://gphoto.org/", "utf-8", 0);
836         if (!docin) return PTP_RC_GeneralError;
837         docroot = xmlDocGetRootElement (docin);
838         if (!docroot) {
839                 xmlFreeDoc (docin);
840                 return PTP_RC_GeneralError;
841         }
842
843         if (strcmp((char*)docroot->name,"x3c")) {
844                 ptp_debug (params, "olympus: docroot is not x3c, but %s", docroot->name);
845                 xmlFreeDoc (docin);
846                 return PTP_RC_GeneralError;
847         }
848         if (xmlChildElementCount(docroot) != 1) {
849                 ptp_debug (params, "olympus: x3c: expected 1 child, got %ld", xmlChildElementCount(docroot));
850                 xmlFreeDoc (docin);
851                 return PTP_RC_GeneralError;
852         }
853         output = xmlFirstElementChild (docroot);
854         if (strcmp((char*)output->name, "output") != 0) {
855                 ptp_debug (params, "olympus: x3c node: expected child 'output', but got %s", (char*)output->name);
856                 xmlFreeDoc (docin);
857                 return PTP_RC_GeneralError;
858         }
859         next = xmlFirstElementChild (output);
860
861         result = PTP_RC_GeneralError;
862
863         while (next) {
864                 if (!strcmp((char*)next->name,"result")) {
865                         xmlChar  *xchar;
866
867                         xchar = xmlNodeGetContent (next);
868                         if (!sscanf((char*)xchar,"%04x",&result))
869                                 ptp_debug (params, "failed scanning result from %s", xchar);
870                         ptp_debug (params,  "ptp result is 0x%04x", result);
871                         next = xmlNextElementSibling (next);
872                         continue;
873                 }
874                 if (sscanf((char*)next->name,"c%x", &xcode)) {
875                         ptp_debug (params,  "ptp code node found %s", (char*)next->name);
876                         *code = next;
877                         next = xmlNextElementSibling (next);
878                         continue;
879                 }
880                 ptp_debug (params, "unhandled node %s", (char*)next->name);
881                 next = xmlNextElementSibling (next);
882         }
883
884         if (result != PTP_RC_OK) {
885                 *code = NULL;
886                 xmlFreeDoc (docin);
887         }
888         return result;
889 }
890 #endif
891
892 uint16_t
893 ptp_olympus_getdeviceinfo (PTPParams* params, PTPDeviceInfo *di)
894 {
895 #ifdef HAVE_LIBXML2
896         uint16_t        ret;
897         PTPContainer    ptp;
898         PTPDataHandler  handler;
899         unsigned char   *data;
900         unsigned long   len;
901         xmlNodePtr      code;
902
903         memset (di, 0, sizeof(PTPDeviceInfo));
904         ptp_init_recv_memory_handler (&handler);
905
906         PTP_CNT_INIT(ptp);
907         ptp.Code   = PTP_OC_OLYMPUS_GetDeviceInfo;
908         ptp.Nparam = 0;
909         len        = 0;
910         data       = NULL;
911         ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
912
913         ptp_exit_recv_memory_handler (&handler, &data, &len);
914
915         ret = ptp_olympus_parse_output_xml(params,(char*)data,len,&code);
916         if (ret != PTP_RC_OK)
917                 return ret;
918
919         ret = parse_9301_tree (params, code, di);
920
921         xmlFreeDoc(code->doc);
922         return ret;
923 #else
924         return PTP_RC_GeneralError;
925 #endif
926 }
927
928 uint16_t
929 ptp_olympus_opensession (PTPParams* params, unsigned char**data, unsigned long *len)
930 {
931         uint16_t        ret;
932         PTPContainer    ptp;
933         PTPDataHandler  handler;
934
935         ptp_init_recv_memory_handler (&handler);
936         PTP_CNT_INIT(ptp);
937         ptp.Code   = PTP_OC_OLYMPUS_OpenSession;
938         ptp.Nparam = 0;
939         *len       = 0;
940         *data      = NULL;
941         ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
942         ptp_exit_recv_memory_handler (&handler, data, len);
943         return ret;
944 }
945
946 uint16_t
947 ptp_olympus_getcameraid (PTPParams* params, unsigned char**data, unsigned long *len)
948 {
949         uint16_t        ret;
950         PTPContainer    ptp;
951         PTPDataHandler  handler;
952
953         ptp_init_recv_memory_handler (&handler);
954         PTP_CNT_INIT(ptp);
955         ptp.Code   = PTP_OC_OLYMPUS_GetCameraID;
956         ptp.Nparam = 0;
957         *len       = 0;
958         *data       = NULL;
959         ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
960         ptp_exit_recv_memory_handler (&handler, data, len);
961         return ret;
962 }
963
964 /**
965  * ptp_generic_no_data:
966  * params:      PTPParams*
967  *              code    PTP OP Code
968  *              n_param count of parameters
969  *              ... variable argument list ...
970  *
971  * Emits a generic PTP command without any data transfer.
972  *
973  * Return values: Some PTP_RC_* code.
974  **/
975 uint16_t
976 ptp_generic_no_data (PTPParams* params, uint16_t code, unsigned int n_param, ...)
977 {
978         PTPContainer ptp;
979         va_list args;
980         unsigned int i;
981
982         if( n_param > 5 )
983                 return PTP_RC_InvalidParameter;
984
985         PTP_CNT_INIT(ptp);
986         ptp.Code=code;
987         ptp.Nparam=n_param;
988
989         va_start(args, n_param);
990         for( i=0; i<n_param; ++i )
991                 (&ptp.Param1)[i] = va_arg(args, uint32_t);
992         va_end(args);
993
994         return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
995 }
996
997 /**
998  * ptp_opensession:
999  * params:      PTPParams*
1000  *              session                 - session number
1001  *
1002  * Establishes a new session.
1003  *
1004  * Return values: Some PTP_RC_* code.
1005  **/
1006 uint16_t
1007 ptp_opensession (PTPParams* params, uint32_t session)
1008 {
1009         uint16_t ret;
1010         PTPContainer ptp;
1011
1012         ptp_debug(params,"PTP: Opening session");
1013
1014         /* SessonID field of the operation dataset should always
1015            be set to 0 for OpenSession request! */
1016         params->session_id=0x00000000;
1017         /* TransactionID should be set to 0 also! */
1018         params->transaction_id=0x0000000;
1019         /* zero out response packet buffer */
1020         params->response_packet = NULL;
1021         params->response_packet_size = 0;
1022         /* no split headers */
1023         params->split_header_data = 0;
1024
1025         PTP_CNT_INIT(ptp);
1026         ptp.Code=PTP_OC_OpenSession;
1027         ptp.Param1=session;
1028         ptp.Nparam=1;
1029         ret=ptp_transaction_new(params, &ptp, PTP_DP_NODATA, 0, NULL);
1030         /* now set the global session id to current session number */
1031         params->session_id=session;
1032         return ret;
1033 }
1034
1035 void
1036 ptp_free_devicepropvalue(uint16_t dt, PTPPropertyValue* dpd) {
1037         switch (dt) {
1038         case PTP_DTC_INT8:      case PTP_DTC_UINT8:
1039         case PTP_DTC_UINT16:    case PTP_DTC_INT16:
1040         case PTP_DTC_UINT32:    case PTP_DTC_INT32:
1041         case PTP_DTC_UINT64:    case PTP_DTC_INT64:
1042         case PTP_DTC_UINT128:   case PTP_DTC_INT128:
1043                 /* Nothing to free */
1044                 break;
1045         case PTP_DTC_AINT8:     case PTP_DTC_AUINT8:
1046         case PTP_DTC_AUINT16:   case PTP_DTC_AINT16:
1047         case PTP_DTC_AUINT32:   case PTP_DTC_AINT32:
1048         case PTP_DTC_AUINT64:   case PTP_DTC_AINT64:
1049         case PTP_DTC_AUINT128:  case PTP_DTC_AINT128:
1050                 if (dpd->a.v)
1051                         free(dpd->a.v);
1052                 break;
1053         case PTP_DTC_STR:
1054                 if (dpd->str)
1055                         free(dpd->str);
1056                 break;
1057         }
1058 }
1059
1060 void
1061 ptp_free_devicepropdesc(PTPDevicePropDesc* dpd)
1062 {
1063         uint16_t i;
1064
1065         ptp_free_devicepropvalue (dpd->DataType, &dpd->FactoryDefaultValue);
1066         ptp_free_devicepropvalue (dpd->DataType, &dpd->CurrentValue);
1067         switch (dpd->FormFlag) {
1068         case PTP_DPFF_Range:
1069                 ptp_free_devicepropvalue (dpd->DataType, &dpd->FORM.Range.MinimumValue);
1070                 ptp_free_devicepropvalue (dpd->DataType, &dpd->FORM.Range.MaximumValue);
1071                 ptp_free_devicepropvalue (dpd->DataType, &dpd->FORM.Range.StepSize);
1072                 break;
1073         case PTP_DPFF_Enumeration:
1074                 if (dpd->FORM.Enum.SupportedValue) {
1075                         for (i=0;i<dpd->FORM.Enum.NumberOfValues;i++)
1076                                 ptp_free_devicepropvalue (dpd->DataType, dpd->FORM.Enum.SupportedValue+i);
1077                         free (dpd->FORM.Enum.SupportedValue);
1078                 }
1079         }
1080         dpd->DataType = PTP_DTC_UNDEF;
1081         dpd->FormFlag = PTP_DPFF_None;
1082 }
1083
1084
1085 void
1086 ptp_free_objectpropdesc(PTPObjectPropDesc* opd)
1087 {
1088         uint16_t i;
1089
1090         ptp_free_devicepropvalue (opd->DataType, &opd->FactoryDefaultValue);
1091         switch (opd->FormFlag) {
1092         case PTP_OPFF_None:
1093                 break;
1094         case PTP_OPFF_Range:
1095                 ptp_free_devicepropvalue (opd->DataType, &opd->FORM.Range.MinimumValue);
1096                 ptp_free_devicepropvalue (opd->DataType, &opd->FORM.Range.MaximumValue);
1097                 ptp_free_devicepropvalue (opd->DataType, &opd->FORM.Range.StepSize);
1098                 break;
1099         case PTP_OPFF_Enumeration:
1100                 if (opd->FORM.Enum.SupportedValue) {
1101                         for (i=0;i<opd->FORM.Enum.NumberOfValues;i++)
1102                                 ptp_free_devicepropvalue (opd->DataType, opd->FORM.Enum.SupportedValue+i);
1103                         free (opd->FORM.Enum.SupportedValue);
1104                 }
1105                 break;
1106         case PTP_OPFF_DateTime:
1107         case PTP_OPFF_FixedLengthArray:
1108         case PTP_OPFF_RegularExpression:
1109         case PTP_OPFF_ByteArray:
1110         case PTP_OPFF_LongString:
1111                 /* Ignore these presently, we cannot unpack them, so there is nothing to be freed. */
1112                 break;
1113         default:
1114                 fprintf (stderr, "Unknown OPFF type %d\n", opd->FormFlag);
1115                 break;
1116         }
1117 }
1118
1119
1120 /**
1121  * ptp_free_params:
1122  * params:      PTPParams*
1123  *
1124  * Frees all data within the PTPParams struct.
1125  *
1126  * Return values: Some PTP_RC_* code.
1127  **/
1128 void
1129 ptp_free_params (PTPParams *params) {
1130         unsigned int i;
1131
1132         if (params->cameraname) free (params->cameraname);
1133         if (params->wifi_profiles) free (params->wifi_profiles);
1134         for (i=0;i<params->nrofobjects;i++)
1135                 ptp_free_object (&params->objects[i]);
1136         free (params->objects);
1137         free (params->events);
1138         for (i=0;i<params->nrofcanon_props;i++) {
1139                 free (params->canon_props[i].data);
1140                 ptp_free_devicepropdesc (&params->canon_props[i].dpd);
1141         }
1142         free (params->canon_props);
1143         free (params->backlogentries);
1144
1145         for (i=0;i<params->nrofdeviceproperties;i++)
1146                 ptp_free_devicepropdesc (&params->deviceproperties[i].desc);
1147         free (params->deviceproperties);
1148
1149         ptp_free_DI (&params->deviceinfo);
1150 }
1151
1152 /**
1153  * ptp_getststorageids:
1154  * params:      PTPParams*
1155  *
1156  * Gets array of StorageIDs and fills the storageids structure.
1157  *
1158  * Return values: Some PTP_RC_* code.
1159  **/
1160 uint16_t
1161 ptp_getstorageids (PTPParams* params, PTPStorageIDs* storageids)
1162 {
1163         uint16_t ret;
1164         PTPContainer ptp;
1165         unsigned int len;
1166         unsigned char* sids=NULL;
1167
1168         PTP_CNT_INIT(ptp);
1169         ptp.Code=PTP_OC_GetStorageIDs;
1170         ptp.Nparam=0;
1171         len=0;
1172         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &sids, &len);
1173         if (ret == PTP_RC_OK) ptp_unpack_SIDs(params, sids, storageids, len);
1174         free(sids);
1175         return ret;
1176 }
1177
1178 /**
1179  * ptp_getststorageinfo:
1180  * params:      PTPParams*
1181  *              storageid               - StorageID
1182  *
1183  * Gets StorageInfo dataset of desired storage and fills storageinfo
1184  * structure.
1185  *
1186  * Return values: Some PTP_RC_* code.
1187  **/
1188 uint16_t
1189 ptp_getstorageinfo (PTPParams* params, uint32_t storageid,
1190                         PTPStorageInfo* storageinfo)
1191 {
1192         uint16_t ret;
1193         PTPContainer ptp;
1194         unsigned char* si=NULL;
1195         unsigned int len;
1196
1197         PTP_CNT_INIT(ptp);
1198         ptp.Code=PTP_OC_GetStorageInfo;
1199         ptp.Param1=storageid;
1200         ptp.Nparam=1;
1201         len=0;
1202         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &si, &len);
1203         if (ret == PTP_RC_OK) ptp_unpack_SI(params, si, storageinfo, len);
1204         free(si);
1205         return ret;
1206 }
1207
1208 /**
1209  * ptp_getobjecthandles:
1210  * params:      PTPParams*
1211  *              storage                 - StorageID
1212  *              objectformatcode        - ObjectFormatCode (optional)
1213  *              associationOH           - ObjectHandle of Association for
1214  *                                        wich a list of children is desired
1215  *                                        (optional)
1216  *              objecthandles           - pointer to structute
1217  *
1218  * Fills objecthandles with structure returned by device.
1219  *
1220  * Return values: Some PTP_RC_* code.
1221  **/
1222 uint16_t
1223 ptp_getobjecthandles (PTPParams* params, uint32_t storage,
1224                         uint32_t objectformatcode, uint32_t associationOH,
1225                         PTPObjectHandles* objecthandles)
1226 {
1227         uint16_t ret;
1228         PTPContainer ptp;
1229         unsigned char* oh=NULL;
1230         unsigned int len;
1231
1232         PTP_CNT_INIT(ptp);
1233         ptp.Code=PTP_OC_GetObjectHandles;
1234         ptp.Param1=storage;
1235         ptp.Param2=objectformatcode;
1236         ptp.Param3=associationOH;
1237         ptp.Nparam=3;
1238         len=0;
1239         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oh, &len);
1240         if (ret == PTP_RC_OK) {
1241                 ptp_unpack_OH(params, oh, objecthandles, len);
1242         } else {
1243                 if (    (storage == 0xffffffff) &&
1244 #if 1//defined TIZEN_EXT
1245                         (associationOH == 0xffffffff)
1246 #else /* TIZEN_EXT */
1247                         (objectformatcode == 0) &&
1248                         (associationOH == 0)
1249 #endif /* TIZEN_EXT */
1250                 ) {
1251                         /* When we query all object handles on all stores and
1252                          * get an error -> just handle it as "0 handles".
1253                          */
1254                         objecthandles->Handler = NULL;
1255                         objecthandles->n = 0;
1256                         ret = PTP_RC_OK;
1257                 }
1258         }
1259         free(oh);
1260         return ret;
1261 }
1262
1263 uint16_t
1264 ptp_getfilesystemmanifest (PTPParams* params, uint32_t storage,
1265                         uint32_t objectformatcode, uint32_t associationOH,
1266                         unsigned char** data)
1267 {
1268         uint16_t ret;
1269         PTPContainer ptp;
1270         unsigned int len;
1271
1272         PTP_CNT_INIT(ptp);
1273         ptp.Code=PTP_OC_GetFilesystemManifest;
1274         ptp.Param1=storage;
1275         ptp.Param2=objectformatcode;
1276         ptp.Param3=associationOH;
1277         ptp.Nparam=3;
1278         len=0;
1279         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, &len);
1280         return ret;
1281 }
1282
1283 /**
1284  * ptp_getnumobjects:
1285  * params:      PTPParams*
1286  *              storage                 - StorageID
1287  *              objectformatcode        - ObjectFormatCode (optional)
1288  *              associationOH           - ObjectHandle of Association for
1289  *                                        wich a list of children is desired
1290  *                                        (optional)
1291  *              numobs                  - pointer to uint32_t that takes number of objects
1292  *
1293  * Fills numobs with number of objects on device.
1294  *
1295  * Return values: Some PTP_RC_* code.
1296  **/
1297 uint16_t
1298 ptp_getnumobjects (PTPParams* params, uint32_t storage,
1299                         uint32_t objectformatcode, uint32_t associationOH,
1300                         uint32_t* numobs)
1301 {
1302         uint16_t ret;
1303         PTPContainer ptp;
1304
1305         PTP_CNT_INIT(ptp);
1306         ptp.Code=PTP_OC_GetNumObjects;
1307         ptp.Param1=storage;
1308         ptp.Param2=objectformatcode;
1309         ptp.Param3=associationOH;
1310         ptp.Nparam=3;
1311         ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
1312         if (ret == PTP_RC_OK) {
1313                 if (ptp.Nparam >= 1)
1314                         *numobs = ptp.Param1;
1315                 else
1316                         ret = PTP_RC_GeneralError;
1317         }
1318         return ret;
1319 }
1320
1321 /**
1322  * ptp_eos_bulbstart:
1323  * params:      PTPParams*
1324  *
1325  * Starts EOS Bulb capture.
1326  *
1327  * Return values: Some PTP_RC_* code.
1328  **/
1329 uint16_t
1330 ptp_canon_eos_bulbstart (PTPParams* params)
1331 {
1332         uint16_t ret;
1333         PTPContainer ptp;
1334
1335         PTP_CNT_INIT(ptp);
1336         ptp.Code   = PTP_OC_CANON_EOS_BulbStart;
1337         ptp.Nparam = 0;
1338         ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
1339         if ((ret == PTP_RC_OK) && (ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000))
1340                 ret = ptp.Param1;
1341         return ret;
1342 }
1343
1344 /**
1345  * ptp_eos_capture:
1346  * params:      PTPParams*
1347  *              uint32_t*       result
1348  *
1349  * This starts a EOS400D style capture. You have to use the
1350  * get_eos_events to find out what resulted.
1351  * The return value is "0" for all OK, and "1" for capture failed. (not fully confirmed)
1352  *
1353  * Return values: Some PTP_RC_* code.
1354  **/
1355 uint16_t
1356 ptp_canon_eos_capture (PTPParams* params, uint32_t *result)
1357 {
1358         uint16_t ret;
1359         PTPContainer ptp;
1360
1361         PTP_CNT_INIT(ptp);
1362         ptp.Code   = PTP_OC_CANON_EOS_RemoteRelease;
1363         ptp.Nparam = 0;
1364         *result = 0;
1365         ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
1366         if ((ret == PTP_RC_OK) && (ptp.Nparam >= 1))
1367                 *result = ptp.Param1;
1368         return ret;
1369 }
1370
1371 /**
1372  * ptp_canon_eos_bulbend:
1373  * params:      PTPParams*
1374  *
1375  * Starts EOS Bulb capture.
1376  *
1377  * Return values: Some PTP_RC_* code.
1378  **/
1379 uint16_t
1380 ptp_canon_eos_bulbend (PTPParams* params)
1381 {
1382         uint16_t ret;
1383         PTPContainer ptp;
1384
1385         PTP_CNT_INIT(ptp);
1386         ptp.Code   = PTP_OC_CANON_EOS_BulbEnd;
1387         ptp.Nparam = 0;
1388         ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
1389         if ((ret == PTP_RC_OK) && (ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000))
1390                 ret = ptp.Param1;
1391         return ret;
1392 }
1393
1394 /**
1395  * ptp_getobjectinfo:
1396  * params:      PTPParams*
1397  *              handle                  - Object handle
1398  *              objectinfo              - pointer to objectinfo that is returned
1399  *
1400  * Get objectinfo structure for handle from device.
1401  *
1402  * Return values: Some PTP_RC_* code.
1403  **/
1404 uint16_t
1405 ptp_getobjectinfo (PTPParams* params, uint32_t handle,
1406                         PTPObjectInfo* objectinfo)
1407 {
1408         uint16_t ret;
1409         PTPContainer ptp;
1410         unsigned char* oi=NULL;
1411         unsigned int len;
1412
1413         PTP_CNT_INIT(ptp);
1414         ptp.Code=PTP_OC_GetObjectInfo;
1415         ptp.Param1=handle;
1416         ptp.Nparam=1;
1417         len=0;
1418         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oi, &len);
1419         if (ret == PTP_RC_OK) ptp_unpack_OI(params, oi, objectinfo, len);
1420         free(oi);
1421         return ret;
1422 }
1423
1424 /**
1425  * ptp_getobject:
1426  * params:      PTPParams*
1427  *              handle                  - Object handle
1428  *              object                  - pointer to data area
1429  *
1430  * Get object 'handle' from device and store the data in newly
1431  * allocated 'object'.
1432  *
1433  * Return values: Some PTP_RC_* code.
1434  **/
1435 uint16_t
1436 ptp_getobject (PTPParams* params, uint32_t handle, unsigned char** object)
1437 {
1438         PTPContainer ptp;
1439         unsigned int len;
1440
1441         PTP_CNT_INIT(ptp);
1442         ptp.Code=PTP_OC_GetObject;
1443         ptp.Param1=handle;
1444         ptp.Nparam=1;
1445         len=0;
1446         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, &len);
1447 }
1448
1449 /**
1450  * ptp_getobject_to_handler:
1451  * params:      PTPParams*
1452  *              handle                  - Object handle
1453  *              PTPDataHandler*         - pointer datahandler
1454  *
1455  * Get object 'handle' from device and store the data in newly
1456  * allocated 'object'.
1457  *
1458  * Return values: Some PTP_RC_* code.
1459  **/
1460 uint16_t
1461 ptp_getobject_to_handler (PTPParams* params, uint32_t handle, PTPDataHandler *handler)
1462 {
1463         PTPContainer ptp;
1464
1465         PTP_CNT_INIT(ptp);
1466         ptp.Code=PTP_OC_GetObject;
1467         ptp.Param1=handle;
1468         ptp.Nparam=1;
1469         return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler);
1470 }
1471
1472 /**
1473  * ptp_getobject_tofd:
1474  * params:      PTPParams*
1475  *              handle                  - Object handle
1476  *              fd                      - File descriptor to write() to
1477  *
1478  * Get object 'handle' from device and write the data to the
1479  * given file descriptor.
1480  *
1481  * Return values: Some PTP_RC_* code.
1482  **/
1483 uint16_t
1484 ptp_getobject_tofd (PTPParams* params, uint32_t handle, int fd)
1485 {
1486         PTPContainer    ptp;
1487         PTPDataHandler  handler;
1488         uint16_t        ret;
1489
1490         ptp_init_fd_handler (&handler, fd);
1491         PTP_CNT_INIT(ptp);
1492         ptp.Code=PTP_OC_GetObject;
1493         ptp.Param1=handle;
1494         ptp.Nparam=1;
1495         ret = ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
1496         ptp_exit_fd_handler (&handler);
1497         return ret;
1498 }
1499
1500 /**
1501  * ptp_getpartialobject:
1502  * params:      PTPParams*
1503  *              handle                  - Object handle
1504  *              offset                  - Offset into object
1505  *              maxbytes                - Maximum of bytes to read
1506  *              object                  - pointer to data area
1507  *              len                     - pointer to returned length
1508  *
1509  * Get object 'handle' from device and store the data in newly
1510  * allocated 'object'. Start from offset and read at most maxbytes.
1511  *
1512  * Return values: Some PTP_RC_* code.
1513  **/
1514 uint16_t
1515 ptp_getpartialobject (PTPParams* params, uint32_t handle, uint32_t offset,
1516                         uint32_t maxbytes, unsigned char** object,
1517                         uint32_t *len)
1518 {
1519         PTPContainer ptp;
1520
1521         PTP_CNT_INIT(ptp);
1522         ptp.Code=PTP_OC_GetPartialObject;
1523         ptp.Param1=handle;
1524         ptp.Param2=offset;
1525         ptp.Param3=maxbytes;
1526         ptp.Nparam=3;
1527         *len=0;
1528         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len);
1529 }
1530
1531 /**
1532  * ptp_getthumb:
1533  * params:      PTPParams*
1534  *              handle                  - Object handle
1535  *              object                  - pointer to data area
1536  *
1537  * Get thumb for object 'handle' from device and store the data in newly
1538  * allocated 'object'.
1539  *
1540  * Return values: Some PTP_RC_* code.
1541  **/
1542 uint16_t
1543 ptp_getthumb (PTPParams* params, uint32_t handle, unsigned char** object, unsigned int *len)
1544 {
1545         PTPContainer ptp;
1546
1547         PTP_CNT_INIT(ptp);
1548         ptp.Code=PTP_OC_GetThumb;
1549         ptp.Param1=handle;
1550         ptp.Nparam=1;
1551         *len = 0;
1552         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len);
1553 }
1554
1555 /**
1556  * ptp_deleteobject:
1557  * params:      PTPParams*
1558  *              handle                  - object handle
1559  *              ofc                     - object format code (optional)
1560  *
1561  * Deletes desired objects.
1562  *
1563  * Return values: Some PTP_RC_* code.
1564  **/
1565 uint16_t
1566 ptp_deleteobject (PTPParams* params, uint32_t handle, uint32_t ofc)
1567 {
1568         PTPContainer ptp;
1569         uint16_t ret;
1570
1571         PTP_CNT_INIT(ptp);
1572         ptp.Code=PTP_OC_DeleteObject;
1573         ptp.Param1=handle;
1574         ptp.Param2=ofc;
1575         ptp.Nparam=2;
1576         ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
1577         if (ret != PTP_RC_OK) {
1578                 return ret;
1579         }
1580         /* If the object is cached and could be removed, cleanse cache. */
1581         ptp_remove_object_from_cache(params, handle);
1582         return PTP_RC_OK;
1583 }
1584
1585 /**
1586  * ptp_sendobjectinfo:
1587  * params:      PTPParams*
1588  *              uint32_t* store         - destination StorageID on Responder
1589  *              uint32_t* parenthandle  - Parent ObjectHandle on responder
1590  *              uint32_t* handle        - see Return values
1591  *              PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
1592  *
1593  * Sends ObjectInfo of file that is to be sent via SendFileObject.
1594  *
1595  * Return values: Some PTP_RC_* code.
1596  * Upon success : uint32_t* store       - Responder StorageID in which
1597  *                                        object will be stored
1598  *                uint32_t* parenthandle- Responder Parent ObjectHandle
1599  *                                        in which the object will be stored
1600  *                uint32_t* handle      - Responder's reserved ObjectHandle
1601  *                                        for the incoming object
1602  **/
1603 uint16_t
1604 ptp_sendobjectinfo (PTPParams* params, uint32_t* store,
1605                         uint32_t* parenthandle, uint32_t* handle,
1606                         PTPObjectInfo* objectinfo)
1607 {
1608         uint16_t ret;
1609         PTPContainer ptp;
1610         unsigned char* oidata=NULL;
1611         uint32_t size;
1612
1613         PTP_CNT_INIT(ptp);
1614         ptp.Code=PTP_OC_SendObjectInfo;
1615         ptp.Param1=*store;
1616         ptp.Param2=*parenthandle;
1617         ptp.Nparam=2;
1618
1619         size=ptp_pack_OI(params, objectinfo, &oidata);
1620         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata, NULL);
1621         free(oidata);
1622         *store=ptp.Param1;
1623         *parenthandle=ptp.Param2;
1624         *handle=ptp.Param3;
1625         return ret;
1626 }
1627
1628 /**
1629  * ptp_sendobject:
1630  * params:      PTPParams*
1631  *              char*   object          - contains the object that is to be sent
1632  *              uint64_t size           - object size
1633  *
1634  * Sends object to Responder.
1635  *
1636  * Return values: Some PTP_RC_* code.
1637  *
1638  */
1639 uint16_t
1640 ptp_sendobject (PTPParams* params, unsigned char* object, uint64_t size)
1641 {
1642         PTPContainer ptp;
1643
1644         PTP_CNT_INIT(ptp);
1645         ptp.Code=PTP_OC_SendObject;
1646         ptp.Nparam=0;
1647
1648         return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object, NULL);
1649 }
1650
1651 /**
1652  * ptp_sendobject_from_handler:
1653  * params:      PTPParams*
1654  *              PTPDataHandler*         - File descriptor to read() object from
1655  *              uint64_t size           - File/object size
1656  *
1657  * Sends object from file descriptor by consecutive reads from this
1658  * descriptor.
1659  *
1660  * Return values: Some PTP_RC_* code.
1661  **/
1662 uint16_t
1663 ptp_sendobject_from_handler (PTPParams* params, PTPDataHandler *handler, uint64_t size)
1664 {
1665         PTPContainer    ptp;
1666
1667         PTP_CNT_INIT(ptp);
1668         ptp.Code=PTP_OC_SendObject;
1669         ptp.Nparam=0;
1670         return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler);
1671 }
1672
1673
1674 /**
1675  * ptp_sendobject_fromfd:
1676  * params:      PTPParams*
1677  *              fd                      - File descriptor to read() object from
1678  *              uint64_t size           - File/object size
1679  *
1680  * Sends object from file descriptor by consecutive reads from this
1681  * descriptor.
1682  *
1683  * Return values: Some PTP_RC_* code.
1684  **/
1685 uint16_t
1686 ptp_sendobject_fromfd (PTPParams* params, int fd, uint64_t size)
1687 {
1688         PTPContainer    ptp;
1689         PTPDataHandler  handler;
1690         uint16_t        ret;
1691
1692         ptp_init_fd_handler (&handler, fd);
1693         PTP_CNT_INIT(ptp);
1694         ptp.Code=PTP_OC_SendObject;
1695         ptp.Nparam=0;
1696         ret = ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, &handler);
1697         ptp_exit_fd_handler (&handler);
1698         return ret;
1699 }
1700
1701 #define PROPCACHE_TIMEOUT 5     /* seconds */
1702
1703 uint16_t
1704 ptp_getdevicepropdesc (PTPParams* params, uint16_t propcode,
1705                         PTPDevicePropDesc* devicepropertydesc)
1706 {
1707         PTPContainer ptp;
1708         uint16_t ret;
1709         unsigned int len;
1710         unsigned char* dpd=NULL;
1711
1712
1713         PTP_CNT_INIT(ptp);
1714         ptp.Code   = PTP_OC_GetDevicePropDesc;
1715         ptp.Param1 = propcode;
1716         ptp.Nparam = 1;
1717         len        = 0;
1718         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpd, &len);
1719
1720         if (ret == PTP_RC_OK) {
1721                 if (params->device_flags & DEVICE_FLAG_OLYMPUS_XML_WRAPPED) {
1722 #ifdef HAVE_LIBXML2
1723                         xmlNodePtr      code;
1724
1725                         ret = ptp_olympus_parse_output_xml (params,(char*)dpd,len,&code);
1726                         if (ret == PTP_RC_OK) {
1727                                 int x;
1728
1729                                 if (    (xmlChildElementCount(code) == 1) &&
1730                                         (!strcmp((char*)code->name,"c1014"))
1731                                 ) {
1732                                         code = xmlFirstElementChild (code);
1733
1734                                         if (    (sscanf((char*)code->name,"p%x", &x)) &&
1735                                                 (x == propcode)
1736                                         ) {
1737                                                 ret = parse_9301_propdesc (params, xmlFirstElementChild (code), devicepropertydesc);
1738                                                 xmlFreeDoc(code->doc);
1739                                         }
1740                                 }
1741                         } else {
1742                                 ptp_debug(params,"failed to parse output xml, ret %x?", ret);
1743                         }
1744 #endif
1745                 } else {
1746                         ptp_unpack_DPD(params, dpd, devicepropertydesc, len);
1747                 }
1748         }
1749         free(dpd);
1750         return ret;
1751 }
1752
1753
1754 uint16_t
1755 ptp_getdevicepropvalue (PTPParams* params, uint16_t propcode,
1756                         PTPPropertyValue* value, uint16_t datatype)
1757 {
1758         PTPContainer ptp;
1759         uint16_t ret;
1760         unsigned int len, offset;
1761         unsigned char* dpv=NULL;
1762
1763
1764         PTP_CNT_INIT(ptp);
1765         ptp.Code=PTP_OC_GetDevicePropValue;
1766         ptp.Param1=propcode;
1767         ptp.Nparam=1;
1768         len=offset=0;
1769         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpv, &len);
1770         if (ret == PTP_RC_OK) {
1771                 int ret2 = ptp_unpack_DPV(params, dpv, &offset, len, value, datatype);
1772                 if (!ret2) {
1773                         ptp_debug (params, "ptp_getdevicepropvalue: unpacking DPV failed");
1774                         ret = PTP_RC_GeneralError;
1775                 }
1776         }
1777         free(dpv);
1778         return ret;
1779 }
1780
1781 uint16_t
1782 ptp_setdevicepropvalue (PTPParams* params, uint16_t propcode,
1783                         PTPPropertyValue *value, uint16_t datatype)
1784 {
1785         PTPContainer ptp;
1786         uint16_t ret;
1787         uint32_t size;
1788         unsigned char* dpv=NULL;
1789
1790         PTP_CNT_INIT(ptp);
1791         ptp.Code=PTP_OC_SetDevicePropValue;
1792         ptp.Param1=propcode;
1793         ptp.Nparam=1;
1794         size=ptp_pack_DPV(params, value, &dpv, datatype);
1795         ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &dpv, NULL);
1796         free(dpv);
1797         return ret;
1798 }
1799
1800 /**
1801  * ptp_ek_sendfileobjectinfo:
1802  * params:      PTPParams*
1803  *              uint32_t* store         - destination StorageID on Responder
1804  *              uint32_t* parenthandle  - Parent ObjectHandle on responder
1805  *              uint32_t* handle        - see Return values
1806  *              PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
1807  *
1808  * Sends ObjectInfo of file that is to be sent via SendFileObject.
1809  *
1810  * Return values: Some PTP_RC_* code.
1811  * Upon success : uint32_t* store       - Responder StorageID in which
1812  *                                        object will be stored
1813  *                uint32_t* parenthandle- Responder Parent ObjectHandle
1814  *                                        in which the object will be stored
1815  *                uint32_t* handle      - Responder's reserved ObjectHandle
1816  *                                        for the incoming object
1817  **/
1818 uint16_t
1819 ptp_ek_sendfileobjectinfo (PTPParams* params, uint32_t* store,
1820                         uint32_t* parenthandle, uint32_t* handle,
1821                         PTPObjectInfo* objectinfo)
1822 {
1823         uint16_t ret;
1824         PTPContainer ptp;
1825         unsigned char* oidata=NULL;
1826         uint32_t size;
1827
1828         PTP_CNT_INIT(ptp);
1829         ptp.Code=PTP_OC_EK_SendFileObjectInfo;
1830         ptp.Param1=*store;
1831         ptp.Param2=*parenthandle;
1832         ptp.Nparam=2;
1833
1834         size=ptp_pack_OI(params, objectinfo, &oidata);
1835         ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata, NULL);
1836         free(oidata);
1837         *store=ptp.Param1;
1838         *parenthandle=ptp.Param2;
1839         *handle=ptp.Param3;
1840         return ret;
1841 }
1842
1843 /**
1844  * ptp_ek_getserial:
1845  * params:      PTPParams*
1846  *              char**  serial          - contains the serial number of the camera
1847  *              uint32_t* size          - contains the string length
1848  *
1849  * Gets the serial number from the device. (ptp serial)
1850  *
1851  * Return values: Some PTP_RC_* code.
1852  *
1853  */
1854 uint16_t
1855 ptp_ek_getserial (PTPParams* params, unsigned char **data, unsigned int *size)
1856 {
1857         PTPContainer ptp;
1858
1859         PTP_CNT_INIT(ptp);
1860         ptp.Code   = PTP_OC_EK_GetSerial;
1861         ptp.Nparam = 0;
1862         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
1863 }
1864
1865 /**
1866  * ptp_ek_setserial:
1867  * params:      PTPParams*
1868  *              char*   serial          - contains the new serial number
1869  *              uint32_t size           - string length
1870  *
1871  * Sets the serial number of the device. (ptp serial)
1872  *
1873  * Return values: Some PTP_RC_* code.
1874  *
1875  */
1876 uint16_t
1877 ptp_ek_setserial (PTPParams* params, unsigned char *data, unsigned int size)
1878 {
1879         PTPContainer ptp;
1880
1881         PTP_CNT_INIT(ptp);
1882         ptp.Code   = PTP_OC_EK_SetSerial;
1883         ptp.Nparam = 0;
1884         return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
1885 }
1886
1887 /* unclear what it does yet */
1888 uint16_t
1889 ptp_ek_9007 (PTPParams* params, unsigned char **data, unsigned int *size)
1890 {
1891         PTPContainer ptp;
1892
1893         PTP_CNT_INIT(ptp);
1894         ptp.Code   = 0x9007;
1895         ptp.Nparam = 0;
1896         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
1897 }
1898
1899 /* unclear what it does yet */
1900 uint16_t
1901 ptp_ek_9009 (PTPParams* params, uint32_t *p1, uint32_t *p2)
1902 {
1903         PTPContainer    ptp;
1904         uint16_t        ret;
1905
1906         PTP_CNT_INIT(ptp);
1907         ptp.Code   = 0x9009;
1908         ptp.Nparam = 0;
1909         ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
1910         *p1 = ptp.Param1;
1911         *p2 = ptp.Param2;
1912         return ret;
1913 }
1914
1915 /* unclear yet, but I guess it returns the info from 9008 */
1916 uint16_t
1917 ptp_ek_900c (PTPParams* params, unsigned char **data, unsigned int *size)
1918 {
1919         PTPContainer ptp;
1920
1921         PTP_CNT_INIT(ptp);
1922         ptp.Code   = 0x900c;
1923         ptp.Nparam = 0;
1924         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
1925         /* returned data is 16bit,16bit,32bit,32bit */
1926 }
1927
1928 /**
1929  * ptp_ek_settext:
1930  * params:      PTPParams*
1931  *              PTPEKTextParams*        - contains the texts to display.
1932  *
1933  * Displays the specified texts on the TFT of the camera.
1934  *
1935  * Return values: Some PTP_RC_* code.
1936  *
1937  */
1938 uint16_t
1939 ptp_ek_settext (PTPParams* params, PTPEKTextParams *text)
1940 {
1941         PTPContainer ptp;
1942         uint16_t ret;
1943         unsigned int size;
1944         unsigned char *data;
1945
1946         PTP_CNT_INIT(ptp);
1947         ptp.Code   = PTP_OC_EK_SetText;
1948         ptp.Nparam = 0;
1949         if (0 == (size = ptp_pack_EK_text(params, text, &data)))
1950                 return PTP_ERROR_BADPARAM;
1951         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
1952         free(data);
1953         return ret;
1954 }
1955
1956 /**
1957  * ptp_ek_sendfileobject:
1958  * params:      PTPParams*
1959  *              char*   object          - contains the object that is to be sent
1960  *              uint32_t size           - object size
1961  *
1962  * Sends object to Responder.
1963  *
1964  * Return values: Some PTP_RC_* code.
1965  *
1966  */
1967 uint16_t
1968 ptp_ek_sendfileobject (PTPParams* params, unsigned char* object, uint32_t size)
1969 {
1970         PTPContainer ptp;
1971
1972         PTP_CNT_INIT(ptp);
1973         ptp.Code=PTP_OC_EK_SendFileObject;
1974         ptp.Nparam=0;
1975
1976         return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object, NULL);
1977 }
1978
1979 /**
1980  * ptp_ek_sendfileobject_from_handler:
1981  * params:      PTPParams*
1982  *              PTPDataHandler* handler - contains the handler of the object that is to be sent
1983  *              uint32_t size           - object size
1984  *
1985  * Sends object to Responder.
1986  *
1987  * Return values: Some PTP_RC_* code.
1988  *
1989  */
1990 uint16_t
1991 ptp_ek_sendfileobject_from_handler (PTPParams* params, PTPDataHandler*handler, uint32_t size)
1992 {
1993         PTPContainer ptp;
1994
1995         PTP_CNT_INIT(ptp);
1996         ptp.Code=PTP_OC_EK_SendFileObject;
1997         ptp.Nparam=0;
1998         return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler);
1999 }
2000
2001 /*************************************************************************
2002  *
2003  * Canon PTP extensions support
2004  *
2005  * (C) Nikolai Kopanygin 2003
2006  *
2007  *************************************************************************/
2008
2009
2010 /**
2011  * ptp_canon_getpartialobjectinfo:
2012  * params:      PTPParams*
2013  *              uint32_t handle         - ObjectHandle
2014  *              uint32_t p2             - Not fully understood parameter
2015  *                                        0 - returns full size
2016  *                                        1 - returns thumbnail size (or EXIF?)
2017  *
2018  * Gets form the responder the size of the specified object.
2019  *
2020  * Return values: Some PTP_RC_* code.
2021  * Upon success : uint32_t* size        - The object size
2022  *                uint32_t* rp2         - Still unknown return parameter
2023  *                                        (perhaps upper 32bit of size)
2024  *
2025  *
2026  **/
2027 uint16_t
2028 ptp_canon_getpartialobjectinfo (PTPParams* params, uint32_t handle, uint32_t p2,
2029                         uint32_t* size, uint32_t* rp2)
2030 {
2031         uint16_t ret;
2032         PTPContainer ptp;
2033
2034         PTP_CNT_INIT(ptp);
2035         ptp.Code=PTP_OC_CANON_GetPartialObjectInfo;
2036         ptp.Param1=handle;
2037         ptp.Param2=p2;
2038         ptp.Nparam=2;
2039         ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
2040         *size=ptp.Param1;
2041         *rp2=ptp.Param2;
2042         return ret;
2043 }
2044
2045 /**
2046  * ptp_canon_get_mac_address:
2047  * params:      PTPParams*
2048  *                                        value 0 works.
2049  * Gets the MAC address of the wireless transmitter.
2050  *
2051  * Return values: Some PTP_RC_* code.
2052  * Upon success : unsigned char* mac    - The MAC address
2053  *
2054  **/
2055 uint16_t
2056 ptp_canon_get_mac_address (PTPParams* params, unsigned char **mac)
2057 {
2058         PTPContainer ptp;
2059         unsigned int size = 0;
2060
2061         PTP_CNT_INIT(ptp);
2062         ptp.Code=PTP_OC_CANON_GetMACAddress;
2063         ptp.Nparam=0;
2064         *mac = NULL;
2065         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, mac, &size);
2066 }
2067
2068 /**
2069  * ptp_canon_get_directory:
2070  * params:      PTPParams*
2071
2072  * Gets the full directory of the camera.
2073  *
2074  * Return values: Some PTP_RC_* code.
2075  * Upon success : PTPObjectHandles        *handles      - filled out with handles
2076  *                PTPObjectInfo           **oinfos      - allocated array of PTP Object Infos
2077  *                uint32_t                **flags       - allocated array of CANON Flags
2078  *
2079  **/
2080 uint16_t
2081 ptp_canon_get_directory (PTPParams* params,
2082         PTPObjectHandles        *handles,
2083         PTPObjectInfo           **oinfos,       /* size(handles->n) */
2084         uint32_t                **flags         /* size(handles->n) */
2085 ) {
2086         PTPContainer    ptp;
2087         unsigned char   *dir = NULL;
2088         unsigned int    size = 0;
2089         uint16_t        ret;
2090
2091         PTP_CNT_INIT(ptp);
2092         ptp.Code=PTP_OC_CANON_GetDirectory;
2093         ptp.Nparam=0;
2094         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dir, &size);
2095         if (ret != PTP_RC_OK)
2096                 return ret;
2097         ret = ptp_unpack_canon_directory(params, dir, ptp.Param1, handles, oinfos, flags);
2098         free (dir);
2099         return ret;
2100 }
2101
2102 /**
2103  * ptp_canon_gettreeinfo:
2104  * params:      PTPParams*
2105  *              uint32_t *out
2106  *
2107  * Switches the camera display to on and lets the user
2108  * select what to transfer. Sends a 0xc011 event when started
2109  * and 0xc013 if direct transfer aborted.
2110  *
2111  * Return values: Some PTP_RC_* code.
2112  *
2113  **/
2114 uint16_t
2115 ptp_canon_gettreeinfo (PTPParams* params, uint32_t *out)
2116 {
2117         PTPContainer ptp;
2118         uint16_t ret;
2119
2120         PTP_CNT_INIT(ptp);
2121         ptp.Code   = PTP_OC_CANON_GetTreeInfo;
2122         ptp.Nparam = 1;
2123         ptp.Param1 = 0xf;
2124         ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
2125         if ((ret == PTP_RC_OK) && (ptp.Nparam>0))
2126                 *out = ptp.Param1;
2127         return ret;
2128 }
2129
2130 /**
2131  * ptp_canon_getpairinginfo:
2132  * params:      PTPParams*
2133  *              int nr
2134  *
2135  * Get the pairing information.
2136  *
2137  * Return values: Some PTP_RC_* code.
2138  *
2139  **/
2140 uint16_t
2141 ptp_canon_getpairinginfo (PTPParams* params, uint32_t nr, unsigned char **data, unsigned int *size)
2142 {
2143         PTPContainer ptp;
2144         uint16_t ret;
2145
2146         PTP_CNT_INIT(ptp);
2147         ptp.Code   = PTP_OC_CANON_GetPairingInfo;
2148         ptp.Nparam = 1;
2149         ptp.Param1 = nr;
2150         *data = NULL;
2151         *size = 0;
2152         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2153         if (ret != PTP_RC_OK)
2154                 return ret;
2155         return PTP_RC_OK;
2156 }
2157
2158 /**
2159  * ptp_canon_get_target_handles:
2160  * params:      PTPParams*
2161  *              PTPCanon_directtransfer_entry **out
2162  *              unsigned int *outsize
2163  *
2164  * Retrieves direct transfer entries specifying the images to transfer
2165  * from the camera (to be retrieved after 0xc011 event).
2166  *
2167  * Return values: Some PTP_RC_* code.
2168  *
2169  **/
2170 uint16_t
2171 ptp_canon_gettreesize (PTPParams* params,
2172         PTPCanon_directtransfer_entry **entries, unsigned int *cnt)
2173 {
2174         PTPContainer ptp;
2175         uint16_t ret;
2176         unsigned char *out = NULL, *cur;
2177         unsigned int i, size;
2178
2179         PTP_CNT_INIT(ptp);
2180         ptp.Code   = PTP_OC_CANON_GetTreeSize;
2181         ptp.Nparam = 0;
2182         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &out, &size);
2183         if (ret != PTP_RC_OK)
2184                 return ret;
2185         *cnt = dtoh32a(out);
2186         *entries = malloc(sizeof(PTPCanon_directtransfer_entry)*(*cnt));
2187         if (!*entries) {
2188                 free (out);
2189                 return PTP_RC_GeneralError;
2190         }
2191         cur = out+4;
2192         for (i=0;i<*cnt;i++) {
2193                 unsigned char len;
2194                 (*entries)[i].oid = dtoh32a(cur);
2195                 (*entries)[i].str = ptp_unpack_string(params, cur, 4, &len);
2196                 cur += 4+(cur[4]*2+1);
2197         }
2198         free (out);
2199         return PTP_RC_OK;
2200 }
2201
2202 /**
2203  * ptp_canon_checkevent:
2204  * params:      PTPParams*
2205  *
2206  * The camera has a FIFO stack, in which it accumulates events.
2207  * Partially these events are communicated also via the USB interrupt pipe
2208  * according to the PTP USB specification, partially not.
2209  * This operation returns from the device a block of data, empty,
2210  * if the event stack is empty, or filled with an event's data otherwise.
2211  * The event is removed from the stack in the latter case.
2212  * The Remote Capture app sends this command to the camera all the time
2213  * of connection, filling with it the gaps between other operations.
2214  *
2215  * Return values: Some PTP_RC_* code.
2216  * Upon success : PTPUSBEventContainer* event   - is filled with the event data
2217  *                                                if any
2218  *                int *isevent                  - returns 1 in case of event
2219  *                                                or 0 otherwise
2220  **/
2221 uint16_t
2222 ptp_canon_checkevent (PTPParams* params, PTPContainer* event, int* isevent)
2223 {
2224         uint16_t ret;
2225         PTPContainer ptp;
2226         unsigned char *evdata = NULL;
2227         unsigned int len;
2228
2229         *isevent=0;
2230         PTP_CNT_INIT(ptp);
2231         ptp.Code=PTP_OC_CANON_CheckEvent;
2232         ptp.Nparam=0;
2233         len=0;
2234         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &evdata, &len);
2235         if (evdata!=NULL) {
2236                 if (ret == PTP_RC_OK) {
2237                         ptp_unpack_EC(params, evdata, event, len);
2238                         *isevent=1;
2239                 }
2240                 free(evdata);
2241         }
2242         return ret;
2243 }
2244
2245 uint16_t
2246 ptp_add_event (PTPParams *params, PTPContainer *evt) {
2247         if (params->nrofevents)
2248                 params->events = realloc(params->events, sizeof(PTPContainer)*(params->nrofevents+1));
2249         else
2250                 params->events = malloc(sizeof(PTPContainer)*1);
2251         memcpy (&params->events[params->nrofevents],evt,1*sizeof(PTPContainer));
2252         params->nrofevents += 1;
2253         return PTP_RC_OK;
2254 }
2255
2256 uint16_t
2257 ptp_check_event (PTPParams *params) {
2258         PTPContainer            event;
2259         uint16_t                ret;
2260
2261         if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_NIKON) &&
2262                 ptp_operation_issupported(params, PTP_OC_NIKON_CheckEvent)
2263         ) {
2264                 unsigned int evtcnt;
2265                 PTPContainer    *xevent = NULL;
2266
2267                 ret = ptp_nikon_check_event(params, &xevent, &evtcnt);
2268                 if (ret != PTP_RC_OK)
2269                         return ret;
2270
2271                 if (evtcnt) {
2272                         if (params->nrofevents)
2273                                 params->events = realloc(params->events, sizeof(PTPContainer)*(evtcnt+params->nrofevents));
2274                         else
2275                                 params->events = malloc(sizeof(PTPContainer)*evtcnt);
2276                         memcpy (&params->events[params->nrofevents],xevent,evtcnt*sizeof(PTPContainer));
2277                         params->nrofevents += evtcnt;
2278                         free (xevent);
2279                 }
2280                 return PTP_RC_OK;
2281         }
2282         /* should not get here ... EOS has no normal PTP events and another queue handling. */
2283         if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) &&
2284                 ptp_operation_issupported(params, PTP_OC_CANON_EOS_GetEvent)
2285         ) {
2286                 return PTP_RC_OK;
2287         }
2288
2289         if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) &&
2290                 ptp_operation_issupported(params, PTP_OC_CANON_CheckEvent)
2291         ) {
2292                 int isevent;
2293
2294                 ret = ptp_canon_checkevent (params,&event,&isevent);
2295                 if (ret!=PTP_RC_OK)
2296                         return ret;
2297                 if (isevent)
2298                         goto store_event;
2299                 /* Event Emulate Mode 0 (unset) and 1-5 get interrupt events. 6-7 does not. */
2300                 if (params->canon_event_mode > 5)
2301                         return ret;
2302
2303                 /* FIXME: fallthrough or return? */
2304 #ifdef __APPLE__
2305                 /* the libusb 1 on darwin currently does not like polling
2306                  * for interrupts, they have no timeout for it. 2010/08/23
2307                  * Check back in 2011 or so. -Marcus
2308                  */
2309                 return ret;
2310 #endif
2311         }
2312         ret = params->event_check(params,&event);
2313
2314 store_event:
2315         if (ret == PTP_RC_OK) {
2316                 ptp_debug (params, "event: nparams=0x%X, code=0x%X, trans_id=0x%X, p1=0x%X, p2=0x%X, p3=0x%X", event.Nparam,event.Code,event.Transaction_ID, event.Param1, event.Param2, event.Param3);
2317                 ptp_add_event (params, &event);
2318         }
2319         if (ret == PTP_ERROR_TIMEOUT) /* ok, just new events */
2320                 ret = PTP_RC_OK;
2321         return ret;
2322 }
2323
2324 int
2325 ptp_get_one_event(PTPParams *params, PTPContainer *event) {
2326         if (!params->nrofevents)
2327                 return 0;
2328         memcpy (event, params->events, sizeof(PTPContainer));
2329         memmove (params->events, params->events+1, sizeof(PTPContainer)*(params->nrofevents-1));
2330         /* do not realloc on shrink. */
2331         params->nrofevents--;
2332         if (!params->nrofevents) {
2333                 free (params->events);
2334                 params->events = NULL;
2335         }
2336         return 1;
2337 }
2338
2339 /**
2340  * ptp_canon_eos_getevent:
2341  *
2342  * This retrieves configuration status/updates/changes
2343  * on EOS cameras. It reads a datablock which has a list of variable
2344  * sized structures.
2345  *
2346  * params:      PTPParams*
2347  *
2348  * Return values: Some PTP_RC_* code.
2349  *
2350  **/
2351 uint16_t
2352 ptp_canon_eos_getevent (PTPParams* params, PTPCanon_changes_entry **entries, int *nrofentries)
2353 {
2354         PTPContainer ptp;
2355         uint16_t        ret;
2356         unsigned int    size = 0;
2357         unsigned char   *data = NULL;
2358
2359         *nrofentries = 0;
2360         *entries = NULL;
2361         PTP_CNT_INIT(ptp);
2362         ptp.Code = PTP_OC_CANON_EOS_GetEvent;
2363         ptp.Nparam = 0;
2364         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
2365         if (ret != PTP_RC_OK) return ret;
2366         *nrofentries = ptp_unpack_CANON_changes(params,data,size,entries);
2367         free (data);
2368         return PTP_RC_OK;
2369 }
2370
2371 uint16_t
2372 ptp_check_eos_events (PTPParams *params) {
2373         uint16_t                ret;
2374         PTPCanon_changes_entry  *entries = NULL, *nentries;
2375         int                     nrofentries = 0;
2376
2377         while (1) { /* call it repeatedly until the camera does not report any */
2378                 ret = ptp_canon_eos_getevent (params, &entries, &nrofentries);
2379                 if (ret != PTP_RC_OK)
2380                         return ret;
2381                 if (!nrofentries)
2382                         return PTP_RC_OK;
2383
2384                 if (params->nrofbacklogentries) {
2385                         nentries = realloc(params->backlogentries,sizeof(entries[0])*(params->nrofbacklogentries+nrofentries));
2386                         if (!nentries)
2387                                 return PTP_RC_GeneralError;
2388                         params->backlogentries = nentries;
2389                         memcpy (nentries+params->nrofbacklogentries, entries, nrofentries*sizeof(entries[0]));
2390                         params->nrofbacklogentries += nrofentries;
2391                         free (entries);
2392                 } else {
2393                         params->backlogentries = entries;
2394                         params->nrofbacklogentries = nrofentries;
2395                 }
2396         }
2397         return PTP_RC_OK;
2398 }
2399
2400 int
2401 ptp_get_one_eos_event (PTPParams *params, PTPCanon_changes_entry *entry) {
2402         if (!params->nrofbacklogentries)
2403                 return 0;
2404         memcpy (entry, params->backlogentries, sizeof(*entry));
2405         if (params->nrofbacklogentries > 1) {
2406                 memmove (params->backlogentries,params->backlogentries+1,sizeof(*entry)*(params->nrofbacklogentries-1));
2407                 params->nrofbacklogentries--;
2408         } else {
2409                 free (params->backlogentries);
2410                 params->backlogentries = NULL;
2411                 params->nrofbacklogentries = 0;
2412         }
2413         return 1;
2414 }
2415
2416
2417 uint16_t
2418 ptp_canon_eos_getdevicepropdesc (PTPParams* params, uint16_t propcode,
2419         PTPDevicePropDesc *dpd)
2420 {
2421         unsigned int i;
2422
2423         for (i=0;i<params->nrofcanon_props;i++)
2424                 if (params->canon_props[i].proptype == propcode)
2425                         break;
2426         if (params->nrofcanon_props == i)
2427                 return PTP_RC_Undefined;
2428         memcpy (dpd, &params->canon_props[i].dpd, sizeof (*dpd));
2429         if (dpd->FormFlag == PTP_DPFF_Enumeration) {
2430                 /* need to duplicate the Enumeration alloc */
2431                 dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*dpd->FORM.Enum.NumberOfValues);
2432                 memcpy (dpd->FORM.Enum.SupportedValue,
2433                         params->canon_props[i].dpd.FORM.Enum.SupportedValue,
2434                         sizeof (PTPPropertyValue)*dpd->FORM.Enum.NumberOfValues
2435                 );
2436         }
2437         if (dpd->DataType == PTP_DTC_STR) {
2438                 dpd->FactoryDefaultValue.str = strdup( params->canon_props[i].dpd.FactoryDefaultValue.str );
2439                 dpd->CurrentValue.str = strdup( params->canon_props[i].dpd.CurrentValue.str );
2440         }
2441
2442         return PTP_RC_OK;
2443 }
2444
2445
2446 uint16_t
2447 ptp_canon_eos_getstorageids (PTPParams* params, PTPStorageIDs* storageids)
2448 {
2449         PTPContainer    ptp;
2450         unsigned int    len = 0;
2451         uint16_t        ret;
2452         unsigned char*  sids=NULL;
2453
2454         PTP_CNT_INIT(ptp);
2455         ptp.Code        = PTP_OC_CANON_EOS_GetStorageIDs;
2456         ptp.Nparam      = 0;
2457         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &sids, &len);
2458         if (ret == PTP_RC_OK) ptp_unpack_SIDs(params, sids, storageids, len);
2459         free(sids);
2460         return ret;
2461 }
2462
2463 uint16_t
2464 ptp_canon_eos_getstorageinfo (PTPParams* params, uint32_t p1, unsigned char **data, unsigned int *size)
2465 {
2466         PTPContainer ptp;
2467         uint16_t        ret;
2468
2469         *size = 0;
2470         *data = NULL;
2471         PTP_CNT_INIT(ptp);
2472         ptp.Code        = PTP_OC_CANON_EOS_GetStorageInfo;
2473         ptp.Nparam      = 1;
2474         ptp.Param1      = p1;
2475         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2476         /* FIXME: do stuff with data */
2477         return ret;
2478 }
2479
2480 uint16_t
2481 ptp_canon_eos_getobjectinfoex (
2482         PTPParams* params, uint32_t storageid, uint32_t oid, uint32_t unk,
2483         PTPCANONFolderEntry **entries, unsigned int *nrofentries
2484 ) {
2485         PTPContainer    ptp;
2486         unsigned int    i, size = 0;
2487         unsigned char   *data, *xdata;
2488         uint16_t        ret;
2489
2490         data = NULL;
2491         PTP_CNT_INIT(ptp);
2492         ptp.Code        = PTP_OC_CANON_EOS_GetObjectInfoEx;
2493         ptp.Nparam      = 3;
2494         ptp.Param1      = storageid;
2495         ptp.Param2      = oid;
2496         ptp.Param3      = unk;
2497         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
2498         if (ret != PTP_RC_OK)
2499                 return ret;
2500
2501         if (!data) {
2502                 *nrofentries = 0;
2503                 return PTP_RC_OK;
2504         }
2505
2506         *nrofentries = dtoh32a(data);
2507         *entries = malloc(*nrofentries * sizeof(PTPCANONFolderEntry));
2508         if (!*entries) {
2509                 free (data);
2510                 return PTP_RC_GeneralError;
2511         }
2512
2513         xdata = data+sizeof(uint32_t);
2514         for (i=0;i<*nrofentries;i++) {
2515                 ptp_unpack_Canon_EOS_FE (params, &xdata[4], &((*entries)[i]));
2516                 xdata += dtoh32a(xdata);
2517         }
2518         free (data);
2519         return PTP_RC_OK;
2520 }
2521
2522 /**
2523  * ptp_canon_eos_getpartialobject:
2524  *
2525  * This retrieves a part of an PTP object which you specify as object id.
2526  * The id originates from 0x9116 call.
2527  * After finishing it, we seem to need to call ptp_canon_eos_enddirecttransfer.
2528  *
2529  * params:      PTPParams*
2530  *              oid             Object ID
2531  *              offset          The offset where to start the data transfer
2532  *              xsize           Size in bytes of the transfer to do
2533  *              data            Pointer that receives the malloc()ed memory of the transfer.
2534  *
2535  * Return values: Some PTP_RC_* code.
2536  *
2537  */
2538 uint16_t
2539 ptp_canon_eos_getpartialobject (PTPParams* params, uint32_t oid, uint32_t offset, uint32_t xsize, unsigned char**data)
2540 {
2541         PTPContainer    ptp;
2542         unsigned int    size = 0;
2543
2544         *data = NULL;
2545         PTP_CNT_INIT(ptp);
2546         ptp.Code        = PTP_OC_CANON_EOS_GetPartialObject;
2547         ptp.Nparam      = 3;
2548         ptp.Param1      = oid;
2549         ptp.Param2      = offset;
2550         ptp.Param3      = xsize;
2551         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, &size);
2552 }
2553
2554 uint16_t
2555 ptp_canon_eos_setdevicepropvalueex (PTPParams* params, unsigned char* data, unsigned int size)
2556 {
2557         PTPContainer    ptp;
2558
2559         PTP_CNT_INIT(ptp);
2560         ptp.Code        = PTP_OC_CANON_EOS_SetDevicePropValueEx;
2561         ptp.Nparam      = 0;
2562         return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
2563 }
2564
2565 uint16_t
2566 ptp_canon_eos_setdevicepropvalue (PTPParams* params,
2567         uint16_t propcode, PTPPropertyValue *value, uint16_t datatype
2568 ) {
2569         PTPContainer    ptp;
2570         uint16_t        ret;
2571         unsigned int    i, size;
2572         unsigned char   *data;
2573
2574         PTP_CNT_INIT(ptp);
2575         ptp.Code        = PTP_OC_CANON_EOS_SetDevicePropValueEx;
2576         ptp.Nparam      = 0;
2577         for (i=0;i<params->nrofcanon_props;i++)
2578                 if (params->canon_props[i].proptype == propcode)
2579                         break;
2580         if (params->nrofcanon_props == i)
2581                 return PTP_RC_Undefined;
2582
2583         switch (propcode) {
2584         case PTP_DPC_CANON_EOS_ImageFormat:
2585         case PTP_DPC_CANON_EOS_ImageFormatCF:
2586         case PTP_DPC_CANON_EOS_ImageFormatSD:
2587         case PTP_DPC_CANON_EOS_ImageFormatExtHD:
2588                 /* special handling of ImageFormat properties */
2589                 size = 8 + ptp_pack_EOS_ImageFormat( params, NULL, value->u16 );
2590                 data = malloc( size );
2591                 if (!data) return PTP_RC_GeneralError;
2592                 params->canon_props[i].dpd.CurrentValue.u16 = value->u16;
2593                 ptp_pack_EOS_ImageFormat( params, data + 8, value->u16 );
2594                 break;
2595         case PTP_DPC_CANON_EOS_CustomFuncEx:
2596                 /* special handling of CustomFuncEx properties */
2597                 ptp_debug (params, "ptp2/ptp_canon_eos_setdevicepropvalue: setting EOS prop %x to %s",propcode,value->str);
2598                 size = 8 + ptp_pack_EOS_CustomFuncEx( params, NULL, value->str );
2599                 data = malloc( size );
2600                 if (!data) return PTP_RC_GeneralError;
2601                 params->canon_props[i].dpd.CurrentValue.str = strdup( value->str );
2602                 ptp_pack_EOS_CustomFuncEx( params, data + 8, value->str );
2603                 break;
2604         default:
2605                 if (datatype != PTP_DTC_STR) {
2606                         data = calloc(sizeof(uint32_t),3);
2607                         if (!data) return PTP_RC_GeneralError;
2608                         size = sizeof(uint32_t)*3;
2609                 } else {
2610                         size = strlen(value->str) + 1 + 8;
2611                         data = calloc(sizeof(char),size);
2612                         if (!data) return PTP_RC_GeneralError;
2613                 }
2614                 switch (datatype) {
2615                 case PTP_DTC_INT8:
2616                 case PTP_DTC_UINT8:
2617                         /*fprintf (stderr, "%x -> %d\n", propcode, value->u8);*/
2618                         htod8a(&data[8], value->u8);
2619                         params->canon_props[i].dpd.CurrentValue.u8 = value->u8;
2620                         break;
2621                 case PTP_DTC_UINT16:
2622                 case PTP_DTC_INT16:
2623                         /*fprintf (stderr, "%x -> %d\n", propcode, value->u16);*/
2624                         htod16a(&data[8], value->u16);
2625                         params->canon_props[i].dpd.CurrentValue.u16 = value->u16;
2626                         break;
2627                 case PTP_DTC_INT32:
2628                 case PTP_DTC_UINT32:
2629                         /*fprintf (stderr, "%x -> %d\n", propcode, value->u32);*/
2630                         htod32a(&data[8], value->u32);
2631                         params->canon_props[i].dpd.CurrentValue.u32 = value->u32;
2632                         break;
2633                 case PTP_DTC_STR:
2634                         strcpy((char*)data + 8, value->str);
2635                         free (params->canon_props[i].dpd.CurrentValue.str);
2636                         params->canon_props[i].dpd.CurrentValue.str = strdup(value->str);
2637                         break;
2638                 }
2639         }
2640
2641         htod32a(&data[0], size);
2642         htod32a(&data[4], propcode);
2643
2644         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
2645         free (data);
2646         return ret;
2647 }
2648
2649 /**
2650  * ptp_canon_getpartialobject:
2651  *
2652  * This operation is used to read from the device a data
2653  * block of an object from a specified offset.
2654  *
2655  * params:      PTPParams*
2656  *      uint32_t handle - the handle of the requested object
2657  *      uint32_t offset - the offset in bytes from the beginning of the object
2658  *      uint32_t size - the requested size of data block to read
2659  *      uint32_t pos - 1 for the first block, 2 - for a block in the middle,
2660  *                  3 - for the last block
2661  *
2662  * Return values: Some PTP_RC_* code.
2663  *      char **block - the pointer to the block of data read
2664  *      uint32_t* readnum - the number of bytes read
2665  *
2666  **/
2667 uint16_t
2668 ptp_canon_getpartialobject (PTPParams* params, uint32_t handle,
2669                                 uint32_t offset, uint32_t size,
2670                                 uint32_t pos, unsigned char** block,
2671                                 uint32_t* readnum)
2672 {
2673         uint16_t ret;
2674         PTPContainer ptp;
2675         unsigned char *data=NULL;
2676         unsigned int len;
2677
2678         PTP_CNT_INIT(ptp);
2679         ptp.Code=PTP_OC_CANON_GetPartialObjectEx;
2680         ptp.Param1=handle;
2681         ptp.Param2=offset;
2682         ptp.Param3=size;
2683         ptp.Param4=pos;
2684         ptp.Nparam=4;
2685         len=0;
2686         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &len);
2687         if (ret==PTP_RC_OK) {
2688                 *block=data;
2689                 *readnum=ptp.Param1;
2690         }
2691         return ret;
2692 }
2693
2694 /**
2695  * ptp_canon_getviewfinderimage:
2696  *
2697  * This operation can be used to read the image which is currently
2698  * in the camera's viewfinder. The image size is 320x240, format is JPEG.
2699  * Of course, prior to calling this operation, one must turn the viewfinder
2700  * on with the CANON_ViewfinderOn command.
2701  * Invoking this operation many times, one can get live video from the camera!
2702  *
2703  * params:      PTPParams*
2704  *
2705  * Return values: Some PTP_RC_* code.
2706  *      char **image - the pointer to the read image
2707  *      unit32_t *size - the size of the image in bytes
2708  *
2709  **/
2710 uint16_t
2711 ptp_canon_getviewfinderimage (PTPParams* params, unsigned char** image, uint32_t* size)
2712 {
2713         uint16_t ret;
2714         PTPContainer ptp;
2715         unsigned int len;
2716
2717         PTP_CNT_INIT(ptp);
2718         ptp.Code=PTP_OC_CANON_GetViewfinderImage;
2719         ptp.Nparam=0;
2720         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, image, &len);
2721         if (ret==PTP_RC_OK) *size=ptp.Param1;
2722         return ret;
2723 }
2724
2725 /**
2726  * ptp_canon_getchanges:
2727  *
2728  * This is an interesting operation, about the effect of which I am not sure.
2729  * This command is called every time when a device property has been changed
2730  * with the SetDevicePropValue operation, and after some other operations.
2731  * This operation reads the array of Device Properties which have been changed
2732  * by the previous operation.
2733  * Probably, this operation is even required to make those changes work.
2734  *
2735  * params:      PTPParams*
2736  *
2737  * Return values: Some PTP_RC_* code.
2738  *      uint16_t** props - the pointer to the array of changed properties
2739  *      uint32_t* propnum - the number of elements in the *props array
2740  *
2741  **/
2742 uint16_t
2743 ptp_canon_getchanges (PTPParams* params, uint16_t** props, uint32_t* propnum)
2744 {
2745         uint16_t ret;
2746         PTPContainer ptp;
2747         unsigned char* data=NULL;
2748         unsigned int len;
2749
2750         PTP_CNT_INIT(ptp);
2751         ptp.Code=PTP_OC_CANON_GetChanges;
2752         ptp.Nparam=0;
2753         len=0;
2754         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &len);
2755         if (ret == PTP_RC_OK)
2756                 *propnum=ptp_unpack_uint16_t_array(params,data,0,props);
2757         free(data);
2758         return ret;
2759 }
2760
2761 /**
2762  * ptp_canon_getobjectinfo:
2763  *
2764  * This command reads a specified object's record in a device's filesystem,
2765  * or the records of all objects belonging to a specified folder (association).
2766  *
2767  * params:      PTPParams*
2768  *      uint32_t store - StorageID,
2769  *      uint32_t p2 - Yet unknown (0 value works OK)
2770  *      uint32_t parent - Parent Object Handle
2771  *                      # If Parent Object Handle is 0xffffffff,
2772  *                      # the Parent Object is the top level folder.
2773  *      uint32_t handle - Object Handle
2774  *                      # If Object Handle is 0, the records of all objects
2775  *                      # belonging to the Parent Object are read.
2776  *                      # If Object Handle is not 0, only the record of this
2777  *                      # Object is read.
2778  *
2779  * Return values: Some PTP_RC_* code.
2780  *      PTPCANONFolderEntry** entries - the pointer to the folder entry array
2781  *      uint32_t* entnum - the number of elements of the array
2782  *
2783  **/
2784 uint16_t
2785 ptp_canon_getobjectinfo (PTPParams* params, uint32_t store, uint32_t p2,
2786                             uint32_t parent, uint32_t handle,
2787                             PTPCANONFolderEntry** entries, uint32_t* entnum)
2788 {
2789         uint16_t ret;
2790         PTPContainer ptp;
2791         unsigned char *data = NULL;
2792         unsigned int len;
2793
2794         PTP_CNT_INIT(ptp);
2795         ptp.Code=PTP_OC_CANON_GetObjectInfoEx;
2796         ptp.Param1=store;
2797         ptp.Param2=p2;
2798         ptp.Param3=parent;
2799         ptp.Param4=handle;
2800         ptp.Nparam=4;
2801         len=0;
2802         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &len);
2803         if (ret == PTP_RC_OK) {
2804                 unsigned int i;
2805                 *entnum=ptp.Param1;
2806                 *entries=calloc(*entnum, sizeof(PTPCANONFolderEntry));
2807                 if (*entries!=NULL) {
2808                         for(i=0; i<(*entnum); i++)
2809                                 ptp_unpack_Canon_FE(params,
2810                                         data+i*PTP_CANON_FolderEntryLen,
2811                                         &((*entries)[i]) );
2812                 } else {
2813                         ret=PTP_ERROR_IO; /* Cannot allocate memory */
2814                 }
2815         }
2816         free(data);
2817         return ret;
2818 }
2819
2820 /**
2821  * ptp_canon_get_objecthandle_by_name:
2822  *
2823  * This command looks up the specified object on the camera.
2824  *
2825  * Format is "A:\\PATH".
2826  *
2827  * The 'A' is the VolumeLabel from GetStorageInfo,
2828  * my IXUS has "A" for the card and "V" for internal memory.
2829  *
2830  * params:      PTPParams*
2831  *      char* name - path name
2832  *
2833  * Return values: Some PTP_RC_* code.
2834  *      uint32_t *oid - PTP object id.
2835  *
2836  **/
2837 uint16_t
2838 ptp_canon_get_objecthandle_by_name (PTPParams* params, char* name, uint32_t* objectid)
2839 {
2840         uint16_t ret;
2841         PTPContainer ptp;
2842         unsigned char *data = NULL;
2843         uint8_t len;
2844
2845         PTP_CNT_INIT (ptp);
2846         ptp.Code=PTP_OC_CANON_GetObjectHandleByName;
2847         ptp.Nparam=0;
2848         len=0;
2849         data = malloc (2*(strlen(name)+1)+2);
2850         memset (data, 0, 2*(strlen(name)+1)+2);
2851         ptp_pack_string (params, name, data, 0, &len);
2852         ret=ptp_transaction (params, &ptp, PTP_DP_SENDDATA, (len+1)*2+1, &data, NULL);
2853         free (data);
2854         *objectid = ptp.Param1;
2855         return ret;
2856 }
2857
2858 /**
2859  * ptp_canon_get_customize_data:
2860  *
2861  * This command downloads the specified theme slot, including jpegs
2862  * and wav files.
2863  *
2864  * params:      PTPParams*
2865  *      uint32_t themenr - nr of theme
2866  *
2867  * Return values: Some PTP_RC_* code.
2868  *      unsigned char **data - pointer to data pointer
2869  *      unsigned int  *size - size of data returned
2870  *
2871  **/
2872 uint16_t
2873 ptp_canon_get_customize_data (PTPParams* params, uint32_t themenr,
2874                 unsigned char **data, unsigned int *size)
2875 {
2876         PTPContainer ptp;
2877
2878         *data = NULL;
2879         *size = 0;
2880         PTP_CNT_INIT(ptp);
2881         ptp.Code        = PTP_OC_CANON_GetCustomizeData;
2882         ptp.Param1      = themenr;
2883         ptp.Nparam      = 1;
2884         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2885 }
2886
2887
2888 uint16_t
2889 ptp_nikon_curve_download (PTPParams* params, unsigned char **data, unsigned int *size) {
2890         PTPContainer ptp;
2891         *data = NULL;
2892         *size = 0;
2893         PTP_CNT_INIT(ptp);
2894         ptp.Code        = PTP_OC_NIKON_CurveDownload;
2895         ptp.Nparam      = 0;
2896         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2897 }
2898
2899 /**
2900  * ptp_sony_sdioconnect:
2901  *
2902  * This changes modes of the camera
2903  *
2904  * params:      PTPParams*
2905  *
2906  * Return values: Some PTP_RC_* code.
2907  *
2908  **/
2909 uint16_t
2910 ptp_sony_sdioconnect (PTPParams* params, uint32_t p1, uint32_t p2, uint32_t p3) {
2911         PTPContainer    ptp;
2912         uint16_t        ret;
2913         unsigned char   *xdata = NULL;
2914         unsigned int    xsize;
2915
2916         PTP_CNT_INIT(ptp);
2917         ptp.Code        = PTP_OC_SONY_SDIOConnect;
2918         ptp.Nparam      = 3;
2919         ptp.Param1      = p1;
2920         ptp.Param2      = p2;
2921         ptp.Param3      = p3;
2922         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize);
2923         free (xdata);
2924         return ret;
2925 }
2926 /**
2927  * ptp_sony_get_vendorpropcodes:
2928  *
2929  * This command downloads the vendor specific property codes.
2930  *
2931  * params:      PTPParams*
2932  *
2933  * Return values: Some PTP_RC_* code.
2934  *      unsigned char **data - pointer to data pointer
2935  *      unsigned int  *size - size of data returned
2936  *
2937  **/
2938 uint16_t
2939 ptp_sony_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size) {
2940         PTPContainer    ptp;
2941         uint16_t        ret;
2942         unsigned char   *xdata = NULL;
2943         unsigned int    xsize;
2944
2945         *props = NULL;
2946         *size = 0;
2947         PTP_CNT_INIT(ptp);
2948         ptp.Code        = PTP_OC_SONY_GetSDIOGetExtDeviceInfo;
2949         ptp.Nparam      = 1;
2950         ptp.Param1      = 0xc8; /* unclear */
2951         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize);
2952         /* first 16 bit is 0xc8 0x00, then an array of 16 bit PTP ids */
2953         if (ret == PTP_RC_OK)
2954                 *size = ptp_unpack_uint16_t_array(params,xdata+2,0,props);
2955         free (xdata);
2956         return ret;
2957 }
2958
2959 uint16_t
2960 ptp_sony_getdevicepropdesc (PTPParams* params, uint16_t propcode, PTPDevicePropDesc *dpd) {
2961         PTPContainer    ptp;
2962         uint16_t        ret;
2963         unsigned char   *xdata = NULL;
2964         unsigned int    xsize,len = 0;
2965
2966         PTP_CNT_INIT(ptp);
2967         ptp.Code        = PTP_OC_SONY_GetDevicePropdesc;
2968         ptp.Nparam      = 1;
2969         ptp.Param1      = propcode;
2970         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize);
2971         /* first 16 bit is 0xc8 0x00, then an array of 16 bit PTP ids */
2972         if (ret == PTP_RC_OK)
2973                 ret = ptp_unpack_Sony_DPD(params,xdata,dpd,xsize,&len)?PTP_RC_OK:PTP_RC_GeneralError;
2974         free (xdata);
2975         return ret;
2976 }
2977
2978 uint16_t
2979 ptp_sony_getalldevicepropdesc (PTPParams* params)
2980 {
2981         PTPContainer            ptp;
2982         uint16_t                ret;
2983         unsigned char           *data = NULL , *dpddata;
2984         uint32_t                size = 0, readlen;
2985         PTPDevicePropDesc       dpd;
2986
2987         PTP_CNT_INIT(ptp);
2988         ptp.Code   = PTP_OC_SONY_GetAllDevicePropData;
2989         ptp.Nparam = 0;
2990         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
2991         if (ret != PTP_RC_OK)
2992                 return ret;
2993         dpddata = data+8; /* nr of entries 32bit, 0 32bit */
2994         size -= 8;
2995         while (size>0) {
2996                 unsigned int    i;
2997                 uint16_t        propcode;
2998
2999                 if (!ptp_unpack_Sony_DPD (params, dpddata, &dpd, size, &readlen))
3000                         break;
3001
3002                 propcode = dpd.DevicePropertyCode;
3003
3004                 for (i=0;i<params->nrofdeviceproperties;i++)
3005                         if (params->deviceproperties[i].desc.DevicePropertyCode == propcode)
3006                                 break;
3007
3008                 if (i == params->nrofdeviceproperties) {
3009                         if (!i)
3010                                 params->deviceproperties = malloc(sizeof(params->deviceproperties[0]));
3011                         else
3012                                 params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0]));
3013                         memset(&params->deviceproperties[i],0,sizeof(params->deviceproperties[0]));
3014                         params->nrofdeviceproperties++;
3015                 } else {
3016                         ptp_free_devicepropdesc (&params->deviceproperties[i].desc);
3017                 }
3018                 params->deviceproperties[i].desc = dpd;
3019 #if 0
3020                 ptp_debug (params, "dpd.DevicePropertyCode %04x, readlen %d, getset %d", dpd.DevicePropertyCode, readlen, dpd.GetSet);
3021                 switch (dpd.DataType) {
3022                 case PTP_DTC_INT8:
3023                         ptp_debug (params, "value %d/%x", dpd.CurrentValue.i8, dpd.CurrentValue.i8);
3024                         break;
3025                 case PTP_DTC_UINT8:
3026                         ptp_debug (params, "value %d/%x", dpd.CurrentValue.u8, dpd.CurrentValue.u8);
3027                         break;
3028                 case PTP_DTC_UINT16:
3029                         ptp_debug (params, "value %d/%x", dpd.CurrentValue.u16, dpd.CurrentValue.u16);
3030                         break;
3031                 case PTP_DTC_INT16:
3032                         ptp_debug (params, "value %d/%x", dpd.CurrentValue.i16, dpd.CurrentValue.i16);
3033                         break;
3034                 case PTP_DTC_INT32:
3035                         ptp_debug (params, "value %d/%x", dpd.CurrentValue.i32, dpd.CurrentValue.i32);
3036                         break;
3037                 case PTP_DTC_UINT32:
3038                         ptp_debug (params, "value %d/%x", dpd.CurrentValue.u32, dpd.CurrentValue.u32);
3039                         break;
3040                 default:
3041                         ptp_debug (params, "unknown type %x", dpd.DataType);
3042                         break;
3043                 }
3044 #endif
3045                 dpddata += readlen;
3046                 size -= readlen;
3047         }
3048         free(data);
3049         return ret;
3050 }
3051
3052 uint16_t
3053 ptp_sony_setdevicecontrolvaluea (PTPParams* params, uint16_t propcode,
3054                         PTPPropertyValue *value, uint16_t datatype)
3055 {
3056         PTPContainer ptp;
3057         uint16_t ret;
3058         uint32_t size;
3059         unsigned char* dpv=NULL;
3060
3061         PTP_CNT_INIT(ptp);
3062         ptp.Code   = PTP_OC_SONY_SetControlDeviceA;
3063         ptp.Param1 = propcode;
3064         ptp.Nparam = 1;
3065         size = ptp_pack_DPV(params, value, &dpv, datatype);
3066         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &dpv, NULL);
3067         free(dpv);
3068         return ret;
3069 }
3070
3071 uint16_t
3072 ptp_sony_setdevicecontrolvalueb (PTPParams* params, uint16_t propcode,
3073                         PTPPropertyValue *value, uint16_t datatype)
3074 {
3075         PTPContainer ptp;
3076         uint16_t ret;
3077         uint32_t size;
3078         unsigned char* dpv=NULL;
3079
3080         PTP_CNT_INIT(ptp);
3081         ptp.Code   = PTP_OC_SONY_SetControlDeviceB;
3082         ptp.Param1 = propcode;
3083         ptp.Nparam = 1;
3084         size = ptp_pack_DPV(params, value, &dpv, datatype);
3085         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &dpv, NULL);
3086         free(dpv);
3087         return ret;
3088 }
3089
3090 /**
3091  * ptp_generic_getdevicepropdesc:
3092  *
3093  * This command gets a propertydesc.
3094  * If a vendor specific property desc query is available, it uses that.
3095  * If not, it falls back to the generic PTP getdevicepropdesc.
3096  *
3097  * params:      PTPParams*
3098  *      uint16_t propcode
3099  *      PTPDevicePropDesc *dpd
3100  *
3101  * Return values: Some PTP_RC_* code.
3102  *
3103  **/
3104 /* Cache time in seconds. Should perhaps be more granular... */
3105 #define CACHETIME 2
3106
3107 uint16_t
3108 ptp_generic_getdevicepropdesc (PTPParams *params, uint16_t propcode, PTPDevicePropDesc *dpd)
3109 {
3110         unsigned int    i;
3111         uint16_t        ret;
3112         time_t          now;
3113
3114         for (i=0;i<params->nrofdeviceproperties;i++)
3115                 if (params->deviceproperties[i].desc.DevicePropertyCode == propcode)
3116                         break;
3117         if (i == params->nrofdeviceproperties) {
3118                 if (!i)
3119                         params->deviceproperties = malloc(sizeof(params->deviceproperties[0]));
3120                 else
3121                         params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0]));
3122                 memset(&params->deviceproperties[i],0,sizeof(params->deviceproperties[0]));
3123                 params->nrofdeviceproperties++;
3124         }
3125
3126         if (params->deviceproperties[i].desc.DataType != PTP_DTC_UNDEF) {
3127                 time(&now);
3128                 if ((now - params->deviceproperties[i].timestamp) <= CACHETIME) {
3129                         duplicate_DevicePropDesc(&params->deviceproperties[i].desc, dpd);
3130                         return PTP_RC_OK;
3131                 }
3132                 /* free cached entry as we will refetch it. */
3133                 ptp_free_devicepropdesc (&params->deviceproperties[i].desc);
3134         }
3135
3136         if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) &&
3137                 ptp_operation_issupported(params, PTP_OC_SONY_GetAllDevicePropData)
3138         ) {
3139                 ret = ptp_sony_getalldevicepropdesc (params);
3140                 if (ret != PTP_RC_OK)
3141                         return ret;
3142
3143                 for (i=0;i<params->nrofdeviceproperties;i++)
3144                         if (params->deviceproperties[i].desc.DevicePropertyCode == propcode)
3145                                 break;
3146                 time(&now);
3147                 params->deviceproperties[i].timestamp = now;
3148                 duplicate_DevicePropDesc(&params->deviceproperties[i].desc, dpd);
3149                 return PTP_RC_OK;
3150         }
3151         if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) &&
3152                 ptp_operation_issupported(params, PTP_OC_SONY_GetDevicePropdesc)
3153         ) {
3154                 ret = ptp_sony_getdevicepropdesc (params, propcode, &params->deviceproperties[i].desc);
3155                 if (ret != PTP_RC_OK)
3156                         return ret;
3157
3158                 time(&now);
3159                 params->deviceproperties[i].timestamp = now;
3160                 duplicate_DevicePropDesc(&params->deviceproperties[i].desc, dpd);
3161                 return PTP_RC_OK;
3162         }
3163
3164
3165         if (ptp_operation_issupported(params, PTP_OC_GetDevicePropDesc)) {
3166                 ret = ptp_getdevicepropdesc (params, propcode, &params->deviceproperties[i].desc);
3167                 if (ret != PTP_RC_OK)
3168                         return ret;
3169
3170                 time(&now);
3171                 params->deviceproperties[i].timestamp = now;
3172                 duplicate_DevicePropDesc(&params->deviceproperties[i].desc, dpd);
3173                 return PTP_RC_OK;
3174         }
3175
3176         return PTP_RC_OK;
3177 }
3178
3179 /**
3180  * ptp_generic_setdevicepropvalue:
3181  *
3182  * This command sets a property value, device specific.
3183  *
3184  * params:      PTPParams*
3185  *      uint16_t propcode
3186  *      PTPDevicePropertyValue *value
3187  *      uint16_t datatype
3188  *
3189  * Return values: Some PTP_RC_* code.
3190  *
3191  **/
3192 uint16_t
3193 ptp_generic_setdevicepropvalue (PTPParams* params, uint16_t propcode,
3194         PTPPropertyValue *value, uint16_t datatype)
3195 {
3196         /* FIXME: change the cache? hmm */
3197         if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) &&
3198                 ptp_operation_issupported(params, PTP_OC_SONY_SetControlDeviceB)
3199         )
3200                 return ptp_sony_setdevicecontrolvaluea (params, propcode, value, datatype);
3201         return ptp_setdevicepropvalue (params, propcode, value, datatype);
3202 }
3203
3204 /**
3205  * ptp_nikon_get_vendorpropcodes:
3206  *
3207  * This command downloads the vendor specific property codes.
3208  *
3209  * params:      PTPParams*
3210  *
3211  * Return values: Some PTP_RC_* code.
3212  *      unsigned char **data - pointer to data pointer
3213  *      unsigned int  *size - size of data returned
3214  *
3215  **/
3216 uint16_t
3217 ptp_nikon_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size) {
3218         PTPContainer    ptp;
3219         uint16_t        ret;
3220         unsigned char   *xdata = NULL;
3221         unsigned int    xsize;
3222
3223         *props = NULL;
3224         *size = 0;
3225         PTP_CNT_INIT(ptp);
3226         ptp.Code        = PTP_OC_NIKON_GetVendorPropCodes;
3227         ptp.Nparam      = 0;
3228         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize);
3229         if (ret == PTP_RC_OK)
3230                 *size = ptp_unpack_uint16_t_array(params,xdata,0,props);
3231         free (xdata);
3232         return ret;
3233 }
3234
3235 uint16_t
3236 ptp_nikon_getfileinfoinblock ( PTPParams* params,
3237         uint32_t p1, uint32_t p2, uint32_t p3,
3238         unsigned char **data, unsigned int *size
3239 ) {
3240         PTPContainer ptp;
3241         *data = NULL;
3242         *size = 0;
3243         PTP_CNT_INIT(ptp);
3244         ptp.Code        = PTP_OC_NIKON_GetFileInfoInBlock;
3245         ptp.Nparam      = 3;
3246         ptp.Param1      = p1;
3247         ptp.Param2      = p2;
3248         ptp.Param3      = p3;
3249         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
3250 }
3251
3252 /**
3253  * ptp_nikon_get_liveview_image:
3254  *
3255  * This command gets a LiveView image from newer Nikons DSLRs.
3256  *
3257  * params:      PTPParams*
3258  *
3259  * Return values: Some PTP_RC_* code.
3260  *
3261  **/
3262 uint16_t
3263 ptp_nikon_get_liveview_image (PTPParams* params, unsigned char **data, unsigned int *size)
3264 {
3265         PTPContainer ptp;
3266
3267         PTP_CNT_INIT(ptp);
3268         ptp.Code=PTP_OC_NIKON_GetLiveViewImg;
3269         ptp.Nparam=0;
3270         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
3271 }
3272
3273 /**
3274  * ptp_nikon_get_preview_image:
3275  *
3276  * This command gets a Preview image from newer Nikons DSLRs.
3277  *
3278  * params:      PTPParams*
3279  *
3280  * Return values: Some PTP_RC_* code.
3281  *
3282  **/
3283 uint16_t
3284 ptp_nikon_get_preview_image (PTPParams* params, unsigned char **xdata, unsigned int *xsize,
3285         uint32_t *handle)
3286 {
3287         PTPContainer    ptp;
3288         uint16_t        ret;
3289
3290         PTP_CNT_INIT(ptp);
3291         ptp.Code=PTP_OC_NIKON_GetPreviewImg;
3292         ptp.Nparam=0;
3293         /* FIXME:
3294          * pdslrdashboard passes 3 parameters:
3295          * objectid, minimum size, maximum size
3296          */
3297         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, xdata, xsize);
3298         if (ret == PTP_RC_OK) {
3299                 if (ptp.Nparam > 0)
3300                         *handle = ptp.Param1;
3301         }
3302         return ret;
3303 }
3304
3305 /**
3306  * ptp_canon_eos_get_viewfinder_image:
3307  *
3308  * This command gets a Viewfinder image from newer Nikons DSLRs.
3309  *
3310  * params:      PTPParams*
3311  *
3312  * Return values: Some PTP_RC_* code.
3313  *
3314  **/
3315 uint16_t
3316 ptp_canon_eos_get_viewfinder_image (PTPParams* params, unsigned char **data, unsigned int *size)
3317 {
3318         PTPContainer ptp;
3319
3320         PTP_CNT_INIT(ptp);
3321         ptp.Code=PTP_OC_CANON_EOS_GetViewFinderData;
3322         ptp.Nparam=1;
3323         ptp.Param1=0x00100000; /* from trace */
3324         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
3325 }
3326
3327 uint16_t
3328 ptp_canon_eos_get_viewfinder_image_handler (PTPParams* params, PTPDataHandler*handler)
3329 {
3330         PTPContainer ptp;
3331
3332         PTP_CNT_INIT(ptp);
3333         ptp.Code=PTP_OC_CANON_EOS_GetViewFinderData;
3334         ptp.Nparam=1;
3335         ptp.Param1=0x00100000; /* from trace */
3336         return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler);
3337 }
3338
3339 /**
3340  * ptp_nikon_check_event:
3341  *
3342  * This command checks the event queue on the Nikon.
3343  *
3344  * params:      PTPParams*
3345  *      PTPUSBEventContainer **event - list of usb events.
3346  *      int *evtcnt - number of usb events in event structure.
3347  *
3348  * Return values: Some PTP_RC_* code.
3349  *
3350  **/
3351 uint16_t
3352 ptp_nikon_check_event (PTPParams* params, PTPContainer** event, unsigned int* evtcnt)
3353 {
3354         PTPContainer ptp;
3355         uint16_t ret;
3356         unsigned char *data = NULL;
3357         unsigned int size = 0;
3358
3359         PTP_CNT_INIT(ptp);
3360         ptp.Code=PTP_OC_NIKON_CheckEvent;
3361         ptp.Nparam=0;
3362         *evtcnt = 0;
3363         ret = ptp_transaction (params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
3364         if (ret == PTP_RC_OK) {
3365                 ptp_unpack_Nikon_EC (params, data, size, event, evtcnt);
3366                 free (data);
3367         }
3368         return ret;
3369 }
3370
3371 /**
3372  * ptp_nikon_getptpipinfo:
3373  *
3374  * This command gets the ptpip info data.
3375  *
3376  * params:      PTPParams*
3377  *      unsigned char *data     - data
3378  *      unsigned int size       - size of returned data
3379  *
3380  * Return values: Some PTP_RC_* code.
3381  *
3382  **/
3383 uint16_t
3384 ptp_nikon_getptpipinfo (PTPParams* params, unsigned char **data, unsigned int *size)
3385 {
3386         PTPContainer ptp;
3387
3388         PTP_CNT_INIT(ptp);
3389         ptp.Code=PTP_OC_NIKON_GetDevicePTPIPInfo;
3390         ptp.Nparam=0;
3391         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
3392 }
3393
3394 /**
3395  * ptp_nikon_getwifiprofilelist:
3396  *
3397  * This command gets the wifi profile list.
3398  *
3399  * params:      PTPParams*
3400  *
3401  * Return values: Some PTP_RC_* code.
3402  *
3403  **/
3404 uint16_t
3405 ptp_nikon_getwifiprofilelist (PTPParams* params)
3406 {
3407         PTPContainer ptp;
3408         unsigned char* data;
3409         unsigned int size;
3410         unsigned int pos;
3411         unsigned int profn;
3412         unsigned int n;
3413         char* buffer;
3414         uint8_t len;
3415
3416         PTP_CNT_INIT(ptp);
3417         ptp.Code=PTP_OC_NIKON_GetProfileAllData;
3418         ptp.Nparam=0;
3419         size = 0;
3420         data = NULL;
3421         CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
3422
3423         if (size < 2) return PTP_RC_Undefined; /* FIXME: Add more precise error code */
3424
3425         params->wifi_profiles_version = data[0];
3426         params->wifi_profiles_number = data[1];
3427         if (params->wifi_profiles)
3428                 free(params->wifi_profiles);
3429
3430         params->wifi_profiles = malloc(params->wifi_profiles_number*sizeof(PTPNIKONWifiProfile));
3431         memset(params->wifi_profiles, 0, params->wifi_profiles_number*sizeof(PTPNIKONWifiProfile));
3432
3433         pos = 2;
3434         profn = 0;
3435         while (profn < params->wifi_profiles_number && pos < size) {
3436                 if (pos+6 >= size) return PTP_RC_Undefined;
3437                 params->wifi_profiles[profn].id = data[pos++];
3438                 params->wifi_profiles[profn].valid = data[pos++];
3439
3440                 n = dtoh32a(&data[pos]);
3441                 pos += 4;
3442                 if (pos+n+4 >= size) return PTP_RC_Undefined;
3443                 strncpy(params->wifi_profiles[profn].profile_name, (char*)&data[pos], n);
3444                 params->wifi_profiles[profn].profile_name[16] = '\0';
3445                 pos += n;
3446
3447                 params->wifi_profiles[profn].display_order = data[pos++];
3448                 params->wifi_profiles[profn].device_type = data[pos++];
3449                 params->wifi_profiles[profn].icon_type = data[pos++];
3450
3451                 buffer = ptp_unpack_string(params, data, pos, &len);
3452                 strncpy(params->wifi_profiles[profn].creation_date, buffer, sizeof(params->wifi_profiles[profn].creation_date));
3453                 free (buffer);
3454                 pos += (len*2+1);
3455                 if (pos+1 >= size) return PTP_RC_Undefined;
3456                 /* FIXME: check if it is really last usage date */
3457                 buffer = ptp_unpack_string(params, data, pos, &len);
3458                 strncpy(params->wifi_profiles[profn].lastusage_date, buffer, sizeof(params->wifi_profiles[profn].lastusage_date));
3459                 free (buffer);
3460                 pos += (len*2+1);
3461                 if (pos+5 >= size) return PTP_RC_Undefined;
3462
3463                 n = dtoh32a(&data[pos]);
3464                 pos += 4;
3465                 if (pos+n >= size) return PTP_RC_Undefined;
3466                 strncpy(params->wifi_profiles[profn].essid, (char*)&data[pos], n);
3467                 params->wifi_profiles[profn].essid[32] = '\0';
3468                 pos += n;
3469                 pos += 1;
3470                 profn++;
3471         }
3472
3473 #if 0
3474         PTPNIKONWifiProfile test;
3475         memset(&test, 0, sizeof(PTPNIKONWifiProfile));
3476         strcpy(test.profile_name, "MyTest");
3477         test.icon_type = 1;
3478         strcpy(test.essid, "nikon");
3479         test.ip_address = 10 + 11 << 16 + 11 << 24;
3480         test.subnet_mask = 24;
3481         test.access_mode = 1;
3482         test.wifi_channel = 1;
3483         test.key_nr = 1;
3484
3485         ptp_nikon_writewifiprofile(params, &test);
3486 #endif
3487
3488         return PTP_RC_OK;
3489 }
3490
3491 /**
3492  * ptp_nikon_writewifiprofile:
3493  *
3494  * This command gets the ptpip info data.
3495  *
3496  * params:      PTPParams*
3497  *      unsigned int profilenr  - profile number
3498  *      unsigned char *data     - data
3499  *      unsigned int size       - size of returned data
3500  *
3501  * Return values: Some PTP_RC_* code.
3502  *
3503  **/
3504 uint16_t
3505 ptp_nikon_writewifiprofile (PTPParams* params, PTPNIKONWifiProfile* profile)
3506 {
3507         unsigned char guid[16];
3508
3509         PTPContainer ptp;
3510         unsigned char buffer[1024];
3511         unsigned char* data = buffer;
3512         int size = 0;
3513         int i;
3514         uint8_t len;
3515         int profilenr = -1;
3516
3517         ptp_nikon_getptpipguid(guid);
3518
3519         if (!params->wifi_profiles)
3520                 CHECK_PTP_RC(ptp_nikon_getwifiprofilelist(params));
3521
3522         for (i = 0; i < params->wifi_profiles_number; i++) {
3523                 if (!params->wifi_profiles[i].valid) {
3524                         profilenr = params->wifi_profiles[i].id;
3525                         break;
3526                 }
3527         }
3528
3529         if (profilenr == -1) {
3530                 /* No free profile! */
3531                 return PTP_RC_StoreFull;
3532         }
3533
3534         memset(buffer, 0, 1024);
3535
3536         buffer[0x00] = 0x64; /* Version */
3537
3538         /* Profile name */
3539         htod32a(&buffer[0x01], 17);
3540         /* 16 as third parameter, so there will always be a null-byte in the end */
3541         strncpy((char*)&buffer[0x05], profile->profile_name, 16);
3542
3543         buffer[0x16] = 0x00; /* Display order */
3544         buffer[0x17] = profile->device_type;
3545         buffer[0x18] = profile->icon_type;
3546
3547         /* FIXME: Creation date: put a real date here */
3548         ptp_pack_string(params, "19990909T090909", data, 0x19, &len);
3549
3550         /* IP parameters */
3551         memcpy(&buffer[0x3A],&profile->ip_address,sizeof(profile->ip_address));
3552         /**((unsigned int*)&buffer[0x3A]) = profile->ip_address; *//* Do not reverse bytes */
3553         buffer[0x3E] = profile->subnet_mask;
3554         memcpy(&buffer[0x3F],&profile->gateway_address,sizeof(profile->gateway_address));
3555         /**((unsigned int*)&buffer[0x3F]) = profile->gateway_address; */ /* Do not reverse bytes */
3556         buffer[0x43] = profile->address_mode;
3557
3558         /* Wifi parameters */
3559         buffer[0x44] = profile->access_mode;
3560         buffer[0x45] = profile->wifi_channel;
3561
3562         htod32a(&buffer[0x46], 33); /* essid */
3563          /* 32 as third parameter, so there will always be a null-byte in the end */
3564         strncpy((char*)&buffer[0x4A], profile->essid, 32);
3565
3566         buffer[0x6B] = profile->authentification;
3567         buffer[0x6C] = profile->encryption;
3568         htod32a(&buffer[0x6D], 64);
3569         for (i = 0; i < 64; i++) {
3570                 buffer[0x71+i] = profile->key[i];
3571         }
3572         buffer[0xB1] = profile->key_nr;
3573         memcpy(&buffer[0xB2], guid, 16);
3574
3575         switch(profile->encryption) {
3576         case 1: /* WEP 64bit */
3577                 htod16a(&buffer[0xC2], 5); /* (64-24)/8 = 5 */
3578                 break;
3579         case 2: /* WEP 128bit */
3580                 htod16a(&buffer[0xC2], 13); /* (128-24)/8 = 13 */
3581                 break;
3582         default:
3583                 htod16a(&buffer[0xC2], 0);
3584         }
3585         size = 0xC4;
3586
3587         PTP_CNT_INIT(ptp);
3588         ptp.Code=PTP_OC_NIKON_SendProfileData;
3589         ptp.Nparam=1;
3590         ptp.Param1=profilenr;
3591         return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
3592 }
3593
3594 /**
3595  * ptp_mtp_getobjectpropssupported:
3596  *
3597  * This command gets the object properties possible from the device.
3598  *
3599  * params:      PTPParams*
3600  *      uint ofc                - object format code
3601  *      unsigned int *propnum   - number of elements in returned array
3602  *      uint16_t *props         - array of supported properties
3603  *
3604  * Return values: Some PTP_RC_* code.
3605  *
3606  **/
3607 uint16_t
3608 ptp_mtp_getobjectpropssupported (PTPParams* params, uint16_t ofc,
3609                  uint32_t *propnum, uint16_t **props
3610 ) {
3611         PTPContainer ptp;
3612         uint16_t ret;
3613         unsigned char *data = NULL;
3614         unsigned int size = 0;
3615
3616         PTP_CNT_INIT(ptp);
3617         ptp.Code=PTP_OC_MTP_GetObjectPropsSupported;
3618         ptp.Nparam = 1;
3619         ptp.Param1 = ofc;
3620         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
3621         if (ret == PTP_RC_OK)
3622                 *propnum=ptp_unpack_uint16_t_array(params,data,0,props);
3623         free(data);
3624         return ret;
3625 }
3626
3627 /**
3628  * ptp_mtp_getobjectpropdesc:
3629  *
3630  * This command gets the object property description.
3631  *
3632  * params:      PTPParams*
3633  *      uint16_t opc    - object property code
3634  *      uint16_t ofc    - object format code
3635  *
3636  * Return values: Some PTP_RC_* code.
3637  *
3638  **/
3639 uint16_t
3640 ptp_mtp_getobjectpropdesc (
3641         PTPParams* params, uint16_t opc, uint16_t ofc, PTPObjectPropDesc *opd
3642 ) {
3643         PTPContainer ptp;
3644         uint16_t ret;
3645         unsigned char *data = NULL;
3646         unsigned int size = 0;
3647
3648         PTP_CNT_INIT(ptp);
3649         ptp.Code=PTP_OC_MTP_GetObjectPropDesc;
3650         ptp.Nparam = 2;
3651         ptp.Param1 = opc;
3652         ptp.Param2 = ofc;
3653         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
3654         if (ret == PTP_RC_OK)
3655                 ptp_unpack_OPD (params, data, opd, size);
3656         free(data);
3657         return ret;
3658 }
3659
3660 /**
3661  * ptp_mtp_getobjectpropvalue:
3662  *
3663  * This command gets the object properties of an object handle.
3664  *
3665  * params:      PTPParams*
3666  *      uint32_t objectid       - object format code
3667  *      uint16_t opc            - object prop code
3668  *
3669  * Return values: Some PTP_RC_* code.
3670  *
3671  **/
3672 uint16_t
3673 ptp_mtp_getobjectpropvalue (
3674         PTPParams* params, uint32_t oid, uint16_t opc,
3675         PTPPropertyValue *value, uint16_t datatype
3676 ) {
3677         PTPContainer ptp;
3678         uint16_t ret;
3679         unsigned char *data = NULL;
3680         unsigned int size = 0;
3681         unsigned int offset = 0;
3682
3683         PTP_CNT_INIT(ptp);
3684         ptp.Code=PTP_OC_MTP_GetObjectPropValue;
3685         ptp.Nparam = 2;
3686         ptp.Param1 = oid;
3687         ptp.Param2 = opc;
3688         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
3689         if (ret == PTP_RC_OK) {
3690                 int ret2 = ptp_unpack_DPV(params, data, &offset, size, value, datatype);
3691                 if (!ret2) {
3692                         ptp_debug (params, "ptp_mtp_getobjectpropvalue: unpacking DPV failed");
3693                         ret = PTP_RC_GeneralError;
3694                 }
3695         }
3696         free(data);
3697         return ret;
3698 }
3699
3700 /**
3701  * ptp_mtp_setobjectpropvalue:
3702  *
3703  * This command gets the object properties of an object handle.
3704  *
3705  * params:      PTPParams*
3706  *      uint32_t objectid       - object format code
3707  *      uint16_t opc            - object prop code
3708  *
3709  * Return values: Some PTP_RC_* code.
3710  *
3711  **/
3712 uint16_t
3713 ptp_mtp_setobjectpropvalue (
3714         PTPParams* params, uint32_t oid, uint16_t opc,
3715         PTPPropertyValue *value, uint16_t datatype
3716 ) {
3717         PTPContainer ptp;
3718         uint16_t ret;
3719         unsigned char *data = NULL;
3720         unsigned int size ;
3721
3722         PTP_CNT_INIT(ptp);
3723         ptp.Code=PTP_OC_MTP_SetObjectPropValue;
3724         ptp.Nparam = 2;
3725         ptp.Param1 = oid;
3726         ptp.Param2 = opc;
3727         size = ptp_pack_DPV(params, value, &data, datatype);
3728         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
3729         free(data);
3730         return ret;
3731 }
3732
3733 uint16_t
3734 ptp_mtp_getobjectreferences (PTPParams* params, uint32_t handle, uint32_t** ohArray, uint32_t* arraylen)
3735 {
3736         PTPContainer ptp;
3737         uint16_t ret;
3738         unsigned char* dpv=NULL;
3739         unsigned int dpvlen = 0;
3740
3741         PTP_CNT_INIT(ptp);
3742         ptp.Code=PTP_OC_MTP_GetObjectReferences;
3743         ptp.Param1=handle;
3744         ptp.Nparam=1;
3745         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpv, &dpvlen);
3746         if (ret == PTP_RC_OK) {
3747                 /* Sandisk Sansa skips the DATA phase, but returns OK as response.
3748                  * this will gives us a NULL here. Handle it. -Marcus */
3749                 if ((dpv == NULL) || (dpvlen == 0)) {
3750                         *arraylen = 0;
3751                         *ohArray = NULL;
3752                 } else {
3753                         *arraylen = ptp_unpack_uint32_t_array(params, dpv, 0, ohArray);
3754                 }
3755         }
3756         free(dpv);
3757         return ret;
3758 }
3759
3760 uint16_t
3761 ptp_mtp_setobjectreferences (PTPParams* params, uint32_t handle, uint32_t* ohArray, uint32_t arraylen)
3762 {
3763         PTPContainer ptp;
3764         uint16_t ret;
3765         uint32_t size;
3766         unsigned char* dpv=NULL;
3767
3768         PTP_CNT_INIT(ptp);
3769         ptp.Code   = PTP_OC_MTP_SetObjectReferences;
3770         ptp.Param1 = handle;
3771         ptp.Nparam = 1;
3772         size = ptp_pack_uint32_t_array(params, ohArray, arraylen, &dpv);
3773         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, (unsigned char **)&dpv, NULL);
3774         free(dpv);
3775         return ret;
3776 }
3777
3778 uint16_t
3779 ptp_mtp_getobjectproplist (PTPParams* params, uint32_t handle, MTPProperties **props, int *nrofprops)
3780 {
3781         uint16_t ret;
3782         PTPContainer ptp;
3783         unsigned char* opldata = NULL;
3784         unsigned int oplsize;
3785
3786         PTP_CNT_INIT(ptp);
3787         ptp.Code = PTP_OC_MTP_GetObjPropList;
3788         ptp.Param1 = handle;
3789         ptp.Param2 = 0x00000000U;  /* 0x00000000U should be "all formats" */
3790         ptp.Param3 = 0xFFFFFFFFU;  /* 0xFFFFFFFFU should be "all properties" */
3791         ptp.Param4 = 0x00000000U;
3792         ptp.Param5 = 0xFFFFFFFFU;  /* means - return full tree below the Param1 handle */
3793         ptp.Nparam = 5;
3794         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &opldata, &oplsize);
3795         if (ret == PTP_RC_OK) *nrofprops = ptp_unpack_OPL(params, opldata, props, oplsize);
3796         if (opldata != NULL)
3797                 free(opldata);
3798         return ret;
3799 }
3800
3801 uint16_t
3802 ptp_mtp_getobjectproplist_single (PTPParams* params, uint32_t handle, MTPProperties **props, int *nrofprops)
3803 {
3804         uint16_t ret;
3805         PTPContainer ptp;
3806         unsigned char* opldata = NULL;
3807         unsigned int oplsize;
3808
3809         PTP_CNT_INIT(ptp);
3810         ptp.Code = PTP_OC_MTP_GetObjPropList;
3811         ptp.Param1 = handle;
3812         ptp.Param2 = 0x00000000U;  /* 0x00000000U should be "all formats" */
3813         ptp.Param3 = 0xFFFFFFFFU;  /* 0xFFFFFFFFU should be "all properties" */
3814         ptp.Param4 = 0x00000000U;
3815         ptp.Param5 = 0x00000000U;  /* means - return single tree below the Param1 handle */
3816         ptp.Nparam = 5;
3817         ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &opldata, &oplsize);
3818         if (ret == PTP_RC_OK) *nrofprops = ptp_unpack_OPL(params, opldata, props, oplsize);
3819         if (opldata != NULL)
3820                 free(opldata);
3821         return ret;
3822 }
3823
3824 uint16_t
3825 ptp_mtp_sendobjectproplist (PTPParams* params, uint32_t* store, uint32_t* parenthandle, uint32_t* handle,
3826                             uint16_t objecttype, uint64_t objectsize, MTPProperties *props, int nrofprops)
3827 {
3828         uint16_t ret;
3829         PTPContainer ptp;
3830         unsigned char* opldata=NULL;
3831         uint32_t oplsize;
3832
3833         PTP_CNT_INIT(ptp);
3834         ptp.Code = PTP_OC_MTP_SendObjectPropList;
3835         ptp.Param1 = *store;
3836         ptp.Param2 = *parenthandle;
3837         ptp.Param3 = (uint32_t) objecttype;
3838         ptp.Param4 = (uint32_t) (objectsize >> 32);
3839         ptp.Param5 = (uint32_t) (objectsize & 0xffffffffU);
3840         ptp.Nparam = 5;
3841
3842         /* Set object handle to 0 for a new object */
3843         oplsize = ptp_pack_OPL(params,props,nrofprops,&opldata);
3844         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, oplsize, &opldata, NULL);
3845         free(opldata);
3846         *store = ptp.Param1;
3847         *parenthandle = ptp.Param2;
3848         *handle = ptp.Param3;
3849
3850         return ret;
3851 }
3852
3853 uint16_t
3854 ptp_mtp_setobjectproplist (PTPParams* params, MTPProperties *props, int nrofprops)
3855 {
3856         uint16_t ret;
3857         PTPContainer ptp;
3858         unsigned char* opldata=NULL;
3859         uint32_t oplsize;
3860
3861         PTP_CNT_INIT(ptp);
3862         ptp.Code = PTP_OC_MTP_SetObjPropList;
3863         ptp.Nparam = 0;
3864
3865         oplsize = ptp_pack_OPL(params,props,nrofprops,&opldata);
3866         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, oplsize, &opldata, NULL);
3867         free(opldata);
3868
3869         return ret;
3870 }
3871
3872 uint16_t
3873 ptp_mtpz_sendwmdrmpdapprequest (PTPParams* params, unsigned char *appcertmsg, uint32_t size)
3874 {
3875         PTPContainer ptp;
3876
3877         PTP_CNT_INIT(ptp);
3878         ptp.Code=PTP_OC_MTP_WMDRMPD_SendWMDRMPDAppRequest;
3879         return ptp_transaction (params, &ptp, PTP_DP_SENDDATA, size, &appcertmsg, NULL);
3880 }
3881
3882 uint16_t
3883 ptp_mtpz_getwmdrmpdappresponse (PTPParams* params, unsigned char **response, uint32_t *size)
3884 {
3885         PTPContainer ptp;
3886
3887         PTP_CNT_INIT(ptp);
3888         ptp.Code = PTP_OC_MTP_WMDRMPD_GetWMDRMPDAppResponse;
3889         *size = 0;
3890         *response = NULL;
3891         return ptp_transaction (params, &ptp, PTP_DP_GETDATA, 0, response, size);
3892 }
3893
3894 /****** CHDK interface ******/
3895
3896 uint16_t
3897 ptp_chdk_get_memory(PTPParams* params, int start, int num, unsigned char **buf)
3898 {
3899         PTPContainer ptp;
3900
3901         PTP_CNT_INIT(ptp);
3902         ptp.Code=PTP_OC_CHDK;
3903         ptp.Nparam=3;
3904         ptp.Param1=PTP_CHDK_GetMemory;
3905         ptp.Param2=start;
3906         ptp.Param3=num;
3907         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, buf, NULL);
3908 }
3909
3910 uint16_t
3911 ptp_chdk_set_memory_long(PTPParams* params, int addr, int val)
3912 {
3913         PTPContainer ptp;
3914         unsigned char *buf = (unsigned char *) &val; /* FIXME ... endianness? */
3915
3916         PTP_CNT_INIT(ptp);
3917         ptp.Code=PTP_OC_CHDK;
3918         ptp.Nparam=3;
3919         ptp.Param1=PTP_CHDK_SetMemory;
3920         ptp.Param2=addr;
3921         ptp.Param3=4;
3922         return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, 4, &buf, NULL);
3923 }
3924
3925 #if 0
3926 int ptp_chdk_upload(PTPParams* params, char *local_fn, char *remote_fn)
3927 {
3928   uint16_t ret;
3929   PTPContainer ptp;
3930   char *buf = NULL;
3931   FILE *f;
3932   unsigned file_len,data_len,file_name_len;
3933
3934   PTP_CNT_INIT(ptp);
3935   ptp.Code=PTP_OC_CHDK;
3936   ptp.Nparam=1;
3937   ptp.Param1=PTP_CHDK_UploadFile;
3938
3939   f = fopen(local_fn,"rb");
3940   if ( f == NULL )
3941   {
3942     ptp_error(params,"could not open file \'%s\'",local_fn);
3943     return 0;
3944   }
3945
3946   fseek(f,0,SEEK_END);
3947   file_len = ftell(f);
3948   fseek(f,0,SEEK_SET);
3949
3950   file_name_len = strlen(remote_fn);
3951   data_len = 4 + file_name_len + file_len;
3952   buf = malloc(data_len);
3953   memcpy(buf,&file_name_len,4);
3954   memcpy(buf+4,remote_fn,file_name_len);
3955   fread(buf+4+file_name_len,1,file_len,f);
3956
3957   fclose(f);
3958
3959   ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, data_len, &buf, NULL);
3960
3961   free(buf);
3962
3963   if ( ret != PTP_RC_OK )
3964   {
3965     ptp_error(params,"unexpected return code 0x%x",ret);
3966     return 0;
3967   }
3968   return 1;
3969 }
3970
3971 static uint16_t gd_to_file(PTPParams* params, PTPGetdataParams *gdparams, unsigned len, unsigned char *bytes) {
3972         FILE *f = (FILE *)gdparams->handler_data;
3973         size_t count=fwrite(bytes,1,len,f);
3974         if(count != len) {
3975                 return PTP_ERROR_IO;
3976         }
3977         return PTP_RC_OK;
3978 }
3979
3980 int ptp_chdk_download(PTPParams* params, char *remote_fn, char *local_fn)
3981 {
3982   uint16_t ret;
3983   PTPContainer ptp;
3984   PTPGetdataParams gdparams;
3985   FILE *f;
3986
3987   f = fopen(local_fn,"wb");
3988   if ( f == NULL )
3989   {
3990     ptp_error(params,"could not open file \'%s\'",local_fn);
3991     return 0;
3992   }
3993
3994   PTP_CNT_INIT(ptp);
3995   ptp.Code=PTP_OC_CHDK;
3996   ptp.Nparam=2;
3997   ptp.Param1=PTP_CHDK_TempData;
3998   ptp.Param2=0;
3999   ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, strlen(remote_fn), &remote_fn, NULL);
4000   if ( ret != PTP_RC_OK )
4001   {
4002     ptp_error(params,"unexpected return code 0x%x",ret);
4003         fclose(f);
4004     return 0;
4005   }
4006
4007   PTP_CNT_INIT(ptp);
4008   ptp.Code=PTP_OC_CHDK;
4009   ptp.Nparam=1;
4010   ptp.Param1=PTP_CHDK_DownloadFile;
4011
4012   PTP_CNT_INIT(gdparams);
4013
4014   gdparams.handler = gd_to_file;
4015   gdparams.block_size = 0; // default
4016   gdparams.handler_data = f;
4017   ret=ptp_getdata_transaction(params, &ptp, &gdparams);
4018   fclose(f);
4019   if ( ret != PTP_RC_OK )
4020   {
4021     ptp_error(params,"unexpected return code 0x%x",ret);
4022     return 0;
4023   }
4024
4025   return 1;
4026 }
4027 #endif
4028
4029 /*
4030  * Preliminary remote capture over USB code. Corresponding CHDK code is in the ptp-remote-capture-test
4031  * This is under development and should not be included in builds for general distribution
4032  */
4033 /*
4034  * isready: 0: not ready, lowest 2 bits: available image formats, 0x10000000: error
4035  */
4036 uint16_t
4037 ptp_chdk_rcisready(PTPParams* params, int *isready, int *imgnum)
4038 {
4039         uint16_t ret;
4040         PTPContainer ptp;
4041
4042         PTP_CNT_INIT(ptp);
4043         ptp.Code=PTP_OC_CHDK;
4044         ptp.Nparam=1;
4045         ptp.Param1=PTP_CHDK_RemoteCaptureIsReady;
4046
4047         ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
4048         if ( ret != PTP_RC_OK )
4049                 return ret;
4050         *isready=ptp.Param1;
4051         *imgnum=ptp.Param2;
4052         return ret;
4053 }
4054
4055 uint16_t
4056 ptp_chdk_rcgetchunk(PTPParams* params, int fmt, ptp_chdk_rc_chunk *chunk)
4057 {
4058         uint16_t ret;
4059         PTPContainer ptp;
4060
4061         PTP_CNT_INIT(ptp);
4062         ptp.Code=PTP_OC_CHDK;
4063         ptp.Nparam=2;
4064         ptp.Param1=PTP_CHDK_RemoteCaptureGetData;
4065         ptp.Param2=fmt; //get chunk
4066
4067         chunk->data = NULL;
4068         chunk->size = 0;
4069         chunk->offset = 0;
4070         chunk->last = 0;
4071
4072         // TODO should allow ptp_getdata_transaction to send chunks directly to file, or to mem
4073         ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &chunk->data, NULL);
4074         if ( ret != PTP_RC_OK )
4075           return ret;
4076         chunk->size = ptp.Param1;
4077         chunk->last = (ptp.Param2 == 0);
4078         chunk->offset = ptp.Param3; //-1 for none
4079         return ret;
4080 }
4081
4082 uint16_t
4083 ptp_chdk_exec_lua(PTPParams* params, char *script, int flags, int *script_id, int *status)
4084 {
4085         uint16_t r;
4086         PTPContainer ptp;
4087
4088         PTP_CNT_INIT(ptp);
4089         ptp.Code=PTP_OC_CHDK;
4090         ptp.Nparam=2;
4091         ptp.Param1=PTP_CHDK_ExecuteScript;
4092         ptp.Param2=PTP_CHDK_SL_LUA | flags;
4093
4094         r = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, strlen(script)+1, (unsigned char**)&script, NULL);
4095
4096         if ( r != PTP_RC_OK ) {
4097                 *script_id = 0;
4098                 *status = 0;
4099                 return r;
4100         } else {
4101                 *script_id = ptp.Param1;
4102                 *status = ptp.Param2;
4103                 //return (*status == PTP_CHDK_S_ERRTYPE_NONE);
4104                 if (*status == PTP_CHDK_S_ERRTYPE_NONE)
4105                         return PTP_RC_OK;
4106                 else
4107                         return r;
4108         }
4109 }
4110
4111 uint16_t
4112 ptp_chdk_get_version(PTPParams* params, int *major, int *minor)
4113 {
4114         uint16_t r;
4115         PTPContainer ptp;
4116
4117         PTP_CNT_INIT(ptp);
4118         ptp.Code=PTP_OC_CHDK;
4119         ptp.Nparam=1;
4120         ptp.Param1=PTP_CHDK_Version;
4121         r=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
4122         if ( r != PTP_RC_OK )
4123                 return r;
4124         *major = ptp.Param1;
4125         *minor = ptp.Param2;
4126         return r;
4127 }
4128
4129 uint16_t
4130 ptp_chdk_get_script_status(PTPParams* params, unsigned *status)
4131 {
4132         uint16_t r;
4133         PTPContainer ptp;
4134
4135         PTP_CNT_INIT(ptp);
4136         ptp.Code=PTP_OC_CHDK;
4137         ptp.Nparam=1;
4138         ptp.Param1=PTP_CHDK_ScriptStatus;
4139         r=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
4140         if ( r != PTP_RC_OK )
4141                 return r;
4142         *status = ptp.Param1;
4143         return r;
4144 }
4145 uint16_t
4146 ptp_chdk_get_script_support(PTPParams* params, unsigned *status)
4147 {
4148         uint16_t r;
4149         PTPContainer ptp;
4150
4151         PTP_CNT_INIT(ptp);
4152         ptp.Code=PTP_OC_CHDK;
4153         ptp.Nparam=1;
4154         ptp.Param1=PTP_CHDK_ScriptSupport;
4155         r=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
4156         if ( r != PTP_RC_OK )
4157                 return r;
4158         *status = ptp.Param1;
4159         return r;
4160 }
4161
4162 uint16_t
4163 ptp_chdk_write_script_msg(PTPParams* params, char *data, unsigned size, int target_script_id, int *status)
4164 {
4165         uint16_t r;
4166         PTPContainer ptp;
4167
4168         // a zero length data phase appears to do bad things, camera stops responding to PTP
4169         if(!size) {
4170                 ptp_error(params,"zero length message not allowed");
4171                 *status = 0;
4172                 return 0;
4173         }
4174         PTP_CNT_INIT(ptp);
4175         ptp.Code=PTP_OC_CHDK;
4176         ptp.Nparam=2;
4177         ptp.Param1=PTP_CHDK_WriteScriptMsg;
4178         ptp.Param2=target_script_id;
4179
4180         r=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, (unsigned char**)&data, NULL);
4181         if ( r != PTP_RC_OK ) {
4182                 *status = 0;
4183                 return r;
4184         }
4185         *status = ptp.Param1;
4186         return r;
4187 }
4188 uint16_t
4189 ptp_chdk_read_script_msg(PTPParams* params, ptp_chdk_script_msg **msg)
4190 {
4191         uint16_t r;
4192         PTPContainer ptp;
4193         unsigned char *data = NULL;
4194
4195         PTP_CNT_INIT(ptp);
4196         ptp.Code=PTP_OC_CHDK;
4197         ptp.Nparam=1;
4198         ptp.Param1=PTP_CHDK_ReadScriptMsg;
4199
4200         *msg = NULL;
4201
4202         /* camera will always send data, otherwise getdata will cause problems */
4203         r=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL);
4204         if ( r != PTP_RC_OK )
4205                 return r;
4206
4207         /* for convenience, always allocate an extra byte and null it*/
4208         *msg = malloc(sizeof(ptp_chdk_script_msg) + ptp.Param4 + 1);
4209         (*msg)->type = ptp.Param1;
4210         (*msg)->subtype = ptp.Param2;
4211         (*msg)->script_id = ptp.Param3;
4212         (*msg)->size = ptp.Param4;
4213         memcpy((*msg)->data,data,(*msg)->size);
4214         (*msg)->data[(*msg)->size] = 0;
4215         free(data);
4216         return r;
4217 }
4218
4219 uint16_t
4220 ptp_chdk_get_live_data(PTPParams* params, unsigned flags, unsigned char **data, unsigned int *data_size) {
4221         uint16_t r;
4222         PTPContainer ptp;
4223         unsigned int real_size = 0;
4224
4225
4226         PTP_CNT_INIT(ptp);
4227         ptp.Code=PTP_OC_CHDK;
4228         ptp.Nparam=2;
4229         ptp.Param1=PTP_CHDK_GetDisplayData;
4230         ptp.Param2=flags;
4231
4232         *data = NULL;
4233         *data_size = 0;
4234
4235         r = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, &real_size);
4236         if ( r != PTP_RC_OK )
4237                 return r;
4238         *data_size = ptp.Param1;
4239         return r;
4240 }
4241
4242 uint16_t
4243 ptp_chdk_call_function(PTPParams* params, int *args, int size, int *ret)
4244 {
4245         uint16_t r;
4246         PTPContainer ptp;
4247
4248         PTP_CNT_INIT(ptp);
4249         ptp.Code=PTP_OC_CHDK;
4250         ptp.Nparam=1;
4251         ptp.Param1=PTP_CHDK_CallFunction;
4252         r=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size*sizeof(int), (unsigned char **) &args, NULL);
4253         if ( r != PTP_RC_OK )
4254                 return r;
4255         if ( ret )
4256                 *ret = ptp.Param1;
4257         return r;
4258 }
4259
4260
4261
4262
4263 /**
4264  * Android MTP Extensions
4265  */
4266
4267 /**
4268  * ptp_android_getpartialobject64:
4269  * params:      PTPParams*
4270  *              handle                  - Object handle
4271  *              offset                  - Offset into object
4272  *              maxbytes                - Maximum of bytes to read
4273  *              object                  - pointer to data area
4274  *              len                     - pointer to returned length
4275  *
4276  * Get object 'handle' from device and store the data in newly
4277  * allocated 'object'. Start from offset and read at most maxbytes.
4278  *
4279  * This is a 64bit offset version of the standard GetPartialObject.
4280  *
4281  * Return values: Some PTP_RC_* code.
4282  **/
4283 uint16_t
4284 ptp_android_getpartialobject64 (PTPParams* params, uint32_t handle, uint64_t offset,
4285                                 uint32_t maxbytes, unsigned char** object,
4286                                 uint32_t *len)
4287 {
4288         PTPContainer ptp;
4289
4290         PTP_CNT_INIT(ptp);
4291         ptp.Code=PTP_OC_ANDROID_GetPartialObject64;
4292         ptp.Param1=handle;
4293         ptp.Param2=offset & 0xFFFFFFFF;
4294         ptp.Param3=offset >> 32;
4295         ptp.Param4=maxbytes;
4296         ptp.Nparam=4;
4297         *len=0;
4298         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len);
4299 }
4300
4301 uint16_t
4302 ptp_android_sendpartialobject (PTPParams* params, uint32_t handle, uint64_t offset,
4303                                 unsigned char* object,  uint32_t len)
4304 {
4305         uint32_t err;
4306         PTPContainer ptp;
4307
4308         PTP_CNT_INIT(ptp);
4309         ptp.Code=PTP_OC_ANDROID_SendPartialObject;
4310         ptp.Param1=handle;
4311         ptp.Param2=offset & 0xFFFFFFFF;
4312         ptp.Param3=offset >> 32;
4313         ptp.Param4=len;
4314         ptp.Nparam=4;
4315
4316         /*
4317          * MtpServer.cpp is buggy: it uses write() without offset
4318          * rather than pwrite to send the data for data coming with
4319          * the header packet
4320          */
4321         params->split_header_data = 1;
4322         err=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, len, &object, NULL);
4323         params->split_header_data = 0;
4324
4325         return err;
4326 }
4327
4328
4329 /* Non PTP protocol functions */
4330 /* devinfo testing functions */
4331
4332 int
4333 ptp_event_issupported(PTPParams* params, uint16_t event)
4334 {
4335         unsigned int i=0;
4336
4337         for (;i<params->deviceinfo.EventsSupported_len;i++) {
4338                 if (params->deviceinfo.EventsSupported[i]==event)
4339                         return 1;
4340         }
4341         return 0;
4342 }
4343
4344
4345 int
4346 ptp_property_issupported(PTPParams* params, uint16_t property)
4347 {
4348         unsigned int i;
4349
4350         for (i=0;i<params->deviceinfo.DevicePropertiesSupported_len;i++)
4351                 if (params->deviceinfo.DevicePropertiesSupported[i]==property)
4352                         return 1;
4353         return 0;
4354 }
4355
4356 void
4357 ptp_free_objectinfo (PTPObjectInfo *oi)
4358 {
4359         if (!oi) return;
4360         free (oi->Filename); oi->Filename = NULL;
4361         free (oi->Keywords); oi->Keywords = NULL;
4362 }
4363
4364 void
4365 ptp_free_object (PTPObject *ob)
4366 {
4367         unsigned int i;
4368         if (!ob) return;
4369
4370         ptp_free_objectinfo (&ob->oi);
4371         for (i=0;i<ob->nrofmtpprops;i++)
4372                 ptp_destroy_object_prop(&ob->mtpprops[i]);
4373         ob->flags = 0;
4374 }
4375
4376 const char *
4377 ptp_strerror(uint16_t error) {
4378
4379         int i;
4380         /* PTP error descriptions */
4381         static struct {
4382                 short n;
4383                 const char *txt;
4384         } ptp_errors[] = {
4385         {PTP_RC_Undefined,              N_("PTP: Undefined Error")},
4386         {PTP_RC_OK,                     N_("PTP: OK!")},
4387         {PTP_RC_GeneralError,           N_("PTP: General Error")},
4388         {PTP_RC_SessionNotOpen,         N_("PTP: Session Not Open")},
4389         {PTP_RC_InvalidTransactionID,   N_("PTP: Invalid Transaction ID")},
4390         {PTP_RC_OperationNotSupported,  N_("PTP: Operation Not Supported")},
4391         {PTP_RC_ParameterNotSupported,  N_("PTP: Parameter Not Supported")},
4392         {PTP_RC_IncompleteTransfer,     N_("PTP: Incomplete Transfer")},
4393         {PTP_RC_InvalidStorageId,       N_("PTP: Invalid Storage ID")},
4394         {PTP_RC_InvalidObjectHandle,    N_("PTP: Invalid Object Handle")},
4395         {PTP_RC_DevicePropNotSupported, N_("PTP: Device Prop Not Supported")},
4396         {PTP_RC_InvalidObjectFormatCode, N_("PTP: Invalid Object Format Code")},
4397         {PTP_RC_StoreFull,              N_("PTP: Store Full")},
4398         {PTP_RC_ObjectWriteProtected,   N_("PTP: Object Write Protected")},
4399         {PTP_RC_StoreReadOnly,          N_("PTP: Store Read Only")},
4400         {PTP_RC_AccessDenied,           N_("PTP: Access Denied")},
4401         {PTP_RC_NoThumbnailPresent,     N_("PTP: No Thumbnail Present")},
4402         {PTP_RC_SelfTestFailed,         N_("PTP: Self Test Failed")},
4403         {PTP_RC_PartialDeletion,        N_("PTP: Partial Deletion")},
4404         {PTP_RC_StoreNotAvailable,      N_("PTP: Store Not Available")},
4405         {PTP_RC_SpecificationByFormatUnsupported,
4406                                 N_("PTP: Specification By Format Unsupported")},
4407         {PTP_RC_NoValidObjectInfo,      N_("PTP: No Valid Object Info")},
4408         {PTP_RC_InvalidCodeFormat,      N_("PTP: Invalid Code Format")},
4409         {PTP_RC_UnknownVendorCode,      N_("PTP: Unknown Vendor Code")},
4410         {PTP_RC_CaptureAlreadyTerminated,
4411                                         N_("PTP: Capture Already Terminated")},
4412         {PTP_RC_DeviceBusy,             N_("PTP: Device Busy")},
4413         {PTP_RC_InvalidParentObject,    N_("PTP: Invalid Parent Object")},
4414         {PTP_RC_InvalidDevicePropFormat, N_("PTP: Invalid Device Prop Format")},
4415         {PTP_RC_InvalidDevicePropValue, N_("PTP: Invalid Device Prop Value")},
4416         {PTP_RC_InvalidParameter,       N_("PTP: Invalid Parameter")},
4417         {PTP_RC_SessionAlreadyOpened,   N_("PTP: Session Already Opened")},
4418         {PTP_RC_TransactionCanceled,    N_("PTP: Transaction Canceled")},
4419         {PTP_RC_SpecificationOfDestinationUnsupported,
4420                         N_("PTP: Specification Of Destination Unsupported")},
4421         {PTP_RC_EK_FilenameRequired,    N_("PTP: EK Filename Required")},
4422         {PTP_RC_EK_FilenameConflicts,   N_("PTP: EK Filename Conflicts")},
4423         {PTP_RC_EK_FilenameInvalid,     N_("PTP: EK Filename Invalid")},
4424
4425         {PTP_ERROR_IO,            N_("PTP: I/O error")},
4426         {PTP_ERROR_BADPARAM,      N_("PTP: Error: bad parameter")},
4427         {PTP_ERROR_DATA_EXPECTED, N_("PTP: Protocol error, data expected")},
4428         {PTP_ERROR_RESP_EXPECTED, N_("PTP: Protocol error, response expected")},
4429         {0, NULL}
4430 };
4431
4432         for (i=0; ptp_errors[i].txt!=NULL; i++)
4433                 if (ptp_errors[i].n == error)
4434                         return ptp_errors[i].txt;
4435         return NULL;
4436 }
4437
4438 void
4439 ptp_perror(PTPParams* params, uint16_t error) {
4440         const char *txt = ptp_strerror(error);
4441         if (txt != NULL)
4442                 ptp_error(params, txt);
4443 }
4444
4445 const char*
4446 ptp_get_property_description(PTPParams* params, uint16_t dpc)
4447 {
4448         int i;
4449         /* Device Property descriptions */
4450         struct {
4451                 uint16_t dpc;
4452                 const char *txt;
4453         } ptp_device_properties[] = {
4454                 {PTP_DPC_Undefined,             N_("Undefined PTP Property")},
4455                 {PTP_DPC_BatteryLevel,          N_("Battery Level")},
4456                 {PTP_DPC_FunctionalMode,        N_("Functional Mode")},
4457                 {PTP_DPC_ImageSize,             N_("Image Size")},
4458                 {PTP_DPC_CompressionSetting,    N_("Compression Setting")},
4459                 {PTP_DPC_WhiteBalance,          N_("White Balance")},
4460                 {PTP_DPC_RGBGain,               N_("RGB Gain")},
4461                 {PTP_DPC_FNumber,               N_("F-Number")},
4462                 {PTP_DPC_FocalLength,           N_("Focal Length")},
4463                 {PTP_DPC_FocusDistance,         N_("Focus Distance")},
4464                 {PTP_DPC_FocusMode,             N_("Focus Mode")},
4465                 {PTP_DPC_ExposureMeteringMode,  N_("Exposure Metering Mode")},
4466                 {PTP_DPC_FlashMode,             N_("Flash Mode")},
4467                 {PTP_DPC_ExposureTime,          N_("Exposure Time")},
4468                 {PTP_DPC_ExposureProgramMode,   N_("Exposure Program Mode")},
4469                 {PTP_DPC_ExposureIndex,
4470                                         N_("Exposure Index (film speed ISO)")},
4471                 {PTP_DPC_ExposureBiasCompensation,
4472                                         N_("Exposure Bias Compensation")},
4473                 {PTP_DPC_DateTime,              N_("Date & Time")},
4474                 {PTP_DPC_CaptureDelay,          N_("Pre-Capture Delay")},
4475                 {PTP_DPC_StillCaptureMode,      N_("Still Capture Mode")},
4476                 {PTP_DPC_Contrast,              N_("Contrast")},
4477                 {PTP_DPC_Sharpness,             N_("Sharpness")},
4478                 {PTP_DPC_DigitalZoom,           N_("Digital Zoom")},
4479                 {PTP_DPC_EffectMode,            N_("Effect Mode")},
4480                 {PTP_DPC_BurstNumber,           N_("Burst Number")},
4481                 {PTP_DPC_BurstInterval,         N_("Burst Interval")},
4482                 {PTP_DPC_TimelapseNumber,       N_("Timelapse Number")},
4483                 {PTP_DPC_TimelapseInterval,     N_("Timelapse Interval")},
4484                 {PTP_DPC_FocusMeteringMode,     N_("Focus Metering Mode")},
4485                 {PTP_DPC_UploadURL,             N_("Upload URL")},
4486                 {PTP_DPC_Artist,                N_("Artist")},
4487                 {PTP_DPC_CopyrightInfo,         N_("Copyright Info")},
4488                 {0,NULL}
4489         };
4490         struct {
4491                 uint16_t dpc;
4492                 const char *txt;
4493         } ptp_device_properties_EK[] = {
4494                 {PTP_DPC_EK_ColorTemperature,   N_("Color Temperature")},
4495                 {PTP_DPC_EK_DateTimeStampFormat,
4496                                         N_("Date Time Stamp Format")},
4497                 {PTP_DPC_EK_BeepMode,           N_("Beep Mode")},
4498                 {PTP_DPC_EK_VideoOut,           N_("Video Out")},
4499                 {PTP_DPC_EK_PowerSaving,        N_("Power Saving")},
4500                 {PTP_DPC_EK_UI_Language,        N_("UI Language")},
4501                 {0,NULL}
4502         };
4503
4504         struct {
4505                 uint16_t dpc;
4506                 const char *txt;
4507         } ptp_device_properties_Canon[] = {
4508                 {PTP_DPC_CANON_BeepMode,        N_("Beep Mode")},
4509                 {PTP_DPC_CANON_BatteryKind,     N_("Battery Type")},
4510                 {PTP_DPC_CANON_BatteryStatus,   N_("Battery Mode")},
4511                 {PTP_DPC_CANON_UILockType,      N_("UILockType")},
4512                 {PTP_DPC_CANON_CameraMode,      N_("Camera Mode")},
4513                 {PTP_DPC_CANON_ImageQuality,    N_("Image Quality")},
4514                 {PTP_DPC_CANON_FullViewFileFormat,      N_("Full View File Format")},
4515                 {PTP_DPC_CANON_ImageSize,       N_("Image Size")},
4516                 {PTP_DPC_CANON_SelfTime,        N_("Self Time")},
4517                 {PTP_DPC_CANON_FlashMode,       N_("Flash Mode")},
4518                 {PTP_DPC_CANON_Beep,            N_("Beep")},
4519                 {PTP_DPC_CANON_ShootingMode,    N_("Shooting Mode")},
4520                 {PTP_DPC_CANON_ImageMode,       N_("Image Mode")},
4521                 {PTP_DPC_CANON_DriveMode,       N_("Drive Mode")},
4522                 {PTP_DPC_CANON_EZoom,           N_("Zoom")},
4523                 {PTP_DPC_CANON_MeteringMode,    N_("Metering Mode")},
4524                 {PTP_DPC_CANON_AFDistance,      N_("AF Distance")},
4525                 {PTP_DPC_CANON_FocusingPoint,   N_("Focusing Point")},
4526                 {PTP_DPC_CANON_WhiteBalance,    N_("White Balance")},
4527                 {PTP_DPC_CANON_SlowShutterSetting,      N_("Slow Shutter Setting")},
4528                 {PTP_DPC_CANON_AFMode,          N_("AF Mode")},
4529                 {PTP_DPC_CANON_ImageStabilization,              N_("Image Stabilization")},
4530                 {PTP_DPC_CANON_Contrast,        N_("Contrast")},
4531                 {PTP_DPC_CANON_ColorGain,       N_("Color Gain")},
4532                 {PTP_DPC_CANON_Sharpness,       N_("Sharpness")},
4533                 {PTP_DPC_CANON_Sensitivity,     N_("Sensitivity")},
4534                 {PTP_DPC_CANON_ParameterSet,    N_("Parameter Set")},
4535                 {PTP_DPC_CANON_ISOSpeed,        N_("ISO Speed")},
4536                 {PTP_DPC_CANON_Aperture,        N_("Aperture")},
4537                 {PTP_DPC_CANON_ShutterSpeed,    N_("Shutter Speed")},
4538                 {PTP_DPC_CANON_ExpCompensation, N_("Exposure Compensation")},
4539                 {PTP_DPC_CANON_FlashCompensation,       N_("Flash Compensation")},
4540                 {PTP_DPC_CANON_AEBExposureCompensation, N_("AEB Exposure Compensation")},
4541                 {PTP_DPC_CANON_AvOpen,          N_("Av Open")},
4542                 {PTP_DPC_CANON_AvMax,           N_("Av Max")},
4543                 {PTP_DPC_CANON_FocalLength,     N_("Focal Length")},
4544                 {PTP_DPC_CANON_FocalLengthTele, N_("Focal Length Tele")},
4545                 {PTP_DPC_CANON_FocalLengthWide, N_("Focal Length Wide")},
4546                 {PTP_DPC_CANON_FocalLengthDenominator,  N_("Focal Length Denominator")},
4547                 {PTP_DPC_CANON_CaptureTransferMode,     N_("Capture Transfer Mode")},
4548                 {PTP_DPC_CANON_Zoom,            N_("Zoom")},
4549                 {PTP_DPC_CANON_NamePrefix,      N_("Name Prefix")},
4550                 {PTP_DPC_CANON_SizeQualityMode, N_("Size Quality Mode")},
4551                 {PTP_DPC_CANON_SupportedThumbSize,      N_("Supported Thumb Size")},
4552                 {PTP_DPC_CANON_SizeOfOutputDataFromCamera,      N_("Size of Output Data from Camera")},
4553                 {PTP_DPC_CANON_SizeOfInputDataToCamera,         N_("Size of Input Data to Camera")},
4554                 {PTP_DPC_CANON_RemoteAPIVersion,N_("Remote API Version")},
4555                 {PTP_DPC_CANON_FirmwareVersion, N_("Firmware Version")},
4556                 {PTP_DPC_CANON_CameraModel,     N_("Camera Model")},
4557                 {PTP_DPC_CANON_CameraOwner,     N_("Camera Owner")},
4558                 {PTP_DPC_CANON_UnixTime,        N_("UNIX Time")},
4559                 {PTP_DPC_CANON_CameraBodyID,    N_("Camera Body ID")},
4560                 {PTP_DPC_CANON_CameraOutput,    N_("Camera Output")},
4561                 {PTP_DPC_CANON_DispAv,          N_("Disp Av")},
4562                 {PTP_DPC_CANON_AvOpenApex,      N_("Av Open Apex")},
4563                 {PTP_DPC_CANON_DZoomMagnification,      N_("Digital Zoom Magnification")},
4564                 {PTP_DPC_CANON_MlSpotPos,       N_("Ml Spot Position")},
4565                 {PTP_DPC_CANON_DispAvMax,       N_("Disp Av Max")},
4566                 {PTP_DPC_CANON_AvMaxApex,       N_("Av Max Apex")},
4567                 {PTP_DPC_CANON_EZoomStartPosition,      N_("EZoom Start Position")},
4568                 {PTP_DPC_CANON_FocalLengthOfTele,       N_("Focal Length Tele")},
4569                 {PTP_DPC_CANON_EZoomSizeOfTele, N_("EZoom Size of Tele")},
4570                 {PTP_DPC_CANON_PhotoEffect,     N_("Photo Effect")},
4571                 {PTP_DPC_CANON_AssistLight,     N_("Assist Light")},
4572                 {PTP_DPC_CANON_FlashQuantityCount,      N_("Flash Quantity Count")},
4573                 {PTP_DPC_CANON_RotationAngle,   N_("Rotation Angle")},
4574                 {PTP_DPC_CANON_RotationScene,   N_("Rotation Scene")},
4575                 {PTP_DPC_CANON_EventEmulateMode,N_("Event Emulate Mode")},
4576                 {PTP_DPC_CANON_DPOFVersion,     N_("DPOF Version")},
4577                 {PTP_DPC_CANON_TypeOfSupportedSlideShow,        N_("Type of Slideshow")},
4578                 {PTP_DPC_CANON_AverageFilesizes,N_("Average Filesizes")},
4579                 {PTP_DPC_CANON_ModelID,         N_("Model ID")},
4580                 {0,NULL}
4581         };
4582
4583         struct {
4584                 uint16_t dpc;
4585                 const char *txt;
4586         } ptp_device_properties_Nikon[] = {
4587                 {PTP_DPC_NIKON_ShootingBank,                    /* 0xD010 */
4588                  N_("Shooting Bank")},
4589                 {PTP_DPC_NIKON_ShootingBankNameA,               /* 0xD011 */
4590                  N_("Shooting Bank Name A")},
4591                 {PTP_DPC_NIKON_ShootingBankNameB,               /* 0xD012 */
4592                  N_("Shooting Bank Name B")},
4593                 {PTP_DPC_NIKON_ShootingBankNameC,               /* 0xD013 */
4594                  N_("Shooting Bank Name C")},
4595                 {PTP_DPC_NIKON_ShootingBankNameD,               /* 0xD014 */
4596                  N_("Shooting Bank Name D")},
4597                 {PTP_DPC_NIKON_ResetBank0,                      /* 0xD015 */
4598                  N_("Reset Bank 0")},
4599                 {PTP_DPC_NIKON_RawCompression,                  /* 0xD016 */
4600                  N_("Raw Compression")},
4601                 {PTP_DPC_NIKON_WhiteBalanceAutoBias,            /* 0xD017 */
4602                  N_("Auto White Balance Bias")},
4603                 {PTP_DPC_NIKON_WhiteBalanceTungstenBias,        /* 0xD018 */
4604                  N_("Tungsten White Balance Bias")},
4605                 {PTP_DPC_NIKON_WhiteBalanceFluorescentBias,     /* 0xD019 */
4606                  N_("Fluorescent White Balance Bias")},
4607                 {PTP_DPC_NIKON_WhiteBalanceDaylightBias,        /* 0xD01a */
4608                  N_("Daylight White Balance Bias")},
4609                 {PTP_DPC_NIKON_WhiteBalanceFlashBias,           /* 0xD01b */
4610                  N_("Flash White Balance Bias")},
4611                 {PTP_DPC_NIKON_WhiteBalanceCloudyBias,          /* 0xD01c */
4612                  N_("Cloudy White Balance Bias")},
4613                 {PTP_DPC_NIKON_WhiteBalanceShadeBias,           /* 0xD01d */
4614                  N_("Shady White Balance Bias")},
4615                 {PTP_DPC_NIKON_WhiteBalanceColorTemperature,    /* 0xD01e */
4616                  N_("White Balance Colour Temperature")},
4617                 {PTP_DPC_NIKON_WhiteBalancePresetNo,            /* 0xD01f */
4618                  N_("White Balance Preset Number")},
4619                 {PTP_DPC_NIKON_WhiteBalancePresetName0,         /* 0xD020 */
4620                  N_("White Balance Preset Name 0")},
4621                 {PTP_DPC_NIKON_WhiteBalancePresetName1,         /* 0xD021 */
4622                  N_("White Balance Preset Name 1")},
4623                 {PTP_DPC_NIKON_WhiteBalancePresetName2,         /* 0xD022 */
4624                  N_("White Balance Preset Name 2")},
4625                 {PTP_DPC_NIKON_WhiteBalancePresetName3,         /* 0xD023 */
4626                  N_("White Balance Preset Name 3")},
4627                 {PTP_DPC_NIKON_WhiteBalancePresetName4,         /* 0xD024 */
4628                  N_("White Balance Preset Name 4")},
4629                 {PTP_DPC_NIKON_WhiteBalancePresetVal0,          /* 0xD025 */
4630                  N_("White Balance Preset Value 0")},
4631                 {PTP_DPC_NIKON_WhiteBalancePresetVal1,          /* 0xD026 */
4632                  N_("White Balance Preset Value 1")},
4633                 {PTP_DPC_NIKON_WhiteBalancePresetVal2,          /* 0xD027 */
4634                  N_("White Balance Preset Value 2")},
4635                 {PTP_DPC_NIKON_WhiteBalancePresetVal3,          /* 0xD028 */
4636                  N_("White Balance Preset Value 3")},
4637                 {PTP_DPC_NIKON_WhiteBalancePresetVal4,          /* 0xD029 */
4638                  N_("White Balance Preset Value 4")},
4639                 {PTP_DPC_NIKON_ImageSharpening,                 /* 0xD02a */
4640                  N_("Sharpening")},
4641                 {PTP_DPC_NIKON_ToneCompensation,                /* 0xD02b */
4642                  N_("Tone Compensation")},
4643                 {PTP_DPC_NIKON_ColorModel,                      /* 0xD02c */
4644                  N_("Color Model")},
4645                 {PTP_DPC_NIKON_HueAdjustment,                   /* 0xD02d */
4646                  N_("Hue Adjustment")},
4647                 {PTP_DPC_NIKON_NonCPULensDataFocalLength,       /* 0xD02e */
4648                  N_("Lens Focal Length (Non CPU)")},
4649                 {PTP_DPC_NIKON_NonCPULensDataMaximumAperture,   /* 0xD02f */
4650                  N_("Lens Maximum Aperture (Non CPU)")},
4651                 {PTP_DPC_NIKON_ShootingMode,                    /* 0xD030 */
4652                  N_("Shooting Mode")},
4653                 {PTP_DPC_NIKON_JPEG_Compression_Policy,         /* 0xD031 */
4654                  N_("JPEG Compression Policy")},
4655                 {PTP_DPC_NIKON_ColorSpace,                      /* 0xD032 */
4656                  N_("Color Space")},
4657                 {PTP_DPC_NIKON_AutoDXCrop,                      /* 0xD033 */
4658                  N_("Auto DX Crop")},
4659                 {PTP_DPC_NIKON_FlickerReduction,                /* 0xD034 */
4660                  N_("Flicker Reduction")},
4661                 {PTP_DPC_NIKON_RemoteMode,                      /* 0xD035 */
4662                  N_("Remote Mode")},
4663                 {PTP_DPC_NIKON_VideoMode,                       /* 0xD036 */
4664                  N_("Video Mode")},
4665                 {PTP_DPC_NIKON_EffectMode,                      /* 0xD037 */
4666                  N_("Effect Mode")},
4667                 {PTP_DPC_NIKON_CSMMenuBankSelect,               /* 0xD040 */
4668                  "PTP_DPC_NIKON_CSMMenuBankSelect"},
4669                 {PTP_DPC_NIKON_MenuBankNameA,                   /* 0xD041 */
4670                  N_("Menu Bank Name A")},
4671                 {PTP_DPC_NIKON_MenuBankNameB,                   /* 0xD042 */
4672                  N_("Menu Bank Name B")},
4673                 {PTP_DPC_NIKON_MenuBankNameC,                   /* 0xD043 */
4674                  N_("Menu Bank Name C")},
4675                 {PTP_DPC_NIKON_MenuBankNameD,                   /* 0xD044 */
4676                  N_("Menu Bank Name D")},
4677                 {PTP_DPC_NIKON_ResetBank,                       /* 0xD045 */
4678                  N_("Reset Menu Bank")},
4679                 {PTP_DPC_NIKON_A1AFCModePriority,               /* 0xD048 */
4680                  "PTP_DPC_NIKON_A1AFCModePriority"},
4681                 {PTP_DPC_NIKON_A2AFSModePriority,               /* 0xD049 */
4682                  "PTP_DPC_NIKON_A2AFSModePriority"},
4683                 {PTP_DPC_NIKON_A3GroupDynamicAF,                /* 0xD04a */
4684                  "PTP_DPC_NIKON_A3GroupDynamicAF"},
4685                 {PTP_DPC_NIKON_A4AFActivation,                  /* 0xD04b */
4686                  "PTP_DPC_NIKON_A4AFActivation"},
4687                 {PTP_DPC_NIKON_FocusAreaIllumManualFocus,       /* 0xD04c */
4688                  "PTP_DPC_NIKON_FocusAreaIllumManualFocus"},
4689                 {PTP_DPC_NIKON_FocusAreaIllumContinuous,        /* 0xD04d */
4690                  "PTP_DPC_NIKON_FocusAreaIllumContinuous"},
4691                 {PTP_DPC_NIKON_FocusAreaIllumWhenSelected,      /* 0xD04e */
4692                  "PTP_DPC_NIKON_FocusAreaIllumWhenSelected"},
4693                 {PTP_DPC_NIKON_FocusAreaWrap,                   /* 0xD04f */
4694                  N_("Focus Area Wrap")},
4695                 {PTP_DPC_NIKON_VerticalAFON,                    /* 0xD050 */
4696                  N_("Vertical AF On")},
4697                 {PTP_DPC_NIKON_AFLockOn,                        /* 0xD051 */
4698                  N_("AF Lock On")},
4699                 {PTP_DPC_NIKON_FocusAreaZone,                   /* 0xD052 */
4700                  N_("Focus Area Zone")},
4701                 {PTP_DPC_NIKON_EnableCopyright,                 /* 0xD053 */
4702                  N_("Enable Copyright")},
4703                 {PTP_DPC_NIKON_ISOAuto,                         /* 0xD054 */
4704                  N_("Auto ISO")},
4705                 {PTP_DPC_NIKON_EVISOStep,                       /* 0xD055 */
4706                  N_("Exposure ISO Step")},
4707                 {PTP_DPC_NIKON_EVStep,                          /* 0xD056 */
4708                  N_("Exposure Step")},
4709                 {PTP_DPC_NIKON_EVStepExposureComp,              /* 0xD057 */
4710                  N_("Exposure Compensation (EV)")},
4711                 {PTP_DPC_NIKON_ExposureCompensation,            /* 0xD058 */
4712                  N_("Exposure Compensation")},
4713                 {PTP_DPC_NIKON_CenterWeightArea,                /* 0xD059 */
4714                  N_("Centre Weight Area")},
4715                 {PTP_DPC_NIKON_ExposureBaseMatrix,              /* 0xD05A */
4716                  N_("Exposure Base Matrix")},
4717                 {PTP_DPC_NIKON_ExposureBaseCenter,              /* 0xD05B */
4718                  N_("Exposure Base Center")},
4719                 {PTP_DPC_NIKON_ExposureBaseSpot,                /* 0xD05C */
4720                  N_("Exposure Base Spot")},
4721                 {PTP_DPC_NIKON_LiveViewAFArea,                  /* 0xD05D */
4722                  N_("Live View AF Area")},
4723                 {PTP_DPC_NIKON_AELockMode,                      /* 0xD05E */
4724                  N_("Exposure Lock")},
4725                 {PTP_DPC_NIKON_AELAFLMode,                      /* 0xD05F */
4726                  N_("Focus Lock")},
4727                 {PTP_DPC_NIKON_LiveViewAFFocus,                 /* 0xD061 */
4728                  N_("Live View AF Focus")},
4729                 {PTP_DPC_NIKON_MeterOff,                        /* 0xD062 */
4730                  N_("Auto Meter Off Time")},
4731                 {PTP_DPC_NIKON_SelfTimer,                       /* 0xD063 */
4732                  N_("Self Timer Delay")},
4733                 {PTP_DPC_NIKON_MonitorOff,                      /* 0xD064 */
4734                  N_("LCD Off Time")},
4735                 {PTP_DPC_NIKON_ImgConfTime,                     /* 0xD065 */
4736                  N_("Img Conf Time")},
4737                 {PTP_DPC_NIKON_AutoOffTimers,                   /* 0xD066 */
4738                  N_("Auto Off Timers")},
4739                 {PTP_DPC_NIKON_AngleLevel,                      /* 0xD067 */
4740                  N_("Angle Level")},
4741                 {PTP_DPC_NIKON_D1ShootingSpeed,                 /* 0xD068 */
4742                  N_("Shooting Speed")},
4743                 {PTP_DPC_NIKON_D2MaximumShots,                  /* 0xD069 */
4744                  N_("Maximum Shots")},
4745                 {PTP_DPC_NIKON_ExposureDelayMode,               /* 0xD06A */
4746                  N_("Exposure delay mode")},
4747                 {PTP_DPC_NIKON_LongExposureNoiseReduction,      /* 0xD06B */
4748                  N_("Long Exposure Noise Reduction")},
4749                 {PTP_DPC_NIKON_FileNumberSequence,              /* 0xD06C */
4750                  N_("File Number Sequencing")},
4751                 {PTP_DPC_NIKON_ControlPanelFinderRearControl,   /* 0xD06D */
4752                  "PTP_DPC_NIKON_ControlPanelFinderRearControl"},
4753                 {PTP_DPC_NIKON_ControlPanelFinderViewfinder,    /* 0xD06E */
4754                  "PTP_DPC_NIKON_ControlPanelFinderViewfinder"},
4755                 {PTP_DPC_NIKON_D7Illumination,                  /* 0xD06F */
4756                  N_("LCD Illumination")},
4757                 {PTP_DPC_NIKON_NrHighISO,                       /* 0xD070 */
4758                  N_("High ISO noise reduction")},
4759                 {PTP_DPC_NIKON_SHSET_CH_GUID_DISP,              /* 0xD071 */
4760                  N_("On screen tips")},
4761                 {PTP_DPC_NIKON_ArtistName,                      /* 0xD072 */
4762                  N_("Artist Name")},
4763                 {PTP_DPC_NIKON_CopyrightInfo,                   /* 0xD073 */
4764                  N_("Copyright Information")},
4765                 {PTP_DPC_NIKON_FlashSyncSpeed,                  /* 0xD074 */
4766                  N_("Flash Sync. Speed")},
4767                 {PTP_DPC_NIKON_FlashShutterSpeed,               /* 0xD075 */
4768                  N_("Flash Shutter Speed")},
4769                 {PTP_DPC_NIKON_E3AAFlashMode,                   /* 0xD076 */
4770                  N_("Flash Mode")},
4771                 {PTP_DPC_NIKON_E4ModelingFlash,                 /* 0xD077 */
4772                  N_("Modeling Flash")},
4773                 {PTP_DPC_NIKON_BracketSet,                      /* 0xD078 */
4774                  N_("Bracket Set")},
4775                 {PTP_DPC_NIKON_E6ManualModeBracketing,          /* 0xD079 */
4776                  N_("Manual Mode Bracketing")},
4777                 {PTP_DPC_NIKON_BracketOrder,                    /* 0xD07A */
4778                  N_("Bracket Order")},
4779                 {PTP_DPC_NIKON_E8AutoBracketSelection,          /* 0xD07B */
4780                  N_("Auto Bracket Selection")},
4781                 {PTP_DPC_NIKON_BracketingSet, N_("NIKON Auto Bracketing Set")}, /* 0xD07C */
4782                 {PTP_DPC_NIKON_F1CenterButtonShootingMode,      /* 0xD080 */
4783                  N_("Center Button Shooting Mode")},
4784                 {PTP_DPC_NIKON_CenterButtonPlaybackMode,        /* 0xD081 */
4785                  N_("Center Button Playback Mode")},
4786                 {PTP_DPC_NIKON_F2Multiselector,                 /* 0xD082 */
4787                  N_("Multiselector")},
4788                 {PTP_DPC_NIKON_F3PhotoInfoPlayback,             /* 0xD083 */
4789                  N_("Photo Info. Playback")},
4790                 {PTP_DPC_NIKON_F4AssignFuncButton,              /* 0xD084 */
4791                  N_("Assign Func. Button")},
4792                 {PTP_DPC_NIKON_F5CustomizeCommDials,            /* 0xD085 */
4793                  N_("Customise Command Dials")},
4794                 {PTP_DPC_NIKON_ReverseCommandDial,              /* 0xD086 */
4795                  N_("Reverse Command Dial")},
4796                 {PTP_DPC_NIKON_ApertureSetting,                 /* 0xD087 */
4797                  N_("Aperture Setting")},
4798                 {PTP_DPC_NIKON_MenusAndPlayback,                /* 0xD088 */
4799                  N_("Menus and Playback")},
4800                 {PTP_DPC_NIKON_F6ButtonsAndDials,               /* 0xD089 */
4801                  N_("Buttons and Dials")},
4802                 {PTP_DPC_NIKON_NoCFCard,                        /* 0xD08A */
4803                  N_("No CF Card Release")},
4804                 {PTP_DPC_NIKON_CenterButtonZoomRatio,           /* 0xD08B */
4805                  N_("Center Button Zoom Ratio")},
4806                 {PTP_DPC_NIKON_FunctionButton2,                 /* 0xD08C */
4807                  N_("Function Button 2")},
4808                 {PTP_DPC_NIKON_AFAreaPoint,                     /* 0xD08D */
4809                  N_("AF Area Point")},
4810                 {PTP_DPC_NIKON_NormalAFOn,                      /* 0xD08E */
4811                  N_("Normal AF On")},
4812                 {PTP_DPC_NIKON_CleanImageSensor,                /* 0xD08F */
4813                  N_("Clean Image Sensor")},
4814                 {PTP_DPC_NIKON_ImageCommentString,              /* 0xD090 */
4815                  N_("Image Comment String")},
4816                 {PTP_DPC_NIKON_ImageCommentEnable,              /* 0xD091 */
4817                  N_("Image Comment Enable")},
4818                 {PTP_DPC_NIKON_ImageRotation,                   /* 0xD092 */
4819                  N_("Image Rotation")},
4820                 {PTP_DPC_NIKON_ManualSetLensNo,                 /* 0xD093 */
4821                  N_("Manual Set Lens Number")},
4822                 {PTP_DPC_NIKON_MovScreenSize,                   /* 0xD0A0 */
4823                  N_("Movie Screen Size")},
4824                 {PTP_DPC_NIKON_MovVoice,                        /* 0xD0A1 */
4825                  N_("Movie Voice")},
4826                 {PTP_DPC_NIKON_MovMicrophone,                   /* 0xD0A2 */
4827                  N_("Movie Microphone")},
4828                 {PTP_DPC_NIKON_MovFileSlot,                     /* 0xD0A3 */
4829                  N_("Movie Card Slot")},
4830                 {PTP_DPC_NIKON_ManualMovieSetting,              /* 0xD0A6 */
4831                  N_("Manual Movie Setting")},
4832                 {PTP_DPC_NIKON_MonitorOffDelay,                 /* 0xD0B3 */
4833                  N_("Monitor Off Delay")},
4834                 {PTP_DPC_NIKON_Bracketing,                      /* 0xD0C0 */
4835                  N_("Bracketing Enable")},
4836                 {PTP_DPC_NIKON_AutoExposureBracketStep,         /* 0xD0C1 */
4837                  N_("Exposure Bracketing Step")},
4838                 {PTP_DPC_NIKON_AutoExposureBracketProgram,      /* 0xD0C2 */
4839                  N_("Exposure Bracketing Program")},
4840                 {PTP_DPC_NIKON_AutoExposureBracketCount,        /* 0xD0C3 */
4841                  N_("Auto Exposure Bracket Count")},
4842                 {PTP_DPC_NIKON_WhiteBalanceBracketStep, N_("White Balance Bracket Step")}, /* 0xD0C4 */
4843                 {PTP_DPC_NIKON_WhiteBalanceBracketProgram, N_("White Balance Bracket Program")}, /* 0xD0C5 */
4844                 {PTP_DPC_NIKON_LensID,                          /* 0xD0E0 */
4845                  N_("Lens ID")},
4846                 {PTP_DPC_NIKON_LensSort,                        /* 0xD0E1 */
4847                  N_("Lens Sort")},
4848                 {PTP_DPC_NIKON_LensType,                        /* 0xD0E2 */
4849                  N_("Lens Type")},
4850                 {PTP_DPC_NIKON_FocalLengthMin,                  /* 0xD0E3 */
4851                  N_("Min. Focal Length")},
4852                 {PTP_DPC_NIKON_FocalLengthMax,                  /* 0xD0E4 */
4853                  N_("Max. Focal Length")},
4854                 {PTP_DPC_NIKON_MaxApAtMinFocalLength,           /* 0xD0E5 */
4855                  N_("Max. Aperture at Min. Focal Length")},
4856                 {PTP_DPC_NIKON_MaxApAtMaxFocalLength,           /* 0xD0E6 */
4857                  N_("Max. Aperture at Max. Focal Length")},
4858                 {PTP_DPC_NIKON_FinderISODisp,                   /* 0xD0F0 */
4859                  N_("Finder ISO Display")},
4860                 {PTP_DPC_NIKON_AutoOffPhoto,                    /* 0xD0F2 */
4861                  N_("Auto Off Photo")},
4862                 {PTP_DPC_NIKON_AutoOffMenu,                     /* 0xD0F3 */
4863                  N_("Auto Off Menu")},
4864                 {PTP_DPC_NIKON_AutoOffInfo,                     /* 0xD0F4 */
4865                  N_("Auto Off Info")},
4866                 {PTP_DPC_NIKON_SelfTimerShootNum,               /* 0xD0F5 */
4867                  N_("Self Timer Shot Number")},
4868                 {PTP_DPC_NIKON_VignetteCtrl,                    /* 0xD0F7 */
4869                  N_("Vignette Control")},
4870                 {PTP_DPC_NIKON_AutoDistortionControl,           /* 0xD0F8 */
4871                  N_("Auto Distortion Control")},
4872                 {PTP_DPC_NIKON_SceneMode,                       /* 0xD0F9 */
4873                  N_("Scene Mode")},
4874                 {PTP_DPC_NIKON_ExposureTime,                    /* 0xD100 */
4875                  N_("Nikon Exposure Time")},
4876                 {PTP_DPC_NIKON_ACPower, N_("AC Power")},        /* 0xD101 */
4877                 {PTP_DPC_NIKON_WarningStatus, N_("Warning Status")},/* 0xD102 */
4878                 {PTP_DPC_NIKON_MaximumShots,                    /* 0xD103 */
4879                  N_("Maximum Shots")},
4880                 {PTP_DPC_NIKON_AFLockStatus, N_("AF Locked")},/* 0xD104 */
4881                 {PTP_DPC_NIKON_AELockStatus, N_("AE Locked")},/* 0xD105 */
4882                 {PTP_DPC_NIKON_FVLockStatus, N_("FV Locked")},/* 0xD106 */
4883                 {PTP_DPC_NIKON_AutofocusLCDTopMode2,            /* 0xD107 */
4884                  N_("AF LCD Top Mode 2")},
4885                 {PTP_DPC_NIKON_AutofocusArea,                   /* 0xD108 */
4886                  N_("Active AF Sensor")},
4887                 {PTP_DPC_NIKON_FlexibleProgram,                 /* 0xD109 */
4888                  N_("Flexible Program")},
4889                 {PTP_DPC_NIKON_LightMeter,                      /* 0xD10A */
4890                  N_("Exposure Meter")},
4891                 {PTP_DPC_NIKON_RecordingMedia,                  /* 0xD10B */
4892                  N_("Recording Media")},
4893                 {PTP_DPC_NIKON_USBSpeed,                        /* 0xD10C */
4894                  N_("USB Speed")},
4895                 {PTP_DPC_NIKON_CCDNumber,                       /* 0xD10D */
4896                  N_("CCD Serial Number")},
4897                 {PTP_DPC_NIKON_CameraOrientation,               /* 0xD10E */
4898                  N_("Camera Orientation")},
4899                 {PTP_DPC_NIKON_GroupPtnType,                    /* 0xD10F */
4900                  N_("Group PTN Type")},
4901                 {PTP_DPC_NIKON_FNumberLock,                     /* 0xD110 */
4902                  N_("FNumber Lock")},
4903                 {PTP_DPC_NIKON_ExposureApertureLock,            /* 0xD111 */
4904                  N_("Exposure Aperture Lock")},
4905                 {PTP_DPC_NIKON_TVLockSetting,                   /* 0xD112 */
4906                  N_("TV Lock Setting")},
4907                 {PTP_DPC_NIKON_AVLockSetting,                   /* 0xD113 */
4908                  N_("AV Lock Setting")},
4909                 {PTP_DPC_NIKON_IllumSetting,                    /* 0xD114 */
4910                  N_("Illum Setting")},
4911                 {PTP_DPC_NIKON_FocusPointBright,                /* 0xD115 */
4912                  N_("Focus Point Bright")},
4913                 {PTP_DPC_NIKON_ExternalFlashAttached,           /* 0xD120 */
4914                  N_("External Flash Attached")},
4915                 {PTP_DPC_NIKON_ExternalFlashStatus,             /* 0xD121 */
4916                  N_("External Flash Status")},
4917                 {PTP_DPC_NIKON_ExternalFlashSort,               /* 0xD122 */
4918                  N_("External Flash Sort")},
4919                 {PTP_DPC_NIKON_ExternalFlashMode,               /* 0xD123 */
4920                  N_("External Flash Mode")},
4921                 {PTP_DPC_NIKON_ExternalFlashCompensation,       /* 0xD124 */
4922                  N_("External Flash Compensation")},
4923                 {PTP_DPC_NIKON_NewExternalFlashMode,            /* 0xD125 */
4924                  N_("External Flash Mode")},
4925                 {PTP_DPC_NIKON_FlashExposureCompensation,       /* 0xD126 */
4926                  N_("Flash Exposure Compensation")},
4927                 {PTP_DPC_NIKON_HDRMode,                         /* 0xD130 */
4928                  N_("HDR Mode")},
4929                 {PTP_DPC_NIKON_HDRHighDynamic,                  /* 0xD131 */
4930                  N_("HDR High Dynamic")},
4931                 {PTP_DPC_NIKON_HDRSmoothing,                    /* 0xD132 */
4932                  N_("HDR Smoothing")},
4933                 {PTP_DPC_NIKON_OptimizeImage,                   /* 0xD140 */
4934                  N_("Optimize Image")},
4935                 {PTP_DPC_NIKON_Saturation,                      /* 0xD142 */
4936                  N_("Saturation")},
4937                 {PTP_DPC_NIKON_BW_FillerEffect,                 /* 0xD143 */
4938                  N_("BW Filler Effect")},
4939                 {PTP_DPC_NIKON_BW_Sharpness,                    /* 0xD144 */
4940                  N_("BW Sharpness")},
4941                 {PTP_DPC_NIKON_BW_Contrast,                     /* 0xD145 */
4942                  N_("BW Contrast")},
4943                 {PTP_DPC_NIKON_BW_Setting_Type,                 /* 0xD146 */
4944                  N_("BW Setting Type")},
4945                 {PTP_DPC_NIKON_Slot2SaveMode,                   /* 0xD148 */
4946                  N_("Slot 2 Save Mode")},
4947                 {PTP_DPC_NIKON_RawBitMode,                      /* 0xD149 */
4948                  N_("Raw Bit Mode")},
4949                 {PTP_DPC_NIKON_ActiveDLighting,                 /* 0xD14E */
4950                  N_("Active D-Lighting")},
4951                 {PTP_DPC_NIKON_FlourescentType,                 /* 0xD14F */
4952                  N_("Flourescent Type")},
4953                 {PTP_DPC_NIKON_TuneColourTemperature,           /* 0xD150 */
4954                  N_("Tune Colour Temperature")},
4955                 {PTP_DPC_NIKON_TunePreset0,                     /* 0xD151 */
4956                  N_("Tune Preset 0")},
4957                 {PTP_DPC_NIKON_TunePreset1,                     /* 0xD152 */
4958                  N_("Tune Preset 1")},
4959                 {PTP_DPC_NIKON_TunePreset2,                     /* 0xD153 */
4960                  N_("Tune Preset 2")},
4961                 {PTP_DPC_NIKON_TunePreset3,                     /* 0xD154 */
4962                  N_("Tune Preset 3")},
4963                 {PTP_DPC_NIKON_TunePreset4,                     /* 0xD155 */
4964                  N_("Tune Preset 4")},
4965                 {PTP_DPC_NIKON_BeepOff,                         /* 0xD160 */
4966                  N_("AF Beep Mode")},
4967                 {PTP_DPC_NIKON_AutofocusMode,                   /* 0xD161 */
4968                  N_("Autofocus Mode")},
4969                 {PTP_DPC_NIKON_AFAssist,                        /* 0xD163 */
4970                  N_("AF Assist Lamp")},
4971                 {PTP_DPC_NIKON_PADVPMode,                       /* 0xD164 */
4972                  N_("Auto ISO P/A/DVP Setting")},
4973                 {PTP_DPC_NIKON_ImageReview,                     /* 0xD165 */
4974                  N_("Image Review")},
4975                 {PTP_DPC_NIKON_AFAreaIllumination,              /* 0xD166 */
4976                  N_("AF Area Illumination")},
4977                 {PTP_DPC_NIKON_FlashMode,                       /* 0xD167 */
4978                  N_("Flash Mode")},
4979                 {PTP_DPC_NIKON_FlashCommanderMode,              /* 0xD168 */
4980                  N_("Flash Commander Mode")},
4981                 {PTP_DPC_NIKON_FlashSign,                       /* 0xD169 */
4982                  N_("Flash Sign")},
4983                 {PTP_DPC_NIKON_ISO_Auto,                        /* 0xD16A */
4984                  N_("ISO Auto")},
4985                 {PTP_DPC_NIKON_RemoteTimeout,                   /* 0xD16B */
4986                  N_("Remote Timeout")},
4987                 {PTP_DPC_NIKON_GridDisplay,                     /* 0xD16C */
4988                  N_("Viewfinder Grid Display")},
4989                 {PTP_DPC_NIKON_FlashModeManualPower,            /* 0xD16D */
4990                  N_("Flash Mode Manual Power")},
4991                 {PTP_DPC_NIKON_FlashModeCommanderPower,         /* 0xD16E */
4992                  N_("Flash Mode Commander Power")},
4993                 {PTP_DPC_NIKON_AutoFP,                          /* 0xD16F */
4994                  N_("Auto FP")},
4995                 {PTP_DPC_NIKON_CSMMenu,                         /* 0xD180 */
4996                  N_("CSM Menu")},
4997                 {PTP_DPC_NIKON_WarningDisplay,                  /* 0xD181 */
4998                  N_("Warning Display")},
4999                 {PTP_DPC_NIKON_BatteryCellKind,                 /* 0xD182 */
5000                  N_("Battery Cell Kind")},
5001                 {PTP_DPC_NIKON_ISOAutoHiLimit,                  /* 0xD183 */
5002                  N_("ISO Auto High Limit")},
5003                 {PTP_DPC_NIKON_DynamicAFArea,                   /* 0xD184 */
5004                  N_("Dynamic AF Area")},
5005                 {PTP_DPC_NIKON_ContinuousSpeedHigh,             /* 0xD186 */
5006                  N_("Continuous Speed High")},
5007                 {PTP_DPC_NIKON_InfoDispSetting,                 /* 0xD187 */
5008                  N_("Info Disp Setting")},
5009                 {PTP_DPC_NIKON_PreviewButton,                   /* 0xD189 */
5010                  N_("Preview Button")},
5011                 {PTP_DPC_NIKON_PreviewButton2,                  /* 0xD18A */
5012                  N_("Preview Button 2")},
5013                 {PTP_DPC_NIKON_AEAFLockButton2,                 /* 0xD18B */
5014                  N_("AEAF Lock Button 2")},
5015                 {PTP_DPC_NIKON_IndicatorDisp,                   /* 0xD18D */
5016                  N_("Indicator Display")},
5017                 {PTP_DPC_NIKON_CellKindPriority,                /* 0xD18E */
5018                  N_("Cell Kind Priority")},
5019                 {PTP_DPC_NIKON_BracketingFramesAndSteps,        /* 0xD190 */
5020                  N_("Bracketing Frames and Steps")},
5021                 {PTP_DPC_NIKON_LiveViewMode,                    /* 0xD1A0 */
5022                  N_("Live View Mode")},
5023                 {PTP_DPC_NIKON_LiveViewDriveMode,               /* 0xD1A1 */
5024                  N_("Live View Drive Mode")},
5025                 {PTP_DPC_NIKON_LiveViewStatus,                  /* 0xD1A2 */
5026                  N_("Live View Status")},
5027                 {PTP_DPC_NIKON_LiveViewImageZoomRatio,          /* 0xD1A3 */
5028                  N_("Live View Image Zoom Ratio")},
5029                 {PTP_DPC_NIKON_LiveViewProhibitCondition,       /* 0xD1A4 */
5030                  N_("Live View Prohibit Condition")},
5031                 {PTP_DPC_NIKON_ExposureDisplayStatus,           /* 0xD1B0 */
5032                  N_("Exposure Display Status")},
5033                 {PTP_DPC_NIKON_ExposureIndicateStatus,          /* 0xD1B1 */
5034                  N_("Exposure Indicate Status")},
5035                 {PTP_DPC_NIKON_InfoDispErrStatus,               /* 0xD1B2 */
5036                  N_("Info Display Error Status")},
5037                 {PTP_DPC_NIKON_ExposureIndicateLightup,         /* 0xD1B3 */
5038                  N_("Exposure Indicate Lightup")},
5039                 {PTP_DPC_NIKON_FlashOpen,                       /* 0xD1C0 */
5040                  N_("Flash Open")},
5041                 {PTP_DPC_NIKON_FlashCharged,                    /* 0xD1C1 */
5042                  N_("Flash Charged")},
5043                 {PTP_DPC_NIKON_FlashMRepeatValue,               /* 0xD1D0 */
5044                  N_("Flash MRepeat Value")},
5045                 {PTP_DPC_NIKON_FlashMRepeatCount,               /* 0xD1D1 */
5046                  N_("Flash MRepeat Count")},
5047                 {PTP_DPC_NIKON_FlashMRepeatInterval,            /* 0xD1D2 */
5048                  N_("Flash MRepeat Interval")},
5049                 {PTP_DPC_NIKON_FlashCommandChannel,             /* 0xD1D3 */
5050                  N_("Flash Command Channel")},
5051                 {PTP_DPC_NIKON_FlashCommandSelfMode,            /* 0xD1D4 */
5052                  N_("Flash Command Self Mode")},
5053                 {PTP_DPC_NIKON_FlashCommandSelfCompensation,    /* 0xD1D5 */
5054                  N_("Flash Command Self Compensation")},
5055                 {PTP_DPC_NIKON_FlashCommandSelfValue,           /* 0xD1D6 */
5056                  N_("Flash Command Self Value")},
5057                 {PTP_DPC_NIKON_FlashCommandAMode,               /* 0xD1D7 */
5058                  N_("Flash Command A Mode")},
5059                 {PTP_DPC_NIKON_FlashCommandACompensation,       /* 0xD1D8 */
5060                  N_("Flash Command A Compensation")},
5061                 {PTP_DPC_NIKON_FlashCommandAValue,              /* 0xD1D9 */
5062                  N_("Flash Command A Value")},
5063                 {PTP_DPC_NIKON_FlashCommandBMode,               /* 0xD1DA */
5064                  N_("Flash Command B Mode")},
5065                 {PTP_DPC_NIKON_FlashCommandBCompensation,       /* 0xD1DB */
5066                  N_("Flash Command B Compensation")},
5067                 {PTP_DPC_NIKON_FlashCommandBValue,              /* 0xD1DC */
5068                  N_("Flash Command B Value")},
5069                 {PTP_DPC_NIKON_ActivePicCtrlItem,               /* 0xD200 */
5070                  N_("Active Pic Ctrl Item")},
5071                 {PTP_DPC_NIKON_ChangePicCtrlItem,               /* 0xD201 */
5072                  N_("Change Pic Ctrl Item")},
5073                 {0,NULL}
5074         };
5075         struct {
5076                 uint16_t dpc;
5077                 const char *txt;
5078         } ptp_device_properties_MTP[] = {
5079                 {PTP_DPC_MTP_SecureTime,        N_("Secure Time")},             /* D101 */
5080                 {PTP_DPC_MTP_DeviceCertificate, N_("Device Certificate")},      /* D102 */
5081                 {PTP_DPC_MTP_RevocationInfo,    N_("Revocation Info")},         /* D103 */
5082                 {PTP_DPC_MTP_SynchronizationPartner,                            /* D401 */
5083                  N_("Synchronization Partner")},
5084                 {PTP_DPC_MTP_DeviceFriendlyName,                                /* D402 */
5085                  N_("Friendly Device Name")},
5086                 {PTP_DPC_MTP_VolumeLevel,       N_("Volume Level")},            /* D403 */
5087                 {PTP_DPC_MTP_DeviceIcon,        N_("Device Icon")},             /* D405 */
5088                 {PTP_DPC_MTP_SessionInitiatorInfo,      N_("Session Initiator Info")},/* D406 */
5089                 {PTP_DPC_MTP_PerceivedDeviceType,       N_("Perceived Device Type")},/* D407 */
5090                 {PTP_DPC_MTP_PlaybackRate,      N_("Playback Rate")},           /* D410 */
5091                 {PTP_DPC_MTP_PlaybackObject,    N_("Playback Object")},         /* D411 */
5092                 {PTP_DPC_MTP_PlaybackContainerIndex,                            /* D412 */
5093                  N_("Playback Container Index")},
5094                 {PTP_DPC_MTP_PlaybackPosition,  N_("Playback Position")},       /* D413 */
5095                 {PTP_DPC_MTP_PlaysForSureID,    N_("PlaysForSure ID")},         /* D131 (?) */
5096                 {0,NULL}
5097         };
5098         struct {
5099                 uint16_t dpc;
5100                 const char *txt;
5101         } ptp_device_properties_FUJI[] = {
5102                 {PTP_DPC_FUJI_ColorTemperature, N_("Color Temperature")},       /* 0xD017 */
5103                 {PTP_DPC_FUJI_Quality, N_("Quality")},                          /* 0xD018 */
5104                 {PTP_DPC_FUJI_Quality, N_("Release Mode")},                     /* 0xD201 */
5105                 {PTP_DPC_FUJI_Quality, N_("Focus Areas")},                      /* 0xD206 */
5106                 {PTP_DPC_FUJI_Quality, N_("AE Lock")},                          /* 0xD213 */
5107                 {PTP_DPC_FUJI_Quality, N_("Aperture")},                         /* 0xD218 */
5108                 {PTP_DPC_FUJI_Quality, N_("Shutter Speed")},                    /* 0xD219 */
5109                 {0,NULL}
5110         };
5111
5112         for (i=0; ptp_device_properties[i].txt!=NULL; i++)
5113                 if (ptp_device_properties[i].dpc==dpc)
5114                         return (ptp_device_properties[i].txt);
5115
5116         if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_MICROSOFT
5117             || params->deviceinfo.VendorExtensionID==PTP_VENDOR_MTP)
5118                 for (i=0; ptp_device_properties_MTP[i].txt!=NULL; i++)
5119                         if (ptp_device_properties_MTP[i].dpc==dpc)
5120                                 return (ptp_device_properties_MTP[i].txt);
5121
5122         if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_EASTMAN_KODAK)
5123                 for (i=0; ptp_device_properties_EK[i].txt!=NULL; i++)
5124                         if (ptp_device_properties_EK[i].dpc==dpc)
5125                                 return (ptp_device_properties_EK[i].txt);
5126
5127         if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_CANON)
5128                 for (i=0; ptp_device_properties_Canon[i].txt!=NULL; i++)
5129                         if (ptp_device_properties_Canon[i].dpc==dpc)
5130                                 return (ptp_device_properties_Canon[i].txt);
5131
5132         if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_NIKON)
5133                 for (i=0; ptp_device_properties_Nikon[i].txt!=NULL; i++)
5134                         if (ptp_device_properties_Nikon[i].dpc==dpc)
5135                                 return (ptp_device_properties_Nikon[i].txt);
5136
5137         if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_FUJI)
5138                 for (i=0; ptp_device_properties_FUJI[i].txt!=NULL; i++)
5139                         if (ptp_device_properties_FUJI[i].dpc==dpc)
5140                                 return (ptp_device_properties_FUJI[i].txt);
5141
5142         return NULL;
5143 }
5144
5145 static int64_t
5146 _value_to_num(PTPPropertyValue *data, uint16_t dt) {
5147         if (dt == PTP_DTC_STR) {
5148                 if (!data->str)
5149                         return 0;
5150                 return atol(data->str);
5151         }
5152         if (dt & PTP_DTC_ARRAY_MASK) {
5153                 return 0;
5154         } else {
5155                 switch (dt) {
5156                 case PTP_DTC_UNDEF:
5157                         return 0;
5158                 case PTP_DTC_INT8:
5159                         return data->i8;
5160                 case PTP_DTC_UINT8:
5161                         return data->u8;
5162                 case PTP_DTC_INT16:
5163                         return data->i16;
5164                 case PTP_DTC_UINT16:
5165                         return data->u16;
5166                 case PTP_DTC_INT32:
5167                         return data->i32;
5168                 case PTP_DTC_UINT32:
5169                         return data->u32;
5170         /*
5171                 PTP_DTC_INT64
5172                 PTP_DTC_UINT64
5173                 PTP_DTC_INT128
5174                 PTP_DTC_UINT128
5175         */
5176                 default:
5177                         return 0;
5178                 }
5179         }
5180
5181         return 0;
5182 }
5183
5184 #define PTP_VAL_BOOL(dpc) {dpc, 0, N_("Off")}, {dpc, 1, N_("On")}
5185 #define PTP_VENDOR_VAL_BOOL(dpc,vendor) {dpc, vendor, 0, N_("Off")}, {dpc, vendor, 1, N_("On")}
5186 #define PTP_VENDOR_VAL_RBOOL(dpc,vendor) {dpc, vendor, 0, N_("On")}, {dpc, vendor, 1, N_("Off")}
5187 #define PTP_VENDOR_VAL_YN(dpc,vendor) {dpc, vendor, 0, N_("No")}, {dpc, vendor, 1, N_("Yes")}
5188
5189 int
5190 ptp_render_property_value(PTPParams* params, uint16_t dpc,
5191                           PTPDevicePropDesc *dpd, unsigned int length, char *out)
5192 {
5193         unsigned int i;
5194         int64_t kval;
5195
5196         struct {
5197                 uint16_t dpc;
5198                 uint16_t vendor;
5199                 double coef;
5200                 double bias;
5201                 const char *format;
5202         } ptp_value_trans[] = {
5203                 {PTP_DPC_BatteryLevel, 0, 1.0, 0.0, "%.0f%%"},          /* 5001 */
5204                 {PTP_DPC_FNumber, 0, 0.01, 0.0, "f/%.2g"},              /* 5007 */
5205                 {PTP_DPC_FocalLength, 0, 0.01, 0.0, "%.0f mm"},         /* 5008 */
5206                 {PTP_DPC_FocusDistance, 0, 0.01, 0.0, "%.0f mm"},       /* 5009 */
5207                 {PTP_DPC_ExposureTime, 0, 0.00001, 0.0, "%.2g sec"},    /* 500D */
5208                 {PTP_DPC_ExposureIndex, 0, 1.0, 0.0, "ISO %.0f"},       /* 500F */
5209                 {PTP_DPC_ExposureBiasCompensation, 0, 0.001, 0.0, N_("%.1f stops")},/* 5010 */
5210                 {PTP_DPC_CaptureDelay, 0, 0.001, 0.0, "%.1fs"},         /* 5012 */
5211                 {PTP_DPC_DigitalZoom, 0, 0.1, 0.0, "%.1f"},             /* 5016 */
5212                 {PTP_DPC_BurstInterval, 0, 0.001, 0.0, "%.1fs"},        /* 5019 */
5213
5214                 /* Nikon device properties */
5215                 {PTP_DPC_NIKON_LightMeter, PTP_VENDOR_NIKON, 0.08333, 0.0, N_("%.1f stops")},/* D10A */
5216                 {PTP_DPC_NIKON_FlashExposureCompensation, PTP_VENDOR_NIKON, 0.16666, 0.0, N_("%.1f stops")}, /* D126 */
5217                 {PTP_DPC_NIKON_CenterWeightArea, PTP_VENDOR_NIKON, 2.0, 6.0, N_("%.0f mm")},/* D059 */
5218                 {PTP_DPC_NIKON_FocalLengthMin, PTP_VENDOR_NIKON, 0.01, 0.0, "%.0f mm"}, /* D0E3 */
5219                 {PTP_DPC_NIKON_FocalLengthMax, PTP_VENDOR_NIKON, 0.01, 0.0, "%.0f mm"}, /* D0E4 */
5220                 {PTP_DPC_NIKON_MaxApAtMinFocalLength, PTP_VENDOR_NIKON, 0.01, 0.0, "f/%.2g"}, /* D0E5 */
5221                 {PTP_DPC_NIKON_MaxApAtMaxFocalLength, PTP_VENDOR_NIKON, 0.01, 0.0, "f/%.2g"}, /* D0E6 */
5222                 {PTP_DPC_NIKON_ExternalFlashCompensation, PTP_VENDOR_NIKON, 1.0/6.0, 0.0,"%.0f"}, /* D124 */
5223                 {PTP_DPC_NIKON_ExposureIndicateStatus, PTP_VENDOR_NIKON, 0.08333, 0.0, N_("%.1f stops")},/* D1B1 - FIXME: check if correct. */
5224                 {PTP_DPC_NIKON_AngleLevel, PTP_VENDOR_NIKON, 1.0/65536, 0.0, "%.1f'"},/* 0xD067 */
5225                 {0, 0, 0.0, 0.0, NULL}
5226         };
5227
5228         struct {
5229                 uint16_t dpc;
5230                 uint16_t vendor;
5231                 int64_t key;
5232                 char *value;
5233         } ptp_value_list[] = {
5234                 {PTP_DPC_CompressionSetting, 0, 0, N_("JPEG Basic")},   /* 5004 */
5235                 {PTP_DPC_CompressionSetting, 0, 1, N_("JPEG Norm")},
5236                 {PTP_DPC_CompressionSetting, 0, 2, N_("JPEG Fine")},
5237                 {PTP_DPC_CompressionSetting, 0, 4, N_("RAW")},
5238                 {PTP_DPC_CompressionSetting, 0, 5, N_("RAW + JPEG Basic")},
5239                 {PTP_DPC_WhiteBalance, 0, 1, N_("Manual")},
5240                 {PTP_DPC_WhiteBalance, 0, 2, N_("Automatic")},          /* 5005 */
5241                 {PTP_DPC_WhiteBalance, 0, 3, N_("One-push Automatic")},
5242                 {PTP_DPC_WhiteBalance, 0, 4, N_("Daylight")},
5243                 {PTP_DPC_WhiteBalance, 0, 5, N_("Fluorescent")},
5244                 {PTP_DPC_WhiteBalance, 0, 6, N_("Incandescent")},
5245                 {PTP_DPC_WhiteBalance, 0, 7, N_("Flash")},
5246                 {PTP_DPC_WhiteBalance, PTP_VENDOR_NIKON, 32784, N_("Cloudy")},
5247                 {PTP_DPC_WhiteBalance, PTP_VENDOR_NIKON, 32785, N_("Shade")},
5248                 {PTP_DPC_WhiteBalance, PTP_VENDOR_NIKON, 32786, N_("Color Temperature")},
5249                 {PTP_DPC_WhiteBalance, PTP_VENDOR_NIKON, 32787, N_("Preset")},
5250                 {PTP_DPC_FocusMode, 0, 1, N_("Manual Focus")},          /* 500A */
5251                 {PTP_DPC_FocusMode, 0, 2, N_("Automatic")},
5252                 {PTP_DPC_FocusMode, 0, 3, N_("Automatic Macro (close-up)")},
5253                 {PTP_DPC_FocusMode, PTP_VENDOR_NIKON, 32784, "AF-S"},
5254                 {PTP_DPC_FocusMode, PTP_VENDOR_NIKON, 32785, "AF-C"},
5255                 {PTP_DPC_FocusMode, PTP_VENDOR_NIKON, 32786, "AF-A"},
5256                 {PTP_DPC_ExposureMeteringMode, 0, 1, N_("Average")},    /* 500B */
5257                 {PTP_DPC_ExposureMeteringMode, 0, 2, N_("Center Weighted Average")},
5258                 {PTP_DPC_ExposureMeteringMode, 0, 3, N_("Multi-spot")},
5259                 {PTP_DPC_ExposureMeteringMode, 0, 4, N_("Center-spot")},
5260                 {PTP_DPC_FlashMode, 0, 0, N_("Undefined")},             /* 500C */
5261                 {PTP_DPC_FlashMode, 0, 1, N_("Automatic flash")},
5262                 {PTP_DPC_FlashMode, 0, 2, N_("Flash off")},
5263                 {PTP_DPC_FlashMode, 0, 3, N_("Fill flash")},
5264                 {PTP_DPC_FlashMode, 0, 4, N_("Automatic Red-eye Reduction")},
5265                 {PTP_DPC_FlashMode, 0, 5, N_("Red-eye fill flash")},
5266                 {PTP_DPC_FlashMode, 0, 6, N_("External sync")},
5267                 {PTP_DPC_FlashMode, PTP_VENDOR_NIKON, 32784, N_("Auto")},
5268                 {PTP_DPC_FlashMode, PTP_VENDOR_NIKON, 32785, N_("Auto Slow Sync")},
5269                 {PTP_DPC_FlashMode, PTP_VENDOR_NIKON, 32786, N_("Rear Curtain Sync + Slow Sync")},
5270                 {PTP_DPC_FlashMode, PTP_VENDOR_NIKON, 32787, N_("Red-eye Reduction + Slow Sync")},
5271                 {PTP_DPC_ExposureProgramMode, 0, 1, "M"},               /* 500E */
5272                 {PTP_DPC_ExposureProgramMode, 0, 3, "A"},
5273                 {PTP_DPC_ExposureProgramMode, 0, 4, "S"},
5274                 {PTP_DPC_ExposureProgramMode, 0, 2, "P"},
5275                 {PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32784, N_("Auto")},
5276                 {PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32785, N_("Portrait")},
5277                 {PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32786, N_("Landscape")},
5278                 {PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32787, N_("Macro")},
5279                 {PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32788, N_("Sports")},
5280                 {PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32790, N_("Night Landscape")},
5281                 {PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32789, N_("Night Portrait")},
5282                 {PTP_DPC_StillCaptureMode, 0, 1, N_("Single Shot")},    /* 5013 */
5283                 {PTP_DPC_StillCaptureMode, 0, 2, N_("Power Wind")},
5284                 {PTP_DPC_StillCaptureMode, 0, 3, N_("Timelapse")},
5285                 {PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32784, N_("Continuous Low Speed")},
5286                 {PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32785, N_("Timer")},
5287                 {PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32787, N_("Remote")},
5288                 {PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32787, N_("Mirror Up")},
5289                 {PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32788, N_("Timer + Remote")},
5290                 {PTP_DPC_FocusMeteringMode, 0, 1, N_("Centre-spot")},   /* 501C */
5291                 {PTP_DPC_FocusMeteringMode, 0, 2, N_("Multi-spot")},
5292                 {PTP_DPC_FocusMeteringMode, PTP_VENDOR_NIKON, 32784, N_("Single Area")},
5293                 {PTP_DPC_FocusMeteringMode, PTP_VENDOR_NIKON, 32785, N_("Closest Subject")},
5294                 {PTP_DPC_FocusMeteringMode, PTP_VENDOR_NIKON, 32786, N_("Group Dynamic")},
5295
5296
5297                 /* Nikon specific device properties */
5298                 {PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 0, N_("Auto")},       /* D02A */
5299                 {PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 1, N_("Normal")},
5300                 {PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 2, N_("Low")},
5301                 {PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 3, N_("Medium Low")},
5302                 {PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 4, N_("Medium high")},
5303                 {PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 5, N_("High")},
5304                 {PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 6, N_("None")},
5305
5306                 {PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 0, N_("Auto")},      /* D02B */
5307                 {PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 1, N_("Normal")},
5308                 {PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 2, N_("Low contrast")},
5309                 {PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 3, N_("Medium Low")},
5310                 {PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 4, N_("Medium High")},
5311                 {PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 5, N_("High control")},
5312                 {PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 6, N_("Custom")},
5313
5314                 {PTP_DPC_NIKON_ColorModel, PTP_VENDOR_NIKON, 0, "sRGB"},                /* D02C */
5315                 {PTP_DPC_NIKON_ColorModel, PTP_VENDOR_NIKON, 1, "AdobeRGB"},
5316                 {PTP_DPC_NIKON_ColorModel, PTP_VENDOR_NIKON, 2, "sRGB"},
5317
5318                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_AutoDXCrop,PTP_VENDOR_NIKON),         /* D033 */
5319
5320                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_FocusAreaWrap,PTP_VENDOR_NIKON),      /* D04F */
5321
5322                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_EnableCopyright,PTP_VENDOR_NIKON),    /* D053 */
5323                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_ISOAuto,PTP_VENDOR_NIKON),            /* D054 */
5324
5325                 /* FIXME! this is not ISO Auto (which is a bool) Perhaps ISO Auto Time?*/
5326                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 0, "1/125"},                  /* D054 */
5327                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 1, "1/60"},
5328                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 2, "1/30"},
5329                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 3, "1/15"},
5330                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 4, "1/8"},
5331                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 5, "1/4"},
5332                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 6, "1/2"},
5333                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 7, "1"},
5334                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 8, "2"},
5335                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 9, "4"},
5336                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 10, "8"},
5337                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 11, "15"},
5338                 {PTP_DPC_NIKON_ISOAuto, PTP_VENDOR_NIKON, 12, "30"},
5339
5340                 {PTP_DPC_NIKON_EVStep, PTP_VENDOR_NIKON, 0, "1/3"},                     /* D056 */
5341                 {PTP_DPC_NIKON_EVStep, PTP_VENDOR_NIKON, 1, "1/2"},
5342
5343                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_ExposureCompensation,PTP_VENDOR_NIKON),/*D058 */
5344                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_AELockMode,PTP_VENDOR_NIKON),         /* D05E */
5345
5346                 {PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 0, N_("AE/AF Lock")},      /* D05F */
5347                 {PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 1, N_("AF Lock only")},
5348                 {PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 2, N_("AE Lock only")},
5349                 {PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 3, N_("AF Lock Hold")},
5350                 {PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 4, N_("AF On")},
5351                 {PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 5, N_("Flash Lock")},
5352
5353                 {PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 0, N_("4 seconds")},         /* D062 */
5354                 {PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 1, N_("6 seconds")},
5355                 {PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 2, N_("8 seconds")},
5356                 {PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 3, N_("16 seconds")},
5357                 {PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 4, N_("30 minutes")},
5358                 {PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 5, N_("30 seconds")},
5359
5360                 {PTP_DPC_NIKON_SelfTimer, PTP_VENDOR_NIKON, 0, N_("2 seconds")},        /* D063 */
5361                 {PTP_DPC_NIKON_SelfTimer, PTP_VENDOR_NIKON, 1, N_("5 seconds")},
5362                 {PTP_DPC_NIKON_SelfTimer, PTP_VENDOR_NIKON, 2, N_("10 seconds")},
5363                 {PTP_DPC_NIKON_SelfTimer, PTP_VENDOR_NIKON, 3, N_("20 seconds")},
5364
5365                 {PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 0, N_("10 seconds")},      /* D064 */
5366                 {PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 1, N_("20 seconds")},
5367                 {PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 2, N_("1 minute")},
5368                 {PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 3, N_("5 minutes")},
5369                 {PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 4, N_("10 minutes")},
5370                 {PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 5, N_("5 seconds")}, /* d80 observed */
5371
5372                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_ExposureDelayMode,PTP_VENDOR_NIKON),  /* D06A */
5373                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_LongExposureNoiseReduction,PTP_VENDOR_NIKON), /* D06B */
5374                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_FileNumberSequence,PTP_VENDOR_NIKON), /* D06C */
5375                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_D7Illumination,PTP_VENDOR_NIKON),     /* D06F */
5376
5377                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_SHSET_CH_GUID_DISP,PTP_VENDOR_NIKON), /* D071 */
5378
5379                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 0, "1/60s"},                /* D075 */
5380                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 1, "1/30s"},
5381                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 2, "1/15s"},
5382                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 3, "1/8s"},
5383                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 4, "1/4s"},
5384                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 5, "1/2s"},
5385                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 6, "1s"},
5386                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 7, "2s"},
5387                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 8, "4s"},
5388                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 9, "8s"},
5389                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 10, "15s"},
5390                 {PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 11, "30s"},
5391
5392                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_E4ModelingFlash,PTP_VENDOR_NIKON),    /* D077 */
5393
5394                 {PTP_DPC_NIKON_BracketSet, PTP_VENDOR_NIKON, 0, N_("AE & Flash")},      /* D078 */
5395                 {PTP_DPC_NIKON_BracketSet, PTP_VENDOR_NIKON, 1, N_("AE only")},
5396                 {PTP_DPC_NIKON_BracketSet, PTP_VENDOR_NIKON, 2, N_("Flash only")},
5397                 {PTP_DPC_NIKON_BracketSet, PTP_VENDOR_NIKON, 3, N_("WB bracketing")},
5398
5399                 {PTP_DPC_NIKON_BracketOrder, PTP_VENDOR_NIKON, 0, N_("MTR > Under")},   /* D07A */
5400                 {PTP_DPC_NIKON_BracketOrder, PTP_VENDOR_NIKON, 1, N_("Under > MTR")},
5401
5402                 {PTP_DPC_NIKON_F1CenterButtonShootingMode, PTP_VENDOR_NIKON, 0, N_("Reset focus point to center")}, /* D080 */
5403                 {PTP_DPC_NIKON_F1CenterButtonShootingMode, PTP_VENDOR_NIKON, 1, N_("Highlight active focus point")},
5404                 {PTP_DPC_NIKON_F1CenterButtonShootingMode, PTP_VENDOR_NIKON, 2, N_("Unused")},
5405
5406                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_F3PhotoInfoPlayback,PTP_VENDOR_NIKON),/* D083 */
5407                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_F5CustomizeCommDials,PTP_VENDOR_NIKON),/* D085 */
5408                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_ReverseCommandDial,PTP_VENDOR_NIKON), /* D086 */
5409                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_F6ButtonsAndDials,PTP_VENDOR_NIKON), /* D089 */
5410                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_NoCFCard,PTP_VENDOR_NIKON),          /* D08A */
5411                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_AFAreaPoint,PTP_VENDOR_NIKON),       /* D08D */
5412
5413                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_ImageCommentEnable,PTP_VENDOR_NIKON), /* D091 */
5414                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_ImageRotation,PTP_VENDOR_NIKON),     /* D092 */
5415
5416                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_MovVoice,PTP_VENDOR_NIKON),          /* D0A1 */
5417
5418                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_Bracketing,PTP_VENDOR_NIKON),         /* D0C0 */
5419
5420                 /* http://www.rottmerhusen.com/objektives/lensid/nikkor.html is complete */
5421                 {PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 0, N_("Unknown")},             /* D0E0 */
5422                 {PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 38, "Sigma 70-300mm 1:4-5.6 D APO Macro"},
5423                 {PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 83, "AF Nikkor 80-200mm 1:2.8 D ED"},
5424                 {PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 118, "AF Nikkor 50mm 1:1.8 D"},
5425                 {PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 127, "AF-S Nikkor 18-70mm 1:3.5-4.5G ED DX"},
5426                 {PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 139, "AF-S Nikkor 18-200mm 1:3.5-5.6 GED DX VR"},
5427                 {PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 147, "AF-S Nikkor 24-70mm 1:2.8G ED DX"},
5428                 {PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 154, "AF-S Nikkor 18-55mm 1:3.5-F5.6G DX VR"},
5429                 {PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 159, "AF-S Nikkor 35mm 1:1.8G DX"},
5430                 {PTP_DPC_NIKON_FinderISODisp, PTP_VENDOR_NIKON, 0, "Show ISO sensitivity"},/* 0xD0F0 */
5431                 {PTP_DPC_NIKON_FinderISODisp, PTP_VENDOR_NIKON, 1, "Show ISO/Easy ISO"},
5432                 {PTP_DPC_NIKON_FinderISODisp, PTP_VENDOR_NIKON, 2, "Show frame count"},
5433
5434                 {PTP_DPC_NIKON_RawCompression, PTP_VENDOR_NIKON, 0, N_("Lossless")},    /* D016 */
5435                 {PTP_DPC_NIKON_RawCompression, PTP_VENDOR_NIKON, 1, N_("Lossy")},
5436
5437                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ACPower,PTP_VENDOR_NIKON),              /* D101 */
5438                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_AFLockStatus,PTP_VENDOR_NIKON),         /* D104 */
5439                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_AELockStatus,PTP_VENDOR_NIKON),         /* D105 */
5440                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_FVLockStatus,PTP_VENDOR_NIKON),         /* D106 */
5441
5442                 {PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 0, N_("Centre")},       /* D108 */
5443                 {PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 1, N_("Top")},
5444                 {PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 2, N_("Bottom")},
5445                 {PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 3, N_("Left")},
5446                 {PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 4, N_("Right")},
5447
5448                 {PTP_DPC_NIKON_RecordingMedia, PTP_VENDOR_NIKON, 0, N_("Card")},        /* D10B */
5449                 {PTP_DPC_NIKON_RecordingMedia, PTP_VENDOR_NIKON, 1, N_("SDRam")},
5450
5451                 {PTP_DPC_NIKON_USBSpeed, PTP_VENDOR_NIKON, 0, N_("USB 1.1")},           /* D10C */
5452                 {PTP_DPC_NIKON_USBSpeed, PTP_VENDOR_NIKON, 1, N_("USB 2.0")},
5453
5454                 {PTP_DPC_NIKON_CameraOrientation, PTP_VENDOR_NIKON, 0, "0'"},           /* D10E */
5455                 {PTP_DPC_NIKON_CameraOrientation, PTP_VENDOR_NIKON, 1, "270'"},
5456                 {PTP_DPC_NIKON_CameraOrientation, PTP_VENDOR_NIKON, 2, "90'"},
5457                 {PTP_DPC_NIKON_CameraOrientation, PTP_VENDOR_NIKON, 3, "180'"},
5458
5459                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_FNumberLock,PTP_VENDOR_NIKON),          /* D110 */
5460                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExposureApertureLock,PTP_VENDOR_NIKON), /* D111 */
5461                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_TVLockSetting,PTP_VENDOR_NIKON),        /* D112 */
5462                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_AVLockSetting,PTP_VENDOR_NIKON),        /* D113 */
5463
5464                 {PTP_DPC_NIKON_IllumSetting,PTP_VENDOR_NIKON,0,N_("LCD Backlight")},    /* D114 */
5465                 {PTP_DPC_NIKON_IllumSetting,PTP_VENDOR_NIKON,1,N_("LCD Backlight and Info Display")},
5466
5467                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExternalFlashAttached,PTP_VENDOR_NIKON),/* D120 */
5468                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExternalFlashStatus,PTP_VENDOR_NIKON),  /* D121 */
5469
5470                 {PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 0, N_("Normal")},       /* D140 */
5471                 {PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 1, N_("Vivid")},
5472                 {PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 2, N_("Sharper")},
5473                 {PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 3, N_("Softer")},
5474                 {PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 4, N_("Direct Print")},
5475                 {PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 5, N_("Portrait")},
5476                 {PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 6, N_("Landscape")},
5477                 {PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 7, N_("Custom")},
5478
5479                 {PTP_DPC_NIKON_Saturation, PTP_VENDOR_NIKON, 0, N_("Normal")},          /* D142 */
5480                 {PTP_DPC_NIKON_Saturation, PTP_VENDOR_NIKON, 1, N_("Moderate")},
5481                 {PTP_DPC_NIKON_Saturation, PTP_VENDOR_NIKON, 2, N_("Enhanced")},
5482
5483                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_BeepOff,PTP_VENDOR_NIKON),           /* D160 */
5484
5485                 {PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 0, N_("AF-S")},         /* D161 */
5486                 {PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 1, N_("AF-C")},
5487                 {PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 2, N_("AF-A")},
5488                 {PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 3, N_("MF (fixed)")},
5489                 {PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 4, N_("MF (selection)")},
5490
5491                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_AFAssist,PTP_VENDOR_NIKON),          /* D163 */
5492
5493                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 0,  "1/125"},               /* D164 */
5494                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 1,  "1/60"},
5495                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 2,  "1/30"},
5496                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 3,  "1/15"},
5497                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 4,  "1/8"},
5498                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 5,  "1/4"},
5499                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 6,  "1/2"},
5500                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 7,  "1"},
5501                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 8,  "2"},
5502                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 9,  "4"},
5503                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 10, "8"},
5504                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 11, "15"},
5505                 {PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 12, "30"},
5506
5507                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_ImageReview,PTP_VENDOR_NIKON),       /* D165 */
5508
5509                 {PTP_DPC_NIKON_AFAreaIllumination, PTP_VENDOR_NIKON, 0, N_("Auto")},    /* D166 */
5510                 {PTP_DPC_NIKON_AFAreaIllumination, PTP_VENDOR_NIKON, 1, N_("Off")},
5511                 {PTP_DPC_NIKON_AFAreaIllumination, PTP_VENDOR_NIKON, 2, N_("On")},
5512
5513                 {PTP_DPC_NIKON_FlashMode, PTP_VENDOR_NIKON, 0, "iTTL"},                 /* D167 */
5514                 {PTP_DPC_NIKON_FlashMode, PTP_VENDOR_NIKON, 1, N_("Manual")},
5515                 {PTP_DPC_NIKON_FlashMode, PTP_VENDOR_NIKON, 2, N_("Commander")},
5516
5517                 {PTP_DPC_NIKON_FlashCommanderMode, PTP_VENDOR_NIKON, 0, N_("TTL")},     /* D168 */
5518                 {PTP_DPC_NIKON_FlashCommanderMode, PTP_VENDOR_NIKON, 1, N_("Auto Aperture")},
5519                 {PTP_DPC_NIKON_FlashCommanderMode, PTP_VENDOR_NIKON, 2, N_("Full Manual")},
5520
5521                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_FlashSign,PTP_VENDOR_NIKON),         /* D169 */
5522
5523                 {PTP_DPC_NIKON_RemoteTimeout, PTP_VENDOR_NIKON, 0, N_("1 min")},        /* D16B */
5524                 {PTP_DPC_NIKON_RemoteTimeout, PTP_VENDOR_NIKON, 1, N_("5 mins")},
5525                 {PTP_DPC_NIKON_RemoteTimeout, PTP_VENDOR_NIKON, 2, N_("10 mins")},
5526                 {PTP_DPC_NIKON_RemoteTimeout, PTP_VENDOR_NIKON, 3, N_("15 mins")},
5527
5528                 PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_GridDisplay,PTP_VENDOR_NIKON),        /* D16C */
5529
5530                 {PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 0, N_("Full")},  /* D16D */
5531                 {PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 1, "1/2"},
5532                 {PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 2, "1/4"},
5533                 {PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 3, "1/8"},
5534                 {PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 4, "1/16"},
5535
5536                 {PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 0, N_("Full")},/* D16E */
5537                 {PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 1, "1/2"},
5538                 {PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 2, "1/4"},
5539                 {PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 3, "1/8"},
5540                 {PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 4, "1/16"},
5541                 {PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 5, "1/32"},
5542                 {PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 6, "1/64"},
5543                 {PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 7, "1/128"},
5544
5545                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_CSMMenu,PTP_VENDOR_NIKON),              /* D180 */
5546                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_WarningDisplay,PTP_VENDOR_NIKON),       /* D181 */
5547
5548                 {PTP_DPC_NIKON_BatteryCellKind, PTP_VENDOR_NIKON, 0, "LR6 (AA alkaline)"},/* D182 */
5549                 {PTP_DPC_NIKON_BatteryCellKind, PTP_VENDOR_NIKON, 1, "HR6 (AA Ni-Mh)"},
5550                 {PTP_DPC_NIKON_BatteryCellKind, PTP_VENDOR_NIKON, 2, "FR6 (AA Lithium)"},
5551                 {PTP_DPC_NIKON_BatteryCellKind, PTP_VENDOR_NIKON, 3, "ZR6 (AA Ni-Mn)"},
5552
5553                 {PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 0, "400"},             /* D183 */
5554                 {PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 1, "800"},
5555                 {PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 2, "1600"},
5556                 {PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 3, "3200"},
5557                 {PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 4, "Hi 1"},
5558                 {PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 5, "Hi 2"},
5559
5560                 {PTP_DPC_NIKON_InfoDispSetting, PTP_VENDOR_NIKON, 0, N_("Auto")},       /* 0xD187 */
5561                 {PTP_DPC_NIKON_InfoDispSetting, PTP_VENDOR_NIKON, 1, N_("Dark on light")},
5562                 {PTP_DPC_NIKON_InfoDispSetting, PTP_VENDOR_NIKON, 2, N_("Light on dark")},
5563
5564                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_IndicatorDisp,PTP_VENDOR_NIKON),        /* D18D */
5565
5566                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_LiveViewStatus,PTP_VENDOR_NIKON),       /* D1A2 */
5567
5568                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExposureDisplayStatus,PTP_VENDOR_NIKON),/* D1B0 */
5569                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_InfoDispErrStatus,PTP_VENDOR_NIKON),    /* D1B2 */
5570                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExposureIndicateLightup,PTP_VENDOR_NIKON),/* D1B3 */
5571
5572                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_FlashOpen,PTP_VENDOR_NIKON),            /* D1C0 */
5573                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_FlashCharged,PTP_VENDOR_NIKON),         /* D1C1 */
5574
5575                 PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ManualMovieSetting,PTP_VENDOR_NIKON),   /* 0xD0A6 */
5576
5577                 {PTP_DPC_NIKON_FlickerReduction, PTP_VENDOR_NIKON, 0, "50Hz"},          /* 0xD034 */
5578                 {PTP_DPC_NIKON_FlickerReduction, PTP_VENDOR_NIKON, 1, "60Hz"},
5579
5580                 {PTP_DPC_NIKON_RemoteMode, PTP_VENDOR_NIKON, 0, N_("Delayed Remote")},  /* 0xD035 */
5581                 {PTP_DPC_NIKON_RemoteMode, PTP_VENDOR_NIKON, 1, N_("Quick Response")},  /* 0xD035 */
5582                 {PTP_DPC_NIKON_RemoteMode, PTP_VENDOR_NIKON, 2, N_("Remote Mirror Up")},/* 0xD035 */
5583
5584                 {PTP_DPC_NIKON_MonitorOffDelay, PTP_VENDOR_NIKON, 0, "5min"},   /* 0xD0b3 */
5585                 {PTP_DPC_NIKON_MonitorOffDelay, PTP_VENDOR_NIKON, 1, "10min"},  /* 0xD0b3 */
5586                 {PTP_DPC_NIKON_MonitorOffDelay, PTP_VENDOR_NIKON, 2, "15min"},  /* 0xD0b3 */
5587                 {PTP_DPC_NIKON_MonitorOffDelay, PTP_VENDOR_NIKON, 3, "20min"},  /* 0xD0b3 */
5588                 {PTP_DPC_NIKON_MonitorOffDelay, PTP_VENDOR_NIKON, 4, "30min"},  /* 0xD0b3 */
5589
5590
5591                 /* Canon stuff */
5592                 PTP_VENDOR_VAL_BOOL(PTP_DPC_CANON_AssistLight,PTP_VENDOR_CANON),
5593                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_CANON_RotationScene,PTP_VENDOR_CANON),
5594                 PTP_VENDOR_VAL_RBOOL(PTP_DPC_CANON_BeepMode,PTP_VENDOR_CANON),
5595                 PTP_VENDOR_VAL_BOOL(PTP_DPC_CANON_Beep,PTP_VENDOR_CANON),
5596
5597                 {PTP_DPC_CANON_RotationAngle, PTP_VENDOR_CANON, 0, "0'"},
5598                 {PTP_DPC_CANON_RotationAngle, PTP_VENDOR_CANON, 3, "270'"},
5599                 {PTP_DPC_CANON_RotationAngle, PTP_VENDOR_CANON, 1, "90'"},
5600
5601                 {PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 0, N_("Unknown")},
5602                 {PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 1, N_("AC")},
5603                 {PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 2, N_("Lithium Ion")},
5604                 {PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 3, N_("Nickel hydride")},
5605                 {PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 4, N_("Nickel cadmium")},
5606                 {PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 5, N_("Alkalium manganese")},
5607
5608                 {PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 0, N_("Undefined")},
5609                 {PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 1, N_("Normal")},
5610                 {PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 2, N_("Warning Level 1")},
5611                 {PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 3, N_("Emergency")},
5612                 {PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 4, N_("Warning Level 0")},
5613
5614                 {PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 0, N_("Undefined")},
5615                 {PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 1, N_("Economy")},
5616                 {PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 2, N_("Normal")},
5617                 {PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 3, N_("Fine")},
5618                 {PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 4, N_("Lossless")},
5619                 {PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 5, N_("SuperFine")},
5620
5621                 {PTP_DPC_CANON_FullViewFileFormat, PTP_VENDOR_CANON, 0, N_("Undefined")},
5622                 {PTP_DPC_CANON_FullViewFileFormat, PTP_VENDOR_CANON, 1, N_("JPEG")},
5623                 {PTP_DPC_CANON_FullViewFileFormat, PTP_VENDOR_CANON, 2, N_("CRW")},
5624
5625                 {PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 0, N_("Large")},
5626                 {PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 1, N_("Medium 1")},
5627                 {PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 2, N_("Small")},
5628                 {PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 3, N_("Medium 2")},
5629                 {PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 7, N_("Medium 3")},
5630
5631                 {PTP_DPC_CANON_SelfTime, PTP_VENDOR_CANON, 0,   N_("Not used")},
5632                 {PTP_DPC_CANON_SelfTime, PTP_VENDOR_CANON, 100, N_("10 seconds")},
5633                 {PTP_DPC_CANON_SelfTime, PTP_VENDOR_CANON, 20,  N_("2 seconds")},
5634
5635                 {PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 0,  N_("Off")},
5636                 {PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 1,  N_("Auto")},
5637                 {PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 2,  N_("On")},
5638                 {PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 3,  N_("Red Eye Suppression")},
5639                 {PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 4,  N_("Low Speed Synchronization")},
5640                 {PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 5,  N_("Auto + Red Eye Suppression")},
5641                 {PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 6,  N_("On + Red Eye Suppression")},
5642
5643                 {PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 0,  N_("Auto")},
5644                 {PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 1,  N_("P")},
5645                 {PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 2,  N_("Tv")},
5646                 {PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 3,  N_("Av")},
5647                 {PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 4,  N_("M")},
5648                 {PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 5,  N_("A_DEP")},
5649                 {PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 6,  N_("M_DEP")},
5650                 {PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 7,  N_("Bulb")},
5651                 /* more actually */
5652
5653                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 0,  N_("Auto")},
5654                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 1,  N_("Manual")},
5655                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 2,  N_("Distant View")},
5656                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 3,  N_("High-Speed Shutter")},
5657                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 4,  N_("Low-Speed Shutter")},
5658                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 5,  N_("Night View")},
5659                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 6,  N_("Grayscale")},
5660                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 7,  N_("Sepia")},
5661                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 8,  N_("Portrait")},
5662                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 9,  N_("Sports")},
5663                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 10,  N_("Macro")},
5664                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 11,  N_("Monochrome")},
5665                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 12,  N_("Pan Focus")},
5666                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 13,  N_("Neutral")},
5667                 {PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 14,  N_("Soft")},
5668
5669                 {PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 0,  N_("Single-Frame Shooting")},
5670                 {PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 1,  N_("Continuous Shooting")},
5671                 {PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 2,  N_("Timer (Single) Shooting")},
5672                 {PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 4,  N_("Continuous Low-speed Shooting")},
5673                 {PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 5,  N_("Continuous High-speed Shooting")},
5674
5675                 {PTP_DPC_CANON_EZoom, PTP_VENDOR_CANON, 0,  N_("Off")},
5676                 {PTP_DPC_CANON_EZoom, PTP_VENDOR_CANON, 1,  N_("2x")},
5677                 {PTP_DPC_CANON_EZoom, PTP_VENDOR_CANON, 2,  N_("4x")},
5678                 {PTP_DPC_CANON_EZoom, PTP_VENDOR_CANON, 3,  N_("Smooth")},
5679
5680                 {PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 0,  N_("Center-weighted Metering")},
5681                 {PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 1,  N_("Spot Metering")},
5682                 {PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 2,  N_("Average Metering")},
5683                 {PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 3,  N_("Evaluative Metering")},
5684                 {PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 4,  N_("Partial Metering")},
5685                 {PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 5,  N_("Center-weighted Average Metering")},
5686                 {PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 6,  N_("Spot Metering Interlocked with AF Frame")},
5687                 {PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 7,  N_("Multi-Spot Metering")},
5688
5689                 {PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 0,  N_("Manual")},
5690                 {PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 1,  N_("Auto")},
5691                 {PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 2,  N_("Unknown")},
5692                 {PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 3,  N_("Zone Focus (Close-up)")},
5693                 {PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 4,  N_("Zone Focus (Very Close)")},
5694                 {PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 5,  N_("Zone Focus (Close)")},
5695                 {PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 6,  N_("Zone Focus (Medium)")},
5696                 {PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 7,  N_("Zone Focus (Far)")},
5697
5698                 {PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0,  N_("Invalid")},
5699                 {PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x1000,  N_("Focusing Point on Center Only, Manual")},
5700                 {PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x1001,  N_("Focusing Point on Center Only, Auto")},
5701                 {PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3000,  N_("Multiple Focusing Points (No Specification), Manual")},
5702                 {PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3001,  N_("Multiple Focusing Points, Auto")},
5703                 {PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3002,  N_("Multiple Focusing Points (Right)")},
5704                 {PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3003,  N_("Multiple Focusing Points (Center)")},
5705                 {PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3004,  N_("Multiple Focusing Points (Left)")},
5706
5707                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 0,  N_("Auto")},
5708                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 1,  N_("Daylight")},
5709                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 2,  N_("Cloudy")},
5710                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 3,  N_("Tungsten")},
5711                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 4,  N_("Fluorescent")},
5712                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 6,  N_("Preset")},
5713                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 7,  N_("Fluorescent H")},
5714                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 9,  N_("Color Temperature")},
5715                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 10,  N_("Custom Whitebalance PC-1")},
5716                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 11,  N_("Custom Whitebalance PC-2")},
5717                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 12,  N_("Custom Whitebalance PC-3")},
5718                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 13,  N_("Missing Number")},
5719                 {PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 14,  N_("Fluorescent H")}, /* dup? */
5720
5721                 {PTP_DPC_CANON_SlowShutterSetting, PTP_VENDOR_CANON, 0,  N_("Off")},
5722                 {PTP_DPC_CANON_SlowShutterSetting, PTP_VENDOR_CANON, 1,  N_("Night View")},
5723                 {PTP_DPC_CANON_SlowShutterSetting, PTP_VENDOR_CANON, 2,  N_("On")},
5724                 {PTP_DPC_CANON_SlowShutterSetting, PTP_VENDOR_CANON, 3,  N_("Low-speed shutter function not available")},
5725
5726                 {PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 0,  N_("Single Shot")},
5727                 {PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 1,  N_("AI Servo")},
5728                 {PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 2,  N_("AI Focus")},
5729                 {PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 3,  N_("Manual")},
5730                 {PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 4,  N_("Continuous")},
5731
5732                 PTP_VENDOR_VAL_BOOL(PTP_DPC_CANON_ImageStabilization,PTP_VENDOR_CANON),
5733
5734                 {PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, -2,  N_("Low 2")},
5735                 {PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, -1,  N_("Low")},
5736                 {PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, 0,  N_("Standard")},
5737                 {PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, 1,  N_("High")},
5738                 {PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, 2,  N_("High 2")},
5739
5740                 {PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, -2,  N_("Low 2")},
5741                 {PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, -1,  N_("Low")},
5742                 {PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, 0,  N_("Standard")},
5743                 {PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, 1,  N_("High")},
5744                 {PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, 2,  N_("High 2")},
5745
5746                 {PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, -2,  N_("Low 2")},
5747                 {PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, -1,  N_("Low")},
5748                 {PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, 0,  N_("Standard")},
5749                 {PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, 1,  N_("High")},
5750                 {PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, 2,  N_("High 2")},
5751
5752                 {PTP_DPC_CANON_Sensitivity, PTP_VENDOR_CANON, 0,  N_("Standard")},
5753                 {PTP_DPC_CANON_Sensitivity, PTP_VENDOR_CANON, 1,  N_("Upper 1")},
5754                 {PTP_DPC_CANON_Sensitivity, PTP_VENDOR_CANON, 2,  N_("Upper 2")},
5755
5756                 {PTP_DPC_CANON_ParameterSet, PTP_VENDOR_CANON, 0x08,  N_("Standard Development Parameters")},
5757                 {PTP_DPC_CANON_ParameterSet, PTP_VENDOR_CANON, 0x10,  N_("Development Parameters 1")},
5758                 {PTP_DPC_CANON_ParameterSet, PTP_VENDOR_CANON, 0x20,  N_("Development Parameters 2")},
5759                 {PTP_DPC_CANON_ParameterSet, PTP_VENDOR_CANON, 0x40,  N_("Development Parameters 3")},
5760
5761                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x00,  N_("Auto")},
5762                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x28,  "6"},
5763                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x30,  "12"},
5764                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x38,  "25"},
5765                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x40,  "50"},
5766                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x43,  "64"},
5767                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x48,  "100"},
5768                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x50,  "200"},
5769                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x58,  "400"},
5770                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x60,  "800"},
5771                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x68,  "1600"},
5772                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x70,  "3200"},
5773                 {PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x78,  "6400"},
5774
5775                 /* 0xd01d - PTP_DPC_CANON_Aperture */
5776                 /* 0xd01e - PTP_DPC_CANON_ShutterSpeed */
5777                 /* 0xd01f - PTP_DPC_CANON_ExpCompensation */
5778                 /* 0xd020 - PTP_DPC_CANON_FlashCompensation */
5779                 /* 0xd021 - PTP_DPC_CANON_AEBExposureCompensation */
5780                 /* 0xd023 - PTP_DPC_CANON_AvOpen */
5781                 /* 0xd024 - PTP_DPC_CANON_AvMax */
5782
5783                 {PTP_DPC_CANON_CameraOutput, PTP_VENDOR_CANON, 0,  N_("Undefined")},
5784                 {PTP_DPC_CANON_CameraOutput, PTP_VENDOR_CANON, 1,  N_("LCD")},
5785                 {PTP_DPC_CANON_CameraOutput, PTP_VENDOR_CANON, 2,  N_("Video OUT")},
5786                 {PTP_DPC_CANON_CameraOutput, PTP_VENDOR_CANON, 3,  N_("Off")},
5787
5788                 {PTP_DPC_CANON_MlSpotPos, PTP_VENDOR_CANON, 0, N_("MlSpotPosCenter")},
5789                 {PTP_DPC_CANON_MlSpotPos, PTP_VENDOR_CANON, 1, N_("MlSpotPosAfLink")},
5790
5791                 {PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 0, N_("Off")},
5792                 {PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 1, N_("Vivid")},
5793                 {PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 2, N_("Neutral")},
5794                 {PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 3, N_("Soft")},
5795                 {PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 4, N_("Sepia")},
5796                 {PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 5, N_("Monochrome")},
5797
5798                 {0, 0, 0, NULL}
5799         };
5800         for (i=0; ptp_value_trans[i].dpc!=0; i++) {
5801                 if ((ptp_value_trans[i].dpc == dpc) &&
5802                         (((ptp_value_trans[i].dpc & 0xf000) == 0x5000) ||
5803                          (ptp_value_trans[i].vendor == params->deviceinfo.VendorExtensionID))
5804                 ) {
5805                         double value = _value_to_num(&(dpd->CurrentValue), dpd->DataType);
5806
5807                         return snprintf(out, length,
5808                                 _(ptp_value_trans[i].format),
5809                                 value * ptp_value_trans[i].coef +
5810                                 ptp_value_trans[i].bias);
5811                 }
5812         }
5813
5814         kval = _value_to_num(&(dpd->CurrentValue), dpd->DataType);
5815         for (i=0; ptp_value_list[i].dpc!=0; i++) {
5816                 if ((ptp_value_list[i].dpc == dpc) &&
5817                         (((ptp_value_list[i].dpc & 0xf000) == 0x5000) ||
5818                           (ptp_value_list[i].vendor == params->deviceinfo.VendorExtensionID)) &&
5819                     (ptp_value_list[i].key==kval)
5820                 ) {
5821                         return snprintf(out, length, "%s", _(ptp_value_list[i].value));
5822                 }
5823         }
5824         if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_MICROSOFT
5825             || params->deviceinfo.VendorExtensionID==PTP_VENDOR_MTP) {
5826                 switch (dpc) {
5827                 case PTP_DPC_MTP_SynchronizationPartner:
5828                 case PTP_DPC_MTP_DeviceFriendlyName:
5829                         return snprintf(out, length, "%s", dpd->CurrentValue.str);
5830                 case PTP_DPC_MTP_SecureTime:
5831                 case PTP_DPC_MTP_DeviceCertificate: {
5832                         /* FIXME: Convert to use unicode demux functions */
5833                         for (i=0;(i<dpd->CurrentValue.a.count) && (i<length);i++)
5834                                 out[i] = dpd->CurrentValue.a.v[i].u16;
5835                         if (    dpd->CurrentValue.a.count &&
5836                                 (dpd->CurrentValue.a.count < length)) {
5837                                 out[dpd->CurrentValue.a.count-1] = 0;
5838                                 return dpd->CurrentValue.a.count-1;
5839                         } else {
5840                                 out[length-1] = 0;
5841                                 return length;
5842                         }
5843                         break;
5844                 }
5845                 default:
5846                         break;
5847                 }
5848         }
5849
5850         return 0;
5851 }
5852
5853 struct {
5854         uint16_t ofc;
5855         const char *format;
5856 } ptp_ofc_trans[] = {
5857         {PTP_OFC_Undefined,"Undefined Type"},
5858         {PTP_OFC_Defined,"Defined Type"},
5859         {PTP_OFC_Association,"Association/Directory"},
5860         {PTP_OFC_Script,"Script"},
5861         {PTP_OFC_Executable,"Executable"},
5862         {PTP_OFC_Text,"Text"},
5863         {PTP_OFC_HTML,"HTML"},
5864         {PTP_OFC_DPOF,"DPOF"},
5865         {PTP_OFC_AIFF,"AIFF"},
5866         {PTP_OFC_WAV,"MS Wave"},
5867         {PTP_OFC_MP3,"MP3"},
5868         {PTP_OFC_AVI,"MS AVI"},
5869         {PTP_OFC_MPEG,"MPEG"},
5870         {PTP_OFC_ASF,"ASF"},
5871         {PTP_OFC_QT,"Apple Quicktime"},
5872         {PTP_OFC_EXIF_JPEG,"JPEG"},
5873         {PTP_OFC_TIFF_EP,"TIFF EP"},
5874         {PTP_OFC_FlashPix,"FlashPix"},
5875         {PTP_OFC_BMP,"BMP"},
5876         {PTP_OFC_CIFF,"CIFF"},
5877         {PTP_OFC_GIF,"GIF"},
5878         {PTP_OFC_JFIF,"JFIF"},
5879         {PTP_OFC_PCD,"PCD"},
5880         {PTP_OFC_PICT,"PICT"},
5881         {PTP_OFC_PNG,"PNG"},
5882         {PTP_OFC_TIFF,"TIFF"},
5883         {PTP_OFC_TIFF_IT,"TIFF_IT"},
5884         {PTP_OFC_JP2,"JP2"},
5885         {PTP_OFC_JPX,"JPX"},
5886         {PTP_OFC_DNG,"DNG"},
5887 };
5888
5889 struct {
5890         uint16_t ofc;
5891         const char *format;
5892 } ptp_ofc_mtp_trans[] = {
5893         {PTP_OFC_MTP_MediaCard,N_("Media Card")},
5894         {PTP_OFC_MTP_MediaCardGroup,N_("Media Card Group")},
5895         {PTP_OFC_MTP_Encounter,N_("Encounter")},
5896         {PTP_OFC_MTP_EncounterBox,N_("Encounter Box")},
5897         {PTP_OFC_MTP_M4A,N_("M4A")},
5898         {PTP_OFC_MTP_Firmware,N_("Firmware")},
5899         {PTP_OFC_MTP_WindowsImageFormat,N_("Windows Image Format")},
5900         {PTP_OFC_MTP_UndefinedAudio,N_("Undefined Audio")},
5901         {PTP_OFC_MTP_WMA,"WMA"},
5902         {PTP_OFC_MTP_OGG,"OGG"},
5903         {PTP_OFC_MTP_AAC,"AAC"},
5904         {PTP_OFC_MTP_AudibleCodec,N_("Audible.com Codec")},
5905         {PTP_OFC_MTP_FLAC,"FLAC"},
5906         {PTP_OFC_MTP_SamsungPlaylist,N_("Samsung Playlist")},
5907         {PTP_OFC_MTP_UndefinedVideo,N_("Undefined Video")},
5908         {PTP_OFC_MTP_WMV,"WMV"},
5909         {PTP_OFC_MTP_MP4,"MP4"},
5910         {PTP_OFC_MTP_MP2,"MP2"},
5911         {PTP_OFC_MTP_3GP,"3GP"},
5912         {PTP_OFC_MTP_UndefinedCollection,N_("Undefined Collection")},
5913         {PTP_OFC_MTP_AbstractMultimediaAlbum,N_("Abstract Multimedia Album")},
5914         {PTP_OFC_MTP_AbstractImageAlbum,N_("Abstract Image Album")},
5915         {PTP_OFC_MTP_AbstractAudioAlbum,N_("Abstract Audio Album")},
5916         {PTP_OFC_MTP_AbstractVideoAlbum,N_("Abstract Video Album")},
5917         {PTP_OFC_MTP_AbstractAudioVideoPlaylist,N_("Abstract Audio Video Playlist")},
5918         {PTP_OFC_MTP_AbstractContactGroup,N_("Abstract Contact Group")},
5919         {PTP_OFC_MTP_AbstractMessageFolder,N_("Abstract Message Folder")},
5920         {PTP_OFC_MTP_AbstractChapteredProduction,N_("Abstract Chaptered Production")},
5921         {PTP_OFC_MTP_AbstractAudioPlaylist,N_("Abstract Audio Playlist")},
5922         {PTP_OFC_MTP_AbstractVideoPlaylist,N_("Abstract Video Playlist")},
5923         {PTP_OFC_MTP_AbstractMediacast,N_("Abstract Mediacast")},
5924         {PTP_OFC_MTP_WPLPlaylist,N_("WPL Playlist")},
5925         {PTP_OFC_MTP_M3UPlaylist,N_("M3U Playlist")},
5926         {PTP_OFC_MTP_MPLPlaylist,N_("MPL Playlist")},
5927         {PTP_OFC_MTP_ASXPlaylist,N_("ASX Playlist")},
5928         {PTP_OFC_MTP_PLSPlaylist,N_("PLS Playlist")},
5929         {PTP_OFC_MTP_UndefinedDocument,N_("Undefined Document")},
5930         {PTP_OFC_MTP_AbstractDocument,N_("Abstract Document")},
5931         {PTP_OFC_MTP_XMLDocument,N_("XMLDocument")},
5932         {PTP_OFC_MTP_MSWordDocument,N_("Microsoft Word Document")},
5933         {PTP_OFC_MTP_MHTCompiledHTMLDocument,N_("MHT Compiled HTML Document")},
5934         {PTP_OFC_MTP_MSExcelSpreadsheetXLS,N_("Microsoft Excel Spreadsheet (.xls)")},
5935         {PTP_OFC_MTP_MSPowerpointPresentationPPT,N_("Microsoft Powerpoint (.ppt)")},
5936         {PTP_OFC_MTP_UndefinedMessage,N_("Undefined Message")},
5937         {PTP_OFC_MTP_AbstractMessage,N_("Abstract Message")},
5938         {PTP_OFC_MTP_UndefinedContact,N_("Undefined Contact")},
5939         {PTP_OFC_MTP_AbstractContact,N_("Abstract Contact")},
5940         {PTP_OFC_MTP_vCard2,N_("vCard2")},
5941         {PTP_OFC_MTP_vCard3,N_("vCard3")},
5942         {PTP_OFC_MTP_UndefinedCalendarItem,N_("Undefined Calendar Item")},
5943         {PTP_OFC_MTP_AbstractCalendarItem,N_("Abstract Calendar Item")},
5944         {PTP_OFC_MTP_vCalendar1,N_("vCalendar1")},
5945         {PTP_OFC_MTP_vCalendar2,N_("vCalendar2")},
5946         {PTP_OFC_MTP_UndefinedWindowsExecutable,N_("Undefined Windows Executable")},
5947         {PTP_OFC_MTP_MediaCast,N_("Media Cast")},
5948         {PTP_OFC_MTP_Section,N_("Section")},
5949 };
5950
5951 int
5952 ptp_render_ofc(PTPParams* params, uint16_t ofc, int spaceleft, char *txt)
5953 {
5954         unsigned int i;
5955
5956         if (!(ofc & 0x8000)) {
5957                 for (i=0;i<sizeof(ptp_ofc_trans)/sizeof(ptp_ofc_trans[0]);i++)
5958                         if (ofc == ptp_ofc_trans[i].ofc)
5959                                 return snprintf(txt, spaceleft, "%s", _(ptp_ofc_trans[i].format));
5960         } else {
5961                 switch (params->deviceinfo.VendorExtensionID) {
5962                 case PTP_VENDOR_EASTMAN_KODAK:
5963                         switch (ofc) {
5964                         case PTP_OFC_EK_M3U:
5965                                 return snprintf (txt, spaceleft,"M3U");
5966                         default:
5967                                 break;
5968                         }
5969                         break;
5970                 case PTP_VENDOR_CANON:
5971                         switch (ofc) {
5972                         case PTP_OFC_CANON_CRW:
5973                                 return snprintf (txt, spaceleft,"CRW");
5974                         default:
5975                                 break;
5976                         }
5977                         break;
5978                 case PTP_VENDOR_MICROSOFT:
5979                 case PTP_VENDOR_MTP:
5980                         for (i=0;i<sizeof(ptp_ofc_mtp_trans)/sizeof(ptp_ofc_mtp_trans[0]);i++)
5981                                 if (ofc == ptp_ofc_mtp_trans[i].ofc)
5982                                         return snprintf(txt, spaceleft, "%s", _(ptp_ofc_mtp_trans[i].format));
5983                         break;
5984                 default:break;
5985                 }
5986         }
5987         return snprintf (txt, spaceleft,_("Unknown(%04x)"), ofc);
5988 }
5989
5990 struct {
5991         uint16_t opcode;
5992         const char *name;
5993 } ptp_opcode_trans[] = {
5994         {PTP_OC_Undefined,N_("Undefined")},
5995         {PTP_OC_GetDeviceInfo,N_("get device info")},
5996         {PTP_OC_OpenSession,N_("Open session")},
5997         {PTP_OC_CloseSession,N_("Close session")},
5998         {PTP_OC_GetStorageIDs,N_("Get storage IDs")},
5999         {PTP_OC_GetStorageInfo,N_("Get storage info")},
6000         {PTP_OC_GetNumObjects,N_("Get number of objects")},
6001         {PTP_OC_GetObjectHandles,N_("Get object handles")},
6002         {PTP_OC_GetObjectInfo,N_("Get object info")},
6003         {PTP_OC_GetObject,N_("Get object")},
6004         {PTP_OC_GetThumb,N_("Get thumbnail")},
6005         {PTP_OC_DeleteObject,N_("Delete object")},
6006         {PTP_OC_SendObjectInfo,N_("Send object info")},
6007         {PTP_OC_SendObject,N_("Send object")},
6008         {PTP_OC_InitiateCapture,N_("Initiate capture")},
6009         {PTP_OC_FormatStore,N_("Format storage")},
6010         {PTP_OC_ResetDevice,N_("Reset device")},
6011         {PTP_OC_SelfTest,N_("Self test device")},
6012         {PTP_OC_SetObjectProtection,N_("Set object protection")},
6013         {PTP_OC_PowerDown,N_("Power down device")},
6014         {PTP_OC_GetDevicePropDesc,N_("Get device property description")},
6015         {PTP_OC_GetDevicePropValue,N_("Get device property value")},
6016         {PTP_OC_SetDevicePropValue,N_("Set device property value")},
6017         {PTP_OC_ResetDevicePropValue,N_("Reset device property value")},
6018         {PTP_OC_TerminateOpenCapture,N_("Terminate open capture")},
6019         {PTP_OC_MoveObject,N_("Move object")},
6020         {PTP_OC_CopyObject,N_("Copy object")},
6021         {PTP_OC_GetPartialObject,N_("Get partial object")},
6022         {PTP_OC_InitiateOpenCapture,N_("Initiate open capture")}
6023 };
6024
6025 struct {
6026         uint16_t opcode;
6027         const char *name;
6028 } ptp_opcode_mtp_trans[] = {
6029         {PTP_OC_MTP_GetObjectPropsSupported,N_("Get object properties supported")},
6030         {PTP_OC_MTP_GetObjectPropDesc,N_("Get object property description")},
6031         {PTP_OC_MTP_GetObjectPropValue,N_("Get object property value")},
6032         {PTP_OC_MTP_SetObjectPropValue,N_("Set object property value")},
6033         {PTP_OC_MTP_GetObjPropList,N_("Get object property list")},
6034         {PTP_OC_MTP_SetObjPropList,N_("Set object property list")},
6035         {PTP_OC_MTP_GetInterdependendPropdesc,N_("Get interdependent property description")},
6036         {PTP_OC_MTP_SendObjectPropList,N_("Send object property list")},
6037         {PTP_OC_MTP_GetObjectReferences,N_("Get object references")},
6038         {PTP_OC_MTP_SetObjectReferences,N_("Set object references")},
6039         {PTP_OC_MTP_UpdateDeviceFirmware,N_("Update device firmware")},
6040         {PTP_OC_MTP_Skip,N_("Skip to next position in playlist")},
6041
6042         /* WMDRMPD Extensions */
6043         {PTP_OC_MTP_WMDRMPD_GetSecureTimeChallenge,N_("Get secure time challenge")},
6044         {PTP_OC_MTP_WMDRMPD_GetSecureTimeResponse,N_("Get secure time response")},
6045         {PTP_OC_MTP_WMDRMPD_SetLicenseResponse,N_("Set license response")},
6046         {PTP_OC_MTP_WMDRMPD_GetSyncList,N_("Get sync list")},
6047         {PTP_OC_MTP_WMDRMPD_SendMeterChallengeQuery,N_("Send meter challenge query")},
6048         {PTP_OC_MTP_WMDRMPD_GetMeterChallenge,N_("Get meter challenge")},
6049         {PTP_OC_MTP_WMDRMPD_SetMeterResponse,N_("Get meter response")},
6050         {PTP_OC_MTP_WMDRMPD_CleanDataStore,N_("Clean data store")},
6051         {PTP_OC_MTP_WMDRMPD_GetLicenseState,N_("Get license state")},
6052         {PTP_OC_MTP_WMDRMPD_SendWMDRMPDCommand,N_("Send WMDRM-PD Command")},
6053         {PTP_OC_MTP_WMDRMPD_SendWMDRMPDRequest,N_("Send WMDRM-PD Request")},
6054
6055         /* WMPPD Extensions */
6056         {PTP_OC_MTP_WMPPD_ReportAddedDeletedItems,N_("Report Added/Deleted Items")},
6057         {PTP_OC_MTP_WMPPD_ReportAcquiredItems,N_("Report Acquired Items")},
6058         {PTP_OC_MTP_WMPPD_PlaylistObjectPref,N_("Get transferable playlist types")},
6059
6060         /* WMDRMPD Extensions... these have no identifiers associated with them */
6061         {PTP_OC_MTP_WMDRMPD_SendWMDRMPDAppRequest,N_("Send WMDRM-PD Application Request")},
6062         {PTP_OC_MTP_WMDRMPD_GetWMDRMPDAppResponse,N_("Get WMDRM-PD Application Response")},
6063         {PTP_OC_MTP_WMDRMPD_EnableTrustedFilesOperations,N_("Enable trusted file operations")},
6064         {PTP_OC_MTP_WMDRMPD_DisableTrustedFilesOperations,N_("Disable trusted file operations")},
6065         {PTP_OC_MTP_WMDRMPD_EndTrustedAppSession,N_("End trusted application session")},
6066
6067         /* AAVT Extensions */
6068         {PTP_OC_MTP_AAVT_OpenMediaSession,N_("Open Media Session")},
6069         {PTP_OC_MTP_AAVT_CloseMediaSession,N_("Close Media Session")},
6070         {PTP_OC_MTP_AAVT_GetNextDataBlock,N_("Get Next Data Block")},
6071         {PTP_OC_MTP_AAVT_SetCurrentTimePosition,N_("Set Current Time Position")},
6072
6073         /* WMDRMND Extensions */
6074         {PTP_OC_MTP_WMDRMND_SendRegistrationRequest,N_("Send Registration Request")},
6075         {PTP_OC_MTP_WMDRMND_GetRegistrationResponse,N_("Get Registration Response")},
6076         {PTP_OC_MTP_WMDRMND_GetProximityChallenge,N_("Get Proximity Challenge")},
6077         {PTP_OC_MTP_WMDRMND_SendProximityResponse,N_("Send Proximity Response")},
6078         {PTP_OC_MTP_WMDRMND_SendWMDRMNDLicenseRequest,N_("Send WMDRM-ND License Request")},
6079         {PTP_OC_MTP_WMDRMND_GetWMDRMNDLicenseResponse,N_("Get WMDRM-ND License Response")},
6080
6081         /* WiFi Provisioning MTP Extension Codes (microsoft.com/WPDWCN: 1.0) */
6082         {PTP_OC_MTP_WPDWCN_ProcessWFCObject,N_("Process WFC Object")},
6083
6084         /* Android Direct I/O Extensions */
6085         {PTP_OC_ANDROID_GetPartialObject64,N_("Get Partial Object (64bit Offset)")},
6086         {PTP_OC_ANDROID_SendPartialObject,N_("Send Partial Object")},
6087         {PTP_OC_ANDROID_TruncateObject,N_("Truncate Object")},
6088         {PTP_OC_ANDROID_BeginEditObject,N_("Begin Edit Object")},
6089         {PTP_OC_ANDROID_EndEditObject,N_("End Edit Object")},
6090 };
6091
6092 int
6093 ptp_render_opcode(PTPParams* params, uint16_t opcode, int spaceleft, char *txt)
6094 {
6095         unsigned int i;
6096
6097         if (!(opcode & 0x8000)) {
6098                 for (i=0;i<sizeof(ptp_opcode_trans)/sizeof(ptp_opcode_trans[0]);i++)
6099                         if (opcode == ptp_opcode_trans[i].opcode)
6100                                 return snprintf(txt, spaceleft, "%s", _(ptp_opcode_trans[i].name));
6101         } else {
6102                 switch (params->deviceinfo.VendorExtensionID) {
6103                 case PTP_VENDOR_MICROSOFT:
6104                 case PTP_VENDOR_MTP:
6105                         for (i=0;i<sizeof(ptp_opcode_mtp_trans)/sizeof(ptp_opcode_mtp_trans[0]);i++)
6106                                 if (opcode == ptp_opcode_mtp_trans[i].opcode)
6107                                         return snprintf(txt, spaceleft, "%s", _(ptp_opcode_mtp_trans[i].name));
6108                         break;
6109                 default:break;
6110                 }
6111         }
6112         return snprintf (txt, spaceleft,_("Unknown (%04x)"), opcode);
6113 }
6114
6115
6116 struct {
6117         uint16_t id;
6118         const char *name;
6119 } ptp_opc_trans[] = {
6120         {PTP_OPC_StorageID,"StorageID"},
6121         {PTP_OPC_ObjectFormat,"ObjectFormat"},
6122         {PTP_OPC_ProtectionStatus,"ProtectionStatus"},
6123         {PTP_OPC_ObjectSize,"ObjectSize"},
6124         {PTP_OPC_AssociationType,"AssociationType"},
6125         {PTP_OPC_AssociationDesc,"AssociationDesc"},
6126         {PTP_OPC_ObjectFileName,"ObjectFileName"},
6127         {PTP_OPC_DateCreated,"DateCreated"},
6128         {PTP_OPC_DateModified,"DateModified"},
6129         {PTP_OPC_Keywords,"Keywords"},
6130         {PTP_OPC_ParentObject,"ParentObject"},
6131         {PTP_OPC_AllowedFolderContents,"AllowedFolderContents"},
6132         {PTP_OPC_Hidden,"Hidden"},
6133         {PTP_OPC_SystemObject,"SystemObject"},
6134         {PTP_OPC_PersistantUniqueObjectIdentifier,"PersistantUniqueObjectIdentifier"},
6135         {PTP_OPC_SyncID,"SyncID"},
6136         {PTP_OPC_PropertyBag,"PropertyBag"},
6137         {PTP_OPC_Name,"Name"},
6138         {PTP_OPC_CreatedBy,"CreatedBy"},
6139         {PTP_OPC_Artist,"Artist"},
6140         {PTP_OPC_DateAuthored,"DateAuthored"},
6141         {PTP_OPC_Description,"Description"},
6142         {PTP_OPC_URLReference,"URLReference"},
6143         {PTP_OPC_LanguageLocale,"LanguageLocale"},
6144         {PTP_OPC_CopyrightInformation,"CopyrightInformation"},
6145         {PTP_OPC_Source,"Source"},
6146         {PTP_OPC_OriginLocation,"OriginLocation"},
6147         {PTP_OPC_DateAdded,"DateAdded"},
6148         {PTP_OPC_NonConsumable,"NonConsumable"},
6149         {PTP_OPC_CorruptOrUnplayable,"CorruptOrUnplayable"},
6150         {PTP_OPC_ProducerSerialNumber,"ProducerSerialNumber"},
6151         {PTP_OPC_RepresentativeSampleFormat,"RepresentativeSampleFormat"},
6152         {PTP_OPC_RepresentativeSampleSize,"RepresentativeSampleSize"},
6153         {PTP_OPC_RepresentativeSampleHeight,"RepresentativeSampleHeight"},
6154         {PTP_OPC_RepresentativeSampleWidth,"RepresentativeSampleWidth"},
6155         {PTP_OPC_RepresentativeSampleDuration,"RepresentativeSampleDuration"},
6156         {PTP_OPC_RepresentativeSampleData,"RepresentativeSampleData"},
6157         {PTP_OPC_Width,"Width"},
6158         {PTP_OPC_Height,"Height"},
6159         {PTP_OPC_Duration,"Duration"},
6160         {PTP_OPC_Rating,"Rating"},
6161         {PTP_OPC_Track,"Track"},
6162         {PTP_OPC_Genre,"Genre"},
6163         {PTP_OPC_Credits,"Credits"},
6164         {PTP_OPC_Lyrics,"Lyrics"},
6165         {PTP_OPC_SubscriptionContentID,"SubscriptionContentID"},
6166         {PTP_OPC_ProducedBy,"ProducedBy"},
6167         {PTP_OPC_UseCount,"UseCount"},
6168         {PTP_OPC_SkipCount,"SkipCount"},
6169         {PTP_OPC_LastAccessed,"LastAccessed"},
6170         {PTP_OPC_ParentalRating,"ParentalRating"},
6171         {PTP_OPC_MetaGenre,"MetaGenre"},
6172         {PTP_OPC_Composer,"Composer"},
6173         {PTP_OPC_EffectiveRating,"EffectiveRating"},
6174         {PTP_OPC_Subtitle,"Subtitle"},
6175         {PTP_OPC_OriginalReleaseDate,"OriginalReleaseDate"},
6176         {PTP_OPC_AlbumName,"AlbumName"},
6177         {PTP_OPC_AlbumArtist,"AlbumArtist"},
6178         {PTP_OPC_Mood,"Mood"},
6179         {PTP_OPC_DRMStatus,"DRMStatus"},
6180         {PTP_OPC_SubDescription,"SubDescription"},
6181         {PTP_OPC_IsCropped,"IsCropped"},
6182         {PTP_OPC_IsColorCorrected,"IsColorCorrected"},
6183         {PTP_OPC_ImageBitDepth,"ImageBitDepth"},
6184         {PTP_OPC_Fnumber,"Fnumber"},
6185         {PTP_OPC_ExposureTime,"ExposureTime"},
6186         {PTP_OPC_ExposureIndex,"ExposureIndex"},
6187         {PTP_OPC_DisplayName,"DisplayName"},
6188         {PTP_OPC_BodyText,"BodyText"},
6189         {PTP_OPC_Subject,"Subject"},
6190         {PTP_OPC_Priority,"Priority"},
6191         {PTP_OPC_GivenName,"GivenName"},
6192         {PTP_OPC_MiddleNames,"MiddleNames"},
6193         {PTP_OPC_FamilyName,"FamilyName"},
6194
6195         {PTP_OPC_Prefix,"Prefix"},
6196         {PTP_OPC_Suffix,"Suffix"},
6197         {PTP_OPC_PhoneticGivenName,"PhoneticGivenName"},
6198         {PTP_OPC_PhoneticFamilyName,"PhoneticFamilyName"},
6199         {PTP_OPC_EmailPrimary,"EmailPrimary"},
6200         {PTP_OPC_EmailPersonal1,"EmailPersonal1"},
6201         {PTP_OPC_EmailPersonal2,"EmailPersonal2"},
6202         {PTP_OPC_EmailBusiness1,"EmailBusiness1"},
6203         {PTP_OPC_EmailBusiness2,"EmailBusiness2"},
6204         {PTP_OPC_EmailOthers,"EmailOthers"},
6205         {PTP_OPC_PhoneNumberPrimary,"PhoneNumberPrimary"},
6206         {PTP_OPC_PhoneNumberPersonal,"PhoneNumberPersonal"},
6207         {PTP_OPC_PhoneNumberPersonal2,"PhoneNumberPersonal2"},
6208         {PTP_OPC_PhoneNumberBusiness,"PhoneNumberBusiness"},
6209         {PTP_OPC_PhoneNumberBusiness2,"PhoneNumberBusiness2"},
6210         {PTP_OPC_PhoneNumberMobile,"PhoneNumberMobile"},
6211         {PTP_OPC_PhoneNumberMobile2,"PhoneNumberMobile2"},
6212         {PTP_OPC_FaxNumberPrimary,"FaxNumberPrimary"},
6213         {PTP_OPC_FaxNumberPersonal,"FaxNumberPersonal"},
6214         {PTP_OPC_FaxNumberBusiness,"FaxNumberBusiness"},
6215         {PTP_OPC_PagerNumber,"PagerNumber"},
6216         {PTP_OPC_PhoneNumberOthers,"PhoneNumberOthers"},
6217         {PTP_OPC_PrimaryWebAddress,"PrimaryWebAddress"},
6218         {PTP_OPC_PersonalWebAddress,"PersonalWebAddress"},
6219         {PTP_OPC_BusinessWebAddress,"BusinessWebAddress"},
6220         {PTP_OPC_InstantMessengerAddress,"InstantMessengerAddress"},
6221         {PTP_OPC_InstantMessengerAddress2,"InstantMessengerAddress2"},
6222         {PTP_OPC_InstantMessengerAddress3,"InstantMessengerAddress3"},
6223         {PTP_OPC_PostalAddressPersonalFull,"PostalAddressPersonalFull"},
6224         {PTP_OPC_PostalAddressPersonalFullLine1,"PostalAddressPersonalFullLine1"},
6225         {PTP_OPC_PostalAddressPersonalFullLine2,"PostalAddressPersonalFullLine2"},
6226         {PTP_OPC_PostalAddressPersonalFullCity,"PostalAddressPersonalFullCity"},
6227         {PTP_OPC_PostalAddressPersonalFullRegion,"PostalAddressPersonalFullRegion"},
6228         {PTP_OPC_PostalAddressPersonalFullPostalCode,"PostalAddressPersonalFullPostalCode"},
6229         {PTP_OPC_PostalAddressPersonalFullCountry,"PostalAddressPersonalFullCountry"},
6230         {PTP_OPC_PostalAddressBusinessFull,"PostalAddressBusinessFull"},
6231         {PTP_OPC_PostalAddressBusinessLine1,"PostalAddressBusinessLine1"},
6232         {PTP_OPC_PostalAddressBusinessLine2,"PostalAddressBusinessLine2"},
6233         {PTP_OPC_PostalAddressBusinessCity,"PostalAddressBusinessCity"},
6234         {PTP_OPC_PostalAddressBusinessRegion,"PostalAddressBusinessRegion"},
6235         {PTP_OPC_PostalAddressBusinessPostalCode,"PostalAddressBusinessPostalCode"},
6236         {PTP_OPC_PostalAddressBusinessCountry,"PostalAddressBusinessCountry"},
6237         {PTP_OPC_PostalAddressOtherFull,"PostalAddressOtherFull"},
6238         {PTP_OPC_PostalAddressOtherLine1,"PostalAddressOtherLine1"},
6239         {PTP_OPC_PostalAddressOtherLine2,"PostalAddressOtherLine2"},
6240         {PTP_OPC_PostalAddressOtherCity,"PostalAddressOtherCity"},
6241         {PTP_OPC_PostalAddressOtherRegion,"PostalAddressOtherRegion"},
6242         {PTP_OPC_PostalAddressOtherPostalCode,"PostalAddressOtherPostalCode"},
6243         {PTP_OPC_PostalAddressOtherCountry,"PostalAddressOtherCountry"},
6244         {PTP_OPC_OrganizationName,"OrganizationName"},
6245         {PTP_OPC_PhoneticOrganizationName,"PhoneticOrganizationName"},
6246         {PTP_OPC_Role,"Role"},
6247         {PTP_OPC_Birthdate,"Birthdate"},
6248         {PTP_OPC_MessageTo,"MessageTo"},
6249         {PTP_OPC_MessageCC,"MessageCC"},
6250         {PTP_OPC_MessageBCC,"MessageBCC"},
6251         {PTP_OPC_MessageRead,"MessageRead"},
6252         {PTP_OPC_MessageReceivedTime,"MessageReceivedTime"},
6253         {PTP_OPC_MessageSender,"MessageSender"},
6254         {PTP_OPC_ActivityBeginTime,"ActivityBeginTime"},
6255         {PTP_OPC_ActivityEndTime,"ActivityEndTime"},
6256         {PTP_OPC_ActivityLocation,"ActivityLocation"},
6257         {PTP_OPC_ActivityRequiredAttendees,"ActivityRequiredAttendees"},
6258         {PTP_OPC_ActivityOptionalAttendees,"ActivityOptionalAttendees"},
6259         {PTP_OPC_ActivityResources,"ActivityResources"},
6260         {PTP_OPC_ActivityAccepted,"ActivityAccepted"},
6261         {PTP_OPC_Owner,"Owner"},
6262         {PTP_OPC_Editor,"Editor"},
6263         {PTP_OPC_Webmaster,"Webmaster"},
6264         {PTP_OPC_URLSource,"URLSource"},
6265         {PTP_OPC_URLDestination,"URLDestination"},
6266         {PTP_OPC_TimeBookmark,"TimeBookmark"},
6267         {PTP_OPC_ObjectBookmark,"ObjectBookmark"},
6268         {PTP_OPC_ByteBookmark,"ByteBookmark"},
6269         {PTP_OPC_LastBuildDate,"LastBuildDate"},
6270         {PTP_OPC_TimetoLive,"TimetoLive"},
6271         {PTP_OPC_MediaGUID,"MediaGUID"},
6272         {PTP_OPC_TotalBitRate,"TotalBitRate"},
6273         {PTP_OPC_BitRateType,"BitRateType"},
6274         {PTP_OPC_SampleRate,"SampleRate"},
6275         {PTP_OPC_NumberOfChannels,"NumberOfChannels"},
6276         {PTP_OPC_AudioBitDepth,"AudioBitDepth"},
6277         {PTP_OPC_ScanDepth,"ScanDepth"},
6278         {PTP_OPC_AudioWAVECodec,"AudioWAVECodec"},
6279         {PTP_OPC_AudioBitRate,"AudioBitRate"},
6280         {PTP_OPC_VideoFourCCCodec,"VideoFourCCCodec"},
6281         {PTP_OPC_VideoBitRate,"VideoBitRate"},
6282         {PTP_OPC_FramesPerThousandSeconds,"FramesPerThousandSeconds"},
6283         {PTP_OPC_KeyFrameDistance,"KeyFrameDistance"},
6284         {PTP_OPC_BufferSize,"BufferSize"},
6285         {PTP_OPC_EncodingQuality,"EncodingQuality"},
6286         {PTP_OPC_EncodingProfile,"EncodingProfile"},
6287         {PTP_OPC_BuyFlag,"BuyFlag"},
6288 };
6289
6290 int
6291 ptp_render_mtp_propname(uint16_t propid, int spaceleft, char *txt) {
6292         unsigned int i;
6293         for (i=0;i<sizeof(ptp_opc_trans)/sizeof(ptp_opc_trans[0]);i++)
6294                 if (propid == ptp_opc_trans[i].id)
6295                         return snprintf(txt, spaceleft, "%s", ptp_opc_trans[i].name);
6296         return snprintf (txt, spaceleft,"unknown(%04x)", propid);
6297 }
6298
6299 /*
6300  * Allocate and default-initialize a few object properties.
6301  */
6302 MTPProperties *
6303 ptp_get_new_object_prop_entry(MTPProperties **props, int *nrofprops) {
6304         MTPProperties *newprops;
6305         MTPProperties *prop;
6306
6307         if (*props == NULL) {
6308                 newprops = malloc(sizeof(MTPProperties)*(*nrofprops+1));
6309         } else {
6310                 newprops = realloc(*props,sizeof(MTPProperties)*(*nrofprops+1));
6311         }
6312         if (newprops == NULL)
6313                 return NULL;
6314         prop = &newprops[*nrofprops];
6315         prop->property = PTP_OPC_StorageID; /* Should be "unknown" */
6316         prop->datatype = PTP_DTC_UNDEF;
6317         prop->ObjectHandle = 0x00000000U;
6318         prop->propval.str = NULL;
6319
6320         (*props) = newprops;
6321         (*nrofprops)++;
6322         return prop;
6323 }
6324
6325 void
6326 ptp_destroy_object_prop(MTPProperties *prop)
6327 {
6328   if (!prop)
6329     return;
6330
6331   if (prop->datatype == PTP_DTC_STR && prop->propval.str != NULL)
6332     free(prop->propval.str);
6333   else if ((prop->datatype == PTP_DTC_AINT8 || prop->datatype == PTP_DTC_AINT16 ||
6334             prop->datatype == PTP_DTC_AINT32 || prop->datatype == PTP_DTC_AINT64 || prop->datatype == PTP_DTC_AINT128 ||
6335             prop->datatype == PTP_DTC_AUINT8 || prop->datatype == PTP_DTC_AUINT16 ||
6336             prop->datatype == PTP_DTC_AUINT32 || prop->datatype == PTP_DTC_AUINT64 || prop->datatype ==  PTP_DTC_AUINT128)
6337             && prop->propval.a.v != NULL)
6338     free(prop->propval.a.v);
6339 }
6340
6341 void
6342 ptp_destroy_object_prop_list(MTPProperties *props, int nrofprops)
6343 {
6344   int i;
6345   MTPProperties *prop = props;
6346
6347   for (i=0;i<nrofprops;i++,prop++)
6348     ptp_destroy_object_prop(prop);
6349   free(props);
6350 }
6351
6352 /*
6353  * Find a certain object property in the cache, i.e. a certain metadata
6354  * item for a certain object handle.
6355  */
6356 MTPProperties *
6357 ptp_find_object_prop_in_cache(PTPParams *params, uint32_t const handle, uint32_t const attribute_id)
6358 {
6359         unsigned int    i;
6360         MTPProperties   *prop;
6361         PTPObject       *ob;
6362         uint16_t        ret;
6363
6364         ret = ptp_object_find (params, handle, &ob);
6365         if (ret != PTP_RC_OK)
6366                 return NULL;
6367         prop = ob->mtpprops;
6368         for (i=0;i<ob->nrofmtpprops;i++) {
6369                 if (attribute_id == prop->property)
6370                         return prop;
6371                 prop++;
6372         }
6373         return NULL;
6374 }
6375
6376 void
6377 ptp_remove_object_from_cache(PTPParams *params, uint32_t handle)
6378 {
6379         unsigned int i;
6380         PTPObject       *ob;
6381         uint16_t        ret;
6382
6383         ret = ptp_object_find (params, handle, &ob);
6384         if (ret != PTP_RC_OK)
6385                 return;
6386         i = ob-params->objects;
6387         /* remove object from object info cache */
6388         ptp_free_object (ob);
6389
6390         if (i < params->nrofobjects-1)
6391                 memmove (ob,ob+1,(params->nrofobjects-1-i)*sizeof(PTPObject));
6392         params->nrofobjects--;
6393         /* We use less memory than before so this shouldn't fail */
6394         params->objects = realloc(params->objects, sizeof(PTPObject)*params->nrofobjects);
6395 }
6396
6397 static int _cmp_ob (const void *a, const void *b) {
6398         PTPObject *oa = (PTPObject*)a;
6399         PTPObject *ob = (PTPObject*)b;
6400
6401         return oa->oid - ob->oid;
6402 }
6403
6404 void
6405 ptp_objects_sort (PTPParams *params) {
6406         qsort (params->objects, params->nrofobjects, sizeof(PTPObject), _cmp_ob);
6407 }
6408
6409 /* Binary search in objects. Needs "objects" to be a sorted by objectid list!  */
6410 uint16_t
6411 ptp_object_find (PTPParams *params, uint32_t handle, PTPObject **retob) {
6412         PTPObject       tmpob;
6413
6414         tmpob.oid = handle;
6415         *retob = bsearch (&tmpob, params->objects, params->nrofobjects, sizeof(tmpob), _cmp_ob);
6416         if (!*retob)
6417                 return PTP_RC_GeneralError;
6418         return PTP_RC_OK;
6419 }
6420
6421 /* Binary search in objects + insert of not found. Needs "objects" to be a sorted by objectid list!  */
6422 uint16_t
6423 ptp_object_find_or_insert (PTPParams *params, uint32_t handle, PTPObject **retob) {
6424         unsigned int    begin, end, cursor;
6425         unsigned int    insertat;
6426         PTPObject       *newobs;
6427
6428         if (!handle) return PTP_RC_GeneralError;
6429         *retob = NULL;
6430         if (!params->nrofobjects) {
6431                 params->objects = calloc(1,sizeof(PTPObject));
6432                 params->nrofobjects = 1;
6433                 params->objects[0].oid = handle;
6434                 *retob = &params->objects[0];
6435                 return PTP_RC_OK;
6436         }
6437         begin = 0;
6438         end = params->nrofobjects-1;
6439         /*ptp_debug (params, "searching %08x, total=%d", handle, params->nrofobjects);*/
6440         while (1) {
6441                 cursor = (end-begin)/2+begin;
6442                 /*ptp_debug (params, "ob %d: %08x [%d-%d]", cursor, params->objects[cursor].oid, begin, end);*/
6443                 if (params->objects[cursor].oid == handle) {
6444                         *retob = &params->objects[cursor];
6445                         return PTP_RC_OK;
6446                 }
6447                 if (params->objects[cursor].oid < handle)
6448                         begin = cursor;
6449                 else
6450                         end = cursor;
6451                 if ((end - begin) <= 1)
6452                         break;
6453         }
6454         if (params->objects[begin].oid == handle) {
6455                 *retob = &params->objects[begin];
6456                 return PTP_RC_OK;
6457         }
6458         if (params->objects[end].oid == handle) {
6459                 *retob = &params->objects[end];
6460                 return PTP_RC_OK;
6461         }
6462         if ((begin == 0) && (handle < params->objects[0].oid)) {
6463                 insertat=begin;
6464         } else {
6465                 if ((end == params->nrofobjects-1) && (handle > params->objects[end].oid))
6466                         insertat=end+1;
6467                 else
6468                         insertat=begin+1;
6469         }
6470         /*ptp_debug (params, "inserting oid %x at [%x,%x], begin=%d, end=%d, insertat=%d\n", handle, params->objects[begin].oid, params->objects[end].oid, begin, end, insertat);*/
6471         newobs = realloc (params->objects, sizeof(PTPObject)*(params->nrofobjects+1));
6472         if (!newobs) return PTP_RC_GeneralError;
6473         params->objects = newobs;
6474         if (insertat<params->nrofobjects)
6475                 memmove (&params->objects[insertat+1],&params->objects[insertat],(params->nrofobjects-insertat)*sizeof(PTPObject));
6476         memset(&params->objects[insertat],0,sizeof(PTPObject));
6477         params->objects[insertat].oid = handle;
6478         *retob = &params->objects[insertat];
6479         params->nrofobjects++;
6480         return PTP_RC_OK;
6481 }
6482
6483 uint16_t
6484 ptp_object_want (PTPParams *params, uint32_t handle, unsigned int want, PTPObject **retob) {
6485         uint16_t        ret;
6486         PTPObject       *ob;
6487         /*Camera                *camera = ((PTPData *)params->data)->camera;*/
6488
6489         /* If GetObjectInfo is broken, force GetPropList */
6490         if (params->device_flags & DEVICE_FLAG_PROPLIST_OVERRIDES_OI)
6491                 want |= PTPOBJECT_MTPPROPLIST_LOADED;
6492
6493         *retob = NULL;
6494         if (!handle) {
6495                 ptp_debug (params, "ptp_object_want: querying handle 0?\n");
6496                 return PTP_RC_GeneralError;
6497         }
6498         ret = ptp_object_find_or_insert (params, handle, &ob);
6499         if (ret != PTP_RC_OK)
6500                 return PTP_RC_GeneralError;
6501         *retob = ob;
6502         /* Do we have all of it already? */
6503         if ((ob->flags & want) == want)
6504                 return PTP_RC_OK;
6505
6506 #define X (PTPOBJECT_OBJECTINFO_LOADED|PTPOBJECT_STORAGEID_LOADED|PTPOBJECT_PARENTOBJECT_LOADED)
6507         if ((want & X) && ((ob->flags & X) != X)) {
6508                 uint32_t        saveparent = 0;
6509
6510                 /* One EOS issue, where getobjecthandles(root) returns obs without root flag. */
6511                 if (ob->flags & PTPOBJECT_PARENTOBJECT_LOADED)
6512                         saveparent = ob->oi.ParentObject;
6513
6514                 ret = ptp_getobjectinfo (params, handle, &ob->oi);
6515                 if (ret != PTP_RC_OK) {
6516                         /* kill it from the internal list ... */
6517                         ptp_remove_object_from_cache(params, handle);
6518                         return ret;
6519                 }
6520                 if (!ob->oi.Filename) ob->oi.Filename=strdup("<none>");
6521                 if (ob->flags & PTPOBJECT_PARENTOBJECT_LOADED)
6522                         ob->oi.ParentObject = saveparent;
6523
6524                 /* Second EOS issue, 0x20000000 has 0x20000000 as parent */
6525                 if (ob->oi.ParentObject == handle)
6526                         ob->oi.ParentObject = 0;
6527
6528                 /* Read out the canon special flags */
6529                 if ((params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) &&
6530                     ptp_operation_issupported(params,PTP_OC_CANON_GetObjectInfoEx)) {
6531                         PTPCANONFolderEntry *ents = NULL;
6532                         uint32_t            numents = 0;
6533
6534                         ret = ptp_canon_getobjectinfo(params,
6535                                 ob->oi.StorageID,0,
6536                                 ob->oi.ParentObject,handle,
6537                                 &ents,&numents
6538                         );
6539                         if ((ret == PTP_RC_OK) && (numents >= 1))
6540                                 ob->canon_flags = ents[0].Flags;
6541                         free (ents);
6542                 }
6543
6544                 ob->flags |= X;
6545         }
6546 #undef X
6547         if (    (want & PTPOBJECT_MTPPROPLIST_LOADED) &&
6548                 (!(ob->flags & PTPOBJECT_MTPPROPLIST_LOADED))
6549         ) {
6550                 int             nrofprops = 0;
6551                 MTPProperties   *props = NULL;
6552
6553                 if (params->device_flags & DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST) {
6554                         want &= ~PTPOBJECT_MTPPROPLIST_LOADED;
6555                         goto fallback;
6556                 }
6557                 /* Microsoft/MTP has fast directory retrieval. */
6558                 if (!ptp_operation_issupported(params,PTP_OC_MTP_GetObjPropList)) {
6559                         want &= ~PTPOBJECT_MTPPROPLIST_LOADED;
6560                         goto fallback;
6561                 }
6562
6563                 ptp_debug (params, "ptp2/mtpfast: reading mtp proplist of %08x", handle);
6564                 /* We just want this one object, not all at once. */
6565                 ret = ptp_mtp_getobjectproplist_single (params, handle, &props, &nrofprops);
6566                 if (ret != PTP_RC_OK)
6567                         goto fallback;
6568                 ob->mtpprops = props;
6569                 ob->nrofmtpprops = nrofprops;
6570
6571                 /* Override the ObjectInfo data with data from properties */
6572                 if (params->device_flags & DEVICE_FLAG_PROPLIST_OVERRIDES_OI) {
6573                         unsigned int i;
6574                         MTPProperties *prop = ob->mtpprops;
6575
6576                         for (i=0;i<ob->nrofmtpprops;i++,prop++) {
6577                                 /* in case we got all subtree objects */
6578                                 if (prop->ObjectHandle != handle) continue;
6579
6580                                 switch (prop->property) {
6581                                 case PTP_OPC_StorageID:
6582                                         ob->oi.StorageID = prop->propval.u32;
6583                                         break;
6584                                 case PTP_OPC_ObjectFormat:
6585                                         ob->oi.ObjectFormat = prop->propval.u16;
6586                                         break;
6587                                 case PTP_OPC_ProtectionStatus:
6588                                         ob->oi.ProtectionStatus = prop->propval.u16;
6589                                         break;
6590                                 case PTP_OPC_ObjectSize:
6591                                         if (prop->datatype == PTP_DTC_UINT64) {
6592                                                 if (prop->propval.u64 > 0xFFFFFFFFU)
6593                                                         ob->oi.ObjectCompressedSize = 0xFFFFFFFFU;
6594                                                 else
6595                                                         ob->oi.ObjectCompressedSize = (uint32_t)prop->propval.u64;
6596                                         } else if (prop->datatype == PTP_DTC_UINT32) {
6597                                                 ob->oi.ObjectCompressedSize = prop->propval.u32;
6598                                         }
6599                                         break;
6600                                 case PTP_OPC_AssociationType:
6601                                         ob->oi.AssociationType = prop->propval.u16;
6602                                         break;
6603                                 case PTP_OPC_AssociationDesc:
6604                                         ob->oi.AssociationDesc = prop->propval.u32;
6605                                         break;
6606                                 case PTP_OPC_ObjectFileName:
6607                                         if (prop->propval.str) {
6608                                                 free(ob->oi.Filename);
6609                                                 ob->oi.Filename = strdup(prop->propval.str);
6610                                         }
6611                                         break;
6612                                 case PTP_OPC_DateCreated:
6613                                         ob->oi.CaptureDate = ptp_unpack_PTPTIME(prop->propval.str);
6614                                         break;
6615                                 case PTP_OPC_DateModified:
6616                                         ob->oi.ModificationDate = ptp_unpack_PTPTIME(prop->propval.str);
6617                                         break;
6618                                 case PTP_OPC_Keywords:
6619                                         if (prop->propval.str) {
6620                                                 free(ob->oi.Keywords);
6621                                                 ob->oi.Keywords = strdup(prop->propval.str);
6622                                         }
6623                                         break;
6624                                 case PTP_OPC_ParentObject:
6625                                         ob->oi.ParentObject = prop->propval.u32;
6626                                         break;
6627                                 }
6628                         }
6629                 }
6630
6631 #if 0
6632                 MTPProperties   *xpl;
6633                 int j;
6634                 PTPObjectInfo   oinfo;
6635
6636                 memset (&oinfo,0,sizeof(oinfo));
6637                 /* hmm, not necessary ... only if we would use it */
6638                 for (j=0;j<nrofprops;j++) {
6639                         xpl = &props[j];
6640                         switch (xpl->property) {
6641                         case PTP_OPC_ParentObject:
6642                                 if (xpl->datatype != PTP_DTC_UINT32) {
6643                                         ptp_debug (params, "ptp2/mtpfast: parentobject has type 0x%x???", xpl->datatype);
6644                                         break;
6645                                 }
6646                                 oinfo.ParentObject = xpl->propval.u32;
6647                                 ptp_debug (params, "ptp2/mtpfast: parent 0x%x", xpl->propval.u32);
6648                                 break;
6649                         case PTP_OPC_ObjectFormat:
6650                                 if (xpl->datatype != PTP_DTC_UINT16) {
6651                                         ptp_debug (params, "ptp2/mtpfast: objectformat has type 0x%x???", xpl->datatype);
6652                                         break;
6653                                 }
6654                                 oinfo.ObjectFormat = xpl->propval.u16;
6655                                 ptp_debug (params, "ptp2/mtpfast: ofc 0x%x", xpl->propval.u16);
6656                                 break;
6657                         case PTP_OPC_ObjectSize:
6658                                 switch (xpl->datatype) {
6659                                 case PTP_DTC_UINT32:
6660                                         oinfo.ObjectCompressedSize = xpl->propval.u32;
6661                                         break;
6662                                 case PTP_DTC_UINT64:
6663                                         oinfo.ObjectCompressedSize = xpl->propval.u64;
6664                                         break;
6665                                 default:
6666                                         ptp_debug (params, "ptp2/mtpfast: objectsize has type 0x%x???", xpl->datatype);
6667                                         break;
6668                                 }
6669                                 ptp_debug (params, "ptp2/mtpfast: objectsize %u", xpl->propval.u32);
6670                                 break;
6671                         case PTP_OPC_StorageID:
6672                                 if (xpl->datatype != PTP_DTC_UINT32) {
6673                                         ptp_debug (params, "ptp2/mtpfast: storageid has type 0x%x???", xpl->datatype);
6674                                         break;
6675                                 }
6676                                 oinfo.StorageID = xpl->propval.u32;
6677                                 ptp_debug (params, "ptp2/mtpfast: storageid 0x%x", xpl->propval.u32);
6678                                 break;
6679                         case PTP_OPC_ProtectionStatus:/*UINT16*/
6680                                 if (xpl->datatype != PTP_DTC_UINT16) {
6681                                         ptp_debug (params, "ptp2/mtpfast: protectionstatus has type 0x%x???", xpl->datatype);
6682                                         break;
6683                                 }
6684                                 oinfo.ProtectionStatus = xpl->propval.u16;
6685                                 ptp_debug (params, "ptp2/mtpfast: protection 0x%x", xpl->propval.u16);
6686                                 break;
6687                         case PTP_OPC_ObjectFileName:
6688                                 if (xpl->datatype != PTP_DTC_STR) {
6689                                         ptp_debug (params, "ptp2/mtpfast: filename has type 0x%x???", xpl->datatype);
6690                                         break;
6691                                 }
6692                                 if (xpl->propval.str) {
6693                                         ptp_debug (params, "ptp2/mtpfast: filename %s", xpl->propval.str);
6694                                         oinfo.Filename = strdup(xpl->propval.str);
6695                                 } else {
6696                                         oinfo.Filename = NULL;
6697                                 }
6698                                 break;
6699                         case PTP_OPC_DateCreated:
6700                                 if (xpl->datatype != PTP_DTC_STR) {
6701                                         ptp_debug (params, "ptp2/mtpfast: datecreated has type 0x%x???", xpl->datatype);
6702                                         break;
6703                                 }
6704                                 ptp_debug (params, "ptp2/mtpfast: capturedate %s", xpl->propval.str);
6705                                 oinfo.CaptureDate = ptp_unpack_PTPTIME (xpl->propval.str);
6706                                 break;
6707                         case PTP_OPC_DateModified:
6708                                 if (xpl->datatype != PTP_DTC_STR) {
6709                                         ptp_debug (params, "ptp2/mtpfast: datemodified has type 0x%x???", xpl->datatype);
6710                                         break;
6711                                 }
6712                                 ptp_debug (params, "ptp2/mtpfast: moddate %s", xpl->propval.str);
6713                                 oinfo.ModificationDate = ptp_unpack_PTPTIME (xpl->propval.str);
6714                                 break;
6715                         default:
6716                                 if ((xpl->property & 0xfff0) == 0xdc00)
6717                                         ptp_debug (params, "ptp2/mtpfast:case %x type %x unhandled", xpl->property, xpl->datatype);
6718                                 break;
6719                         }
6720                 }
6721                 if (!oinfo.Filename)
6722                         /* i have one such file on my Creative */
6723                         oinfo.Filename = strdup("<null>");
6724 #endif
6725                 ob->flags |= PTPOBJECT_MTPPROPLIST_LOADED;
6726 fallback:       ;
6727         }
6728         if ((ob->flags & want) == want)
6729                 return PTP_RC_OK;
6730         ptp_debug (params, "ptp_object_want: oid 0x%08x, want flags %x, have only %x?", handle, want, ob->flags);
6731         return PTP_RC_GeneralError;
6732 }
6733
6734
6735 uint16_t
6736 ptp_add_object_to_cache(PTPParams *params, uint32_t handle)
6737 {
6738         PTPObject *ob;
6739         return ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED|PTPOBJECT_MTPPROPLIST_LOADED, &ob);
6740 }