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