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