1/* ptp.c
2 *
3 * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
4 * Copyright (C) 2003-2009 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 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23
24#define _BSD_SOURCE
25#include "config.h"
26#include "ptp.h"
27
28#include <stdlib.h>
29#include <stdarg.h>
30#include <stdio.h>
31#include <string.h>
32#include <unistd.h>
33
34#ifdef ENABLE_NLS
35#  include <libintl.h>
36#  undef _
37#  define _(String) dgettext (PACKAGE, String)
38#  ifdef gettext_noop
39#    define N_(String) gettext_noop (String)
40#  else
41#    define N_(String) (String)
42#  endif
43#else
44#  define textdomain(String) (String)
45#  define gettext(String) (String)
46#  define dgettext(Domain,Message) (Message)
47#  define dcgettext(Domain,Message,Type) (Message)
48#  define bindtextdomain(Domain,Directory) (Domain)
49#  define _(String) (String)
50#  define N_(String) (String)
51#endif
52
53#define CHECK_PTP_RC(result)	{uint16_t r=(result); if (r!=PTP_RC_OK) return r;}
54
55#define PTP_CNT_INIT(cnt) {memset(&cnt,0,sizeof(cnt));}
56
57static uint16_t ptp_exit_recv_memory_handler (PTPDataHandler*,unsigned char**,unsigned long*);
58static uint16_t ptp_init_recv_memory_handler(PTPDataHandler*);
59static uint16_t ptp_init_send_memory_handler(PTPDataHandler*,unsigned char*,unsigned long len);
60static uint16_t ptp_exit_send_memory_handler (PTPDataHandler *handler);
61
62static void
63ptp_debug (PTPParams *params, const char *format, ...)
64{
65        va_list args;
66
67        va_start (args, format);
68        if (params->debug_func!=NULL)
69                params->debug_func (params->data, format, args);
70        else
71	{
72                vfprintf (stderr, format, args);
73		fprintf (stderr,"\n");
74		fflush (stderr);
75	}
76        va_end (args);
77}
78
79static void
80ptp_error (PTPParams *params, const char *format, ...)
81{
82        va_list args;
83
84        va_start (args, format);
85        if (params->error_func!=NULL)
86                params->error_func (params->data, format, args);
87        else
88	{
89                vfprintf (stderr, format, args);
90		fprintf (stderr,"\n");
91		fflush (stderr);
92	}
93        va_end (args);
94}
95
96/* Pack / unpack functions */
97
98#include "ptp-pack.c"
99
100/* major PTP functions */
101
102/* Transaction data phase description */
103#define PTP_DP_NODATA		0x0000	/* no data phase */
104#define PTP_DP_SENDDATA		0x0001	/* sending data */
105#define PTP_DP_GETDATA		0x0002	/* receiving data */
106#define PTP_DP_DATA_MASK	0x00ff	/* data phase mask */
107
108/**
109 * ptp_transaction:
110 * params:	PTPParams*
111 * 		PTPContainer* ptp	- general ptp container
112 * 		uint16_t flags		- lower 8 bits - data phase description
113 * 		unsigned int sendlen	- senddata phase data length
114 * 		char** data		- send or receive data buffer pointer
115 * 		int* recvlen		- receive data length
116 *
117 * Performs PTP transaction. ptp is a PTPContainer with appropriate fields
118 * filled in (i.e. operation code and parameters). It's up to caller to do
119 * so.
120 * The flags decide thether the transaction has a data phase and what is its
121 * direction (send or receive).
122 * If transaction is sending data the sendlen should contain its length in
123 * bytes, otherwise it's ignored.
124 * The data should contain an address of a pointer to data going to be sent
125 * or is filled with such a pointer address if data are received depending
126 * od dataphase direction (send or received) or is beeing ignored (no
127 * dataphase).
128 * The memory for a pointer should be preserved by the caller, if data are
129 * beeing retreived the appropriate amount of memory is beeing allocated
130 * (the caller should handle that!).
131 *
132 * Return values: Some PTP_RC_* code.
133 * Upon success PTPContainer* ptp contains PTP Response Phase container with
134 * all fields filled in.
135 **/
136static uint16_t
137ptp_transaction_new (PTPParams* params, PTPContainer* ptp,
138		uint16_t flags, unsigned int sendlen,
139		PTPDataHandler *handler
140) {
141	int tries;
142
143	if ((params==NULL) || (ptp==NULL))
144		return PTP_ERROR_BADPARAM;
145
146	ptp->Transaction_ID=params->transaction_id++;
147	ptp->SessionID=params->session_id;
148	/* send request */
149	CHECK_PTP_RC(params->sendreq_func (params, ptp));
150	/* is there a dataphase? */
151	switch (flags&PTP_DP_DATA_MASK) {
152	case PTP_DP_SENDDATA:
153		{
154			uint16_t ret;
155			ret = params->senddata_func(params, ptp,
156						    sendlen, handler);
157			if (ret == PTP_ERROR_CANCEL) {
158				ret = params->cancelreq_func(params,
159							     params->transaction_id-1);
160				if (ret == PTP_RC_OK)
161					ret = PTP_ERROR_CANCEL;
162			}
163			if (ret != PTP_RC_OK)
164				return ret;
165		}
166		break;
167	case PTP_DP_GETDATA:
168		{
169			uint16_t ret;
170			ret = params->getdata_func(params, ptp, handler);
171			if (ret == PTP_ERROR_CANCEL) {
172				ret = params->cancelreq_func(params,
173							     params->transaction_id-1);
174				if (ret == PTP_RC_OK)
175					ret = PTP_ERROR_CANCEL;
176			}
177			if (ret != PTP_RC_OK)
178				return ret;
179		}
180		break;
181	case PTP_DP_NODATA:
182		break;
183	default:
184		return PTP_ERROR_BADPARAM;
185	}
186	tries = 3;
187	while (1) {
188		/* get response */
189		CHECK_PTP_RC(params->getresp_func(params, ptp));
190		if (ptp->Transaction_ID != params->transaction_id-1) {
191			/* try to clean up potential left overs from previous session */
192			if ((ptp->Code == PTP_OC_OpenSession) && tries--)
193				continue;
194			ptp_error (params,
195				"PTP: Sequence number mismatch %d vs expected %d.",
196				ptp->Transaction_ID, params->transaction_id-1
197			);
198			return PTP_ERROR_BADPARAM;
199		}
200		break;
201	}
202	return ptp->Code;
203}
204
205/* memory data get/put handler */
206typedef struct {
207	unsigned char	*data;
208	unsigned long	size, curoff;
209} PTPMemHandlerPrivate;
210
211static uint16_t
212memory_getfunc(PTPParams* params, void* private,
213	       unsigned long wantlen, unsigned char *data,
214	       unsigned long *gotlen
215) {
216	PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private;
217	unsigned long tocopy = wantlen;
218
219	if (priv->curoff + tocopy > priv->size)
220		tocopy = priv->size - priv->curoff;
221	memcpy (data, priv->data + priv->curoff, tocopy);
222	priv->curoff += tocopy;
223	*gotlen = tocopy;
224	return PTP_RC_OK;
225}
226
227static uint16_t
228memory_putfunc(PTPParams* params, void* private,
229	       unsigned long sendlen, unsigned char *data,
230	       unsigned long *putlen
231) {
232	PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private;
233
234	if (priv->curoff + sendlen > priv->size) {
235		priv->data = realloc (priv->data, priv->curoff+sendlen);
236		priv->size = priv->curoff + sendlen;
237	}
238	memcpy (priv->data + priv->curoff, data, sendlen);
239	priv->curoff += sendlen;
240	*putlen = sendlen;
241	return PTP_RC_OK;
242}
243
244/* init private struct for receiving data. */
245static uint16_t
246ptp_init_recv_memory_handler(PTPDataHandler *handler) {
247	PTPMemHandlerPrivate* priv;
248	priv = malloc (sizeof(PTPMemHandlerPrivate));
249	handler->priv = priv;
250	handler->getfunc = memory_getfunc;
251	handler->putfunc = memory_putfunc;
252	priv->data = NULL;
253	priv->size = 0;
254	priv->curoff = 0;
255	return PTP_RC_OK;
256}
257
258/* init private struct and put data in for sending data.
259 * data is still owned by caller.
260 */
261static uint16_t
262ptp_init_send_memory_handler(PTPDataHandler *handler,
263	unsigned char *data, unsigned long len
264) {
265	PTPMemHandlerPrivate* priv;
266	priv = malloc (sizeof(PTPMemHandlerPrivate));
267	if (!priv)
268		return PTP_RC_GeneralError;
269	handler->priv = priv;
270	handler->getfunc = memory_getfunc;
271	handler->putfunc = memory_putfunc;
272	priv->data = data;
273	priv->size = len;
274	priv->curoff = 0;
275	return PTP_RC_OK;
276}
277
278/* free private struct + data */
279static uint16_t
280ptp_exit_send_memory_handler (PTPDataHandler *handler) {
281	PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->priv;
282	/* data is owned by caller */
283	free (priv);
284	return PTP_RC_OK;
285}
286
287/* hand over our internal data to caller */
288static uint16_t
289ptp_exit_recv_memory_handler (PTPDataHandler *handler,
290	unsigned char **data, unsigned long *size
291) {
292	PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->priv;
293	*data = priv->data;
294	*size = priv->size;
295	free (priv);
296	return PTP_RC_OK;
297}
298
299/* fd data get/put handler */
300typedef struct {
301	int fd;
302} PTPFDHandlerPrivate;
303
304static uint16_t
305fd_getfunc(PTPParams* params, void* private,
306	       unsigned long wantlen, unsigned char *data,
307	       unsigned long *gotlen
308) {
309	PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)private;
310	int		got;
311
312	got = read (priv->fd, data, wantlen);
313	if (got != -1)
314		*gotlen = got;
315	else
316		return PTP_RC_GeneralError;
317	return PTP_RC_OK;
318}
319
320static uint16_t
321fd_putfunc(PTPParams* params, void* private,
322	       unsigned long sendlen, unsigned char *data,
323	       unsigned long *putlen
324) {
325	int		written;
326	PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)private;
327
328	written = write (priv->fd, data, sendlen);
329	if (written != -1)
330		*putlen = written;
331	else
332		return PTP_RC_GeneralError;
333	return PTP_RC_OK;
334}
335
336static uint16_t
337ptp_init_fd_handler(PTPDataHandler *handler, int fd) {
338	PTPFDHandlerPrivate* priv;
339	priv = malloc (sizeof(PTPFDHandlerPrivate));
340	handler->priv = priv;
341	handler->getfunc = fd_getfunc;
342	handler->putfunc = fd_putfunc;
343	priv->fd = fd;
344	return PTP_RC_OK;
345}
346
347static uint16_t
348ptp_exit_fd_handler (PTPDataHandler *handler) {
349	PTPFDHandlerPrivate* priv = (PTPFDHandlerPrivate*)handler->priv;
350	free (priv);
351	return PTP_RC_OK;
352}
353
354/* Old style transaction, based on memory */
355static uint16_t
356ptp_transaction (PTPParams* params, PTPContainer* ptp,
357		uint16_t flags, unsigned int sendlen,
358		unsigned char **data, unsigned int *recvlen
359) {
360	PTPDataHandler	handler;
361	uint16_t	ret;
362
363	switch (flags & PTP_DP_DATA_MASK) {
364	case PTP_DP_SENDDATA:
365		ptp_init_send_memory_handler (&handler, *data, sendlen);
366		break;
367	case PTP_DP_GETDATA:
368		ptp_init_recv_memory_handler (&handler);
369		break;
370	default:break;
371	}
372	ret = ptp_transaction_new (params, ptp, flags, sendlen, &handler);
373	switch (flags & PTP_DP_DATA_MASK) {
374	case PTP_DP_SENDDATA:
375		ptp_exit_send_memory_handler (&handler);
376		break;
377	case PTP_DP_GETDATA: {
378		unsigned long len;
379		ptp_exit_recv_memory_handler (&handler, data, &len);
380		if (recvlen)
381			*recvlen = len;
382		break;
383	}
384	default:break;
385	}
386	return ret;
387}
388
389
390/**
391 * PTP operation functions
392 *
393 * all ptp_ functions should take integer parameters
394 * in host byte order!
395 **/
396
397
398/**
399 * ptp_getdeviceinfo:
400 * params:	PTPParams*
401 *
402 * Gets device info dataset and fills deviceinfo structure.
403 *
404 * Return values: Some PTP_RC_* code.
405 **/
406uint16_t
407ptp_getdeviceinfo (PTPParams* params, PTPDeviceInfo* deviceinfo)
408{
409	uint16_t 	ret;
410	unsigned long	len;
411	PTPContainer	ptp;
412	unsigned char*	di=NULL;
413	PTPDataHandler	handler;
414
415	ptp_init_recv_memory_handler (&handler);
416	PTP_CNT_INIT(ptp);
417	ptp.Code=PTP_OC_GetDeviceInfo;
418	ptp.Nparam=0;
419	len=0;
420	ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
421	ptp_exit_recv_memory_handler (&handler, &di, &len);
422	if (!di) ret = PTP_RC_GeneralError;
423	if (ret == PTP_RC_OK) ptp_unpack_DI(params, di, deviceinfo, len);
424	free(di);
425	return ret;
426}
427
428uint16_t
429ptp_canon_eos_getdeviceinfo (PTPParams* params, PTPCanonEOSDeviceInfo*di)
430{
431	uint16_t 	ret;
432	PTPContainer	ptp;
433	PTPDataHandler	handler;
434	unsigned long	len;
435	unsigned char	*data;
436
437	ptp_init_recv_memory_handler (&handler);
438	PTP_CNT_INIT(ptp);
439	ptp.Code=PTP_OC_CANON_EOS_GetDeviceInfoEx;
440	ptp.Nparam=0;
441	len=0;
442	data=NULL;
443	ret=ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
444	ptp_exit_recv_memory_handler (&handler, &data, &len);
445	if (ret == PTP_RC_OK) ptp_unpack_EOS_DI(params, data, di, len);
446	free (data);
447	return ret;
448}
449
450/**
451 * ptp_generic_no_data:
452 * params:	PTPParams*
453 * 		code	PTP OP Code
454 * 		n_param	count of parameters
455 *		... variable argument list ...
456 *
457 * Emits a generic PTP command without any data transfer.
458 *
459 * Return values: Some PTP_RC_* code.
460 **/
461uint16_t
462ptp_generic_no_data (PTPParams* params, uint16_t code, unsigned int n_param, ...)
463{
464	PTPContainer ptp;
465	va_list args;
466	int i;
467
468	if( n_param > 5 )
469		return PTP_RC_InvalidParameter;
470
471	PTP_CNT_INIT(ptp);
472	ptp.Code=code;
473	ptp.Nparam=n_param;
474
475	va_start(args, n_param);
476	for( i=0; i<n_param; ++i )
477		(&ptp.Param1)[i] = va_arg(args, uint32_t);
478	va_end(args);
479
480	return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
481}
482
483/**
484 * ptp_opensession:
485 * params:	PTPParams*
486 * 		session			- session number
487 *
488 * Establishes a new session.
489 *
490 * Return values: Some PTP_RC_* code.
491 **/
492uint16_t
493ptp_opensession (PTPParams* params, uint32_t session)
494{
495	uint16_t ret;
496	PTPContainer ptp;
497
498	ptp_debug(params,"PTP: Opening session");
499
500	/* SessonID field of the operation dataset should always
501	   be set to 0 for OpenSession request! */
502	params->session_id=0x00000000;
503	/* TransactionID should be set to 0 also! */
504	params->transaction_id=0x0000000;
505	/* zero out response packet buffer */
506	params->response_packet = NULL;
507	params->response_packet_size = 0;
508	/* no split headers */
509	params->split_header_data = 0;
510
511	PTP_CNT_INIT(ptp);
512	ptp.Code=PTP_OC_OpenSession;
513	ptp.Param1=session;
514	ptp.Nparam=1;
515	ret=ptp_transaction_new(params, &ptp, PTP_DP_NODATA, 0, NULL);
516	/* now set the global session id to current session number */
517	params->session_id=session;
518	return ret;
519}
520
521/**
522 * ptp_free_params:
523 * params:	PTPParams*
524 *
525 * Frees all data within the PTPParams struct.
526 *
527 * Return values: Some PTP_RC_* code.
528 **/
529void
530ptp_free_params (PTPParams *params) {
531	int i;
532
533	if (params->cameraname) free (params->cameraname);
534	if (params->wifi_profiles) free (params->wifi_profiles);
535	for (i=0;i<params->nrofobjects;i++)
536		ptp_free_object (&params->objects[i]);
537	free (params->objects);
538	ptp_free_DI (&params->deviceinfo);
539}
540
541/**
542 * ptp_getststorageids:
543 * params:	PTPParams*
544 *
545 * Gets array of StorageIDs and fills the storageids structure.
546 *
547 * Return values: Some PTP_RC_* code.
548 **/
549uint16_t
550ptp_getstorageids (PTPParams* params, PTPStorageIDs* storageids)
551{
552	uint16_t ret;
553	PTPContainer ptp;
554	unsigned int len;
555	unsigned char* sids=NULL;
556
557	PTP_CNT_INIT(ptp);
558	ptp.Code=PTP_OC_GetStorageIDs;
559	ptp.Nparam=0;
560	len=0;
561	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &sids, &len);
562	if (ret == PTP_RC_OK) ptp_unpack_SIDs(params, sids, storageids, len);
563	free(sids);
564	return ret;
565}
566
567/**
568 * ptp_getststorageinfo:
569 * params:	PTPParams*
570 *		storageid		- StorageID
571 *
572 * Gets StorageInfo dataset of desired storage and fills storageinfo
573 * structure.
574 *
575 * Return values: Some PTP_RC_* code.
576 **/
577uint16_t
578ptp_getstorageinfo (PTPParams* params, uint32_t storageid,
579			PTPStorageInfo* storageinfo)
580{
581	uint16_t ret;
582	PTPContainer ptp;
583	unsigned char* si=NULL;
584	unsigned int len;
585
586	PTP_CNT_INIT(ptp);
587	ptp.Code=PTP_OC_GetStorageInfo;
588	ptp.Param1=storageid;
589	ptp.Nparam=1;
590	len=0;
591	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &si, &len);
592	if (ret == PTP_RC_OK) ptp_unpack_SI(params, si, storageinfo, len);
593	free(si);
594	return ret;
595}
596
597/**
598 * ptp_getobjecthandles:
599 * params:	PTPParams*
600 *		storage			- StorageID
601 *		objectformatcode	- ObjectFormatCode (optional)
602 *		associationOH		- ObjectHandle of Association for
603 *					  wich a list of children is desired
604 *					  (optional)
605 *		objecthandles		- pointer to structute
606 *
607 * Fills objecthandles with structure returned by device.
608 *
609 * Return values: Some PTP_RC_* code.
610 **/
611uint16_t
612ptp_getobjecthandles (PTPParams* params, uint32_t storage,
613			uint32_t objectformatcode, uint32_t associationOH,
614			PTPObjectHandles* objecthandles)
615{
616	uint16_t ret;
617	PTPContainer ptp;
618	unsigned char* oh=NULL;
619	unsigned int len;
620
621	PTP_CNT_INIT(ptp);
622	ptp.Code=PTP_OC_GetObjectHandles;
623	ptp.Param1=storage;
624	ptp.Param2=objectformatcode;
625	ptp.Param3=associationOH;
626	ptp.Nparam=3;
627	len=0;
628	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oh, &len);
629	if (ret == PTP_RC_OK) {
630		ptp_unpack_OH(params, oh, objecthandles, len);
631	} else {
632		if (	(storage == 0xffffffff) &&
633			(objectformatcode == 0) &&
634			(associationOH == 0)
635		) {
636			/* When we query all object handles on all stores and
637			 * get an error -> just handle it as "0 handles".
638			 */
639			objecthandles->Handler = NULL;
640			objecthandles->n = 0;
641			ret = PTP_RC_OK;
642		}
643	}
644	free(oh);
645	return ret;
646}
647
648/**
649 * ptp_getnumobjects:
650 * params:	PTPParams*
651 *		storage			- StorageID
652 *		objectformatcode	- ObjectFormatCode (optional)
653 *		associationOH		- ObjectHandle of Association for
654 *					  wich a list of children is desired
655 *					  (optional)
656 *		numobs			- pointer to uint32_t that takes number of objects
657 *
658 * Fills numobs with number of objects on device.
659 *
660 * Return values: Some PTP_RC_* code.
661 **/
662uint16_t
663ptp_getnumobjects (PTPParams* params, uint32_t storage,
664			uint32_t objectformatcode, uint32_t associationOH,
665			uint32_t* numobs)
666{
667	uint16_t ret;
668	PTPContainer ptp;
669	int len;
670
671	PTP_CNT_INIT(ptp);
672	ptp.Code=PTP_OC_GetNumObjects;
673	ptp.Param1=storage;
674	ptp.Param2=objectformatcode;
675	ptp.Param3=associationOH;
676	ptp.Nparam=3;
677	len=0;
678	ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
679	if (ret == PTP_RC_OK) {
680		if (ptp.Nparam >= 1)
681			*numobs = ptp.Param1;
682		else
683			ret = PTP_RC_GeneralError;
684	}
685	return ret;
686}
687
688/**
689 * ptp_getobjectinfo:
690 * params:	PTPParams*
691 *		handle			- Object handle
692 *		objectinfo		- pointer to objectinfo that is returned
693 *
694 * Get objectinfo structure for handle from device.
695 *
696 * Return values: Some PTP_RC_* code.
697 **/
698uint16_t
699ptp_getobjectinfo (PTPParams* params, uint32_t handle,
700			PTPObjectInfo* objectinfo)
701{
702	uint16_t ret;
703	PTPContainer ptp;
704	unsigned char* oi=NULL;
705	unsigned int len;
706
707	PTP_CNT_INIT(ptp);
708	ptp.Code=PTP_OC_GetObjectInfo;
709	ptp.Param1=handle;
710	ptp.Nparam=1;
711	len=0;
712	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oi, &len);
713	if (ret == PTP_RC_OK) ptp_unpack_OI(params, oi, objectinfo, len);
714	free(oi);
715	return ret;
716}
717
718/**
719 * ptp_getobject:
720 * params:	PTPParams*
721 *		handle			- Object handle
722 *		object			- pointer to data area
723 *
724 * Get object 'handle' from device and store the data in newly
725 * allocated 'object'.
726 *
727 * Return values: Some PTP_RC_* code.
728 **/
729uint16_t
730ptp_getobject (PTPParams* params, uint32_t handle, unsigned char** object)
731{
732	PTPContainer ptp;
733	unsigned int len;
734
735	PTP_CNT_INIT(ptp);
736	ptp.Code=PTP_OC_GetObject;
737	ptp.Param1=handle;
738	ptp.Nparam=1;
739	len=0;
740	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, &len);
741}
742
743/**
744 * ptp_getobject_to_handler:
745 * params:	PTPParams*
746 *		handle			- Object handle
747 *		PTPDataHandler*		- pointer datahandler
748 *
749 * Get object 'handle' from device and store the data in newly
750 * allocated 'object'.
751 *
752 * Return values: Some PTP_RC_* code.
753 **/
754uint16_t
755ptp_getobject_to_handler (PTPParams* params, uint32_t handle, PTPDataHandler *handler)
756{
757	PTPContainer ptp;
758
759	PTP_CNT_INIT(ptp);
760	ptp.Code=PTP_OC_GetObject;
761	ptp.Param1=handle;
762	ptp.Nparam=1;
763	return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler);
764}
765
766/**
767 * ptp_getobject_tofd:
768 * params:	PTPParams*
769 *		handle			- Object handle
770 *		fd                      - File descriptor to write() to
771 *
772 * Get object 'handle' from device and write the data to the
773 * given file descriptor.
774 *
775 * Return values: Some PTP_RC_* code.
776 **/
777uint16_t
778ptp_getobject_tofd (PTPParams* params, uint32_t handle, int fd)
779{
780	PTPContainer	ptp;
781	PTPDataHandler	handler;
782	uint16_t	ret;
783
784	ptp_init_fd_handler (&handler, fd);
785	PTP_CNT_INIT(ptp);
786	ptp.Code=PTP_OC_GetObject;
787	ptp.Param1=handle;
788	ptp.Nparam=1;
789	ret = ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
790	ptp_exit_fd_handler (&handler);
791	return ret;
792}
793
794/**
795 * ptp_getpartialobject:
796 * params:	PTPParams*
797 *		handle			- Object handle
798 *		offset			- Offset into object
799 *		maxbytes		- Maximum of bytes to read
800 *		object			- pointer to data area
801 *
802 * Get object 'handle' from device and store the data in newly
803 * allocated 'object'. Start from offset and read at most maxbytes.
804 *
805 * Return values: Some PTP_RC_* code.
806 **/
807uint16_t
808ptp_getpartialobject (PTPParams* params, uint32_t handle, uint32_t offset,
809			uint32_t maxbytes, unsigned char** object)
810{
811	PTPContainer ptp;
812	unsigned int len;
813
814	PTP_CNT_INIT(ptp);
815	ptp.Code=PTP_OC_GetPartialObject;
816	ptp.Param1=handle;
817	ptp.Param2=offset;
818	ptp.Param3=maxbytes;
819	ptp.Nparam=3;
820	len=0;
821	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, &len);
822}
823
824/**
825 * ptp_getthumb:
826 * params:	PTPParams*
827 *		handle			- Object handle
828 *		object			- pointer to data area
829 *
830 * Get thumb for object 'handle' from device and store the data in newly
831 * allocated 'object'.
832 *
833 * Return values: Some PTP_RC_* code.
834 **/
835uint16_t
836ptp_getthumb (PTPParams* params, uint32_t handle, unsigned char** object)
837{
838	PTPContainer ptp;
839	unsigned int len;
840
841	PTP_CNT_INIT(ptp);
842	ptp.Code=PTP_OC_GetThumb;
843	ptp.Param1=handle;
844	ptp.Nparam=1;
845	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, &len);
846}
847
848/**
849 * ptp_deleteobject:
850 * params:	PTPParams*
851 *		handle			- object handle
852 *		ofc			- object format code (optional)
853 *
854 * Deletes desired objects.
855 *
856 * Return values: Some PTP_RC_* code.
857 **/
858uint16_t
859ptp_deleteobject (PTPParams* params, uint32_t handle, uint32_t ofc)
860{
861	PTPContainer ptp;
862	uint16_t ret;
863
864	PTP_CNT_INIT(ptp);
865	ptp.Code=PTP_OC_DeleteObject;
866	ptp.Param1=handle;
867	ptp.Param2=ofc;
868	ptp.Nparam=2;
869	ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
870	if (ret != PTP_RC_OK) {
871		return ret;
872	}
873	/* If the object is cached and could be removed, cleanse cache. */
874	ptp_remove_object_from_cache(params, handle);
875	return PTP_RC_OK;
876}
877
878/**
879 * ptp_sendobjectinfo:
880 * params:	PTPParams*
881 *		uint32_t* store		- destination StorageID on Responder
882 *		uint32_t* parenthandle 	- Parent ObjectHandle on responder
883 * 		uint32_t* handle	- see Return values
884 *		PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
885 *
886 * Sends ObjectInfo of file that is to be sent via SendFileObject.
887 *
888 * Return values: Some PTP_RC_* code.
889 * Upon success : uint32_t* store	- Responder StorageID in which
890 *					  object will be stored
891 *		  uint32_t* parenthandle- Responder Parent ObjectHandle
892 *					  in which the object will be stored
893 *		  uint32_t* handle	- Responder's reserved ObjectHandle
894 *					  for the incoming object
895 **/
896uint16_t
897ptp_sendobjectinfo (PTPParams* params, uint32_t* store,
898			uint32_t* parenthandle, uint32_t* handle,
899			PTPObjectInfo* objectinfo)
900{
901	uint16_t ret;
902	PTPContainer ptp;
903	unsigned char* oidata=NULL;
904	uint32_t size;
905
906	PTP_CNT_INIT(ptp);
907	ptp.Code=PTP_OC_SendObjectInfo;
908	ptp.Param1=*store;
909	ptp.Param2=*parenthandle;
910	ptp.Nparam=2;
911
912	size=ptp_pack_OI(params, objectinfo, &oidata);
913	ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata, NULL);
914	free(oidata);
915	*store=ptp.Param1;
916	*parenthandle=ptp.Param2;
917	*handle=ptp.Param3;
918	return ret;
919}
920
921/**
922 * ptp_sendobject:
923 * params:	PTPParams*
924 *		char*	object		- contains the object that is to be sent
925 *		uint32_t size		- object size
926 *
927 * Sends object to Responder.
928 *
929 * Return values: Some PTP_RC_* code.
930 *
931 */
932uint16_t
933ptp_sendobject (PTPParams* params, unsigned char* object, uint32_t size)
934{
935	PTPContainer ptp;
936
937	PTP_CNT_INIT(ptp);
938	ptp.Code=PTP_OC_SendObject;
939	ptp.Nparam=0;
940
941	return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object, NULL);
942}
943
944/**
945 * ptp_sendobject_from_handler:
946 * params:	PTPParams*
947 *		PTPDataHandler*         - File descriptor to read() object from
948 *              uint32_t size           - File/object size
949 *
950 * Sends object from file descriptor by consecutive reads from this
951 * descriptor.
952 *
953 * Return values: Some PTP_RC_* code.
954 **/
955uint16_t
956ptp_sendobject_from_handler (PTPParams* params, PTPDataHandler *handler, uint32_t size)
957{
958	PTPContainer	ptp;
959
960	PTP_CNT_INIT(ptp);
961	ptp.Code=PTP_OC_SendObject;
962	ptp.Nparam=0;
963	return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler);
964}
965
966
967/**
968 * ptp_sendobject_fromfd:
969 * params:	PTPParams*
970 *		fd                      - File descriptor to read() object from
971 *              uint32_t size           - File/object size
972 *
973 * Sends object from file descriptor by consecutive reads from this
974 * descriptor.
975 *
976 * Return values: Some PTP_RC_* code.
977 **/
978uint16_t
979ptp_sendobject_fromfd (PTPParams* params, int fd, uint32_t size)
980{
981	PTPContainer	ptp;
982	PTPDataHandler	handler;
983	uint16_t	ret;
984
985	ptp_init_fd_handler (&handler, fd);
986	PTP_CNT_INIT(ptp);
987	ptp.Code=PTP_OC_SendObject;
988	ptp.Nparam=0;
989	ret = ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, &handler);
990	ptp_exit_fd_handler (&handler);
991	return ret;
992}
993
994
995uint16_t
996ptp_getdevicepropdesc (PTPParams* params, uint16_t propcode,
997			PTPDevicePropDesc* devicepropertydesc)
998{
999	PTPContainer ptp;
1000	uint16_t ret;
1001	unsigned int len;
1002	unsigned char* dpd=NULL;
1003
1004	PTP_CNT_INIT(ptp);
1005	ptp.Code=PTP_OC_GetDevicePropDesc;
1006	ptp.Param1=propcode;
1007	ptp.Nparam=1;
1008	len=0;
1009	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpd, &len);
1010	if (ret == PTP_RC_OK) ptp_unpack_DPD(params, dpd, devicepropertydesc, len);
1011	free(dpd);
1012	return ret;
1013}
1014
1015
1016uint16_t
1017ptp_getdevicepropvalue (PTPParams* params, uint16_t propcode,
1018			PTPPropertyValue* value, uint16_t datatype)
1019{
1020	PTPContainer ptp;
1021	uint16_t ret;
1022	unsigned int len;
1023	int offset;
1024	unsigned char* dpv=NULL;
1025
1026
1027	PTP_CNT_INIT(ptp);
1028	ptp.Code=PTP_OC_GetDevicePropValue;
1029	ptp.Param1=propcode;
1030	ptp.Nparam=1;
1031	len=offset=0;
1032	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpv, &len);
1033	if (ret == PTP_RC_OK) ptp_unpack_DPV(params, dpv, &offset, len, value, datatype);
1034	free(dpv);
1035	return ret;
1036}
1037
1038uint16_t
1039ptp_setdevicepropvalue (PTPParams* params, uint16_t propcode,
1040			PTPPropertyValue *value, uint16_t datatype)
1041{
1042	PTPContainer ptp;
1043	uint16_t ret;
1044	uint32_t size;
1045	unsigned char* dpv=NULL;
1046
1047	PTP_CNT_INIT(ptp);
1048	ptp.Code=PTP_OC_SetDevicePropValue;
1049	ptp.Param1=propcode;
1050	ptp.Nparam=1;
1051	size=ptp_pack_DPV(params, value, &dpv, datatype);
1052	ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &dpv, NULL);
1053	free(dpv);
1054	return ret;
1055}
1056
1057/**
1058 * ptp_ek_sendfileobjectinfo:
1059 * params:	PTPParams*
1060 *		uint32_t* store		- destination StorageID on Responder
1061 *		uint32_t* parenthandle 	- Parent ObjectHandle on responder
1062 * 		uint32_t* handle	- see Return values
1063 *		PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
1064 *
1065 * Sends ObjectInfo of file that is to be sent via SendFileObject.
1066 *
1067 * Return values: Some PTP_RC_* code.
1068 * Upon success : uint32_t* store	- Responder StorageID in which
1069 *					  object will be stored
1070 *		  uint32_t* parenthandle- Responder Parent ObjectHandle
1071 *					  in which the object will be stored
1072 *		  uint32_t* handle	- Responder's reserved ObjectHandle
1073 *					  for the incoming object
1074 **/
1075uint16_t
1076ptp_ek_sendfileobjectinfo (PTPParams* params, uint32_t* store,
1077			uint32_t* parenthandle, uint32_t* handle,
1078			PTPObjectInfo* objectinfo)
1079{
1080	uint16_t ret;
1081	PTPContainer ptp;
1082	unsigned char* oidata=NULL;
1083	uint32_t size;
1084
1085	PTP_CNT_INIT(ptp);
1086	ptp.Code=PTP_OC_EK_SendFileObjectInfo;
1087	ptp.Param1=*store;
1088	ptp.Param2=*parenthandle;
1089	ptp.Nparam=2;
1090
1091	size=ptp_pack_OI(params, objectinfo, &oidata);
1092	ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata, NULL);
1093	free(oidata);
1094	*store=ptp.Param1;
1095	*parenthandle=ptp.Param2;
1096	*handle=ptp.Param3;
1097	return ret;
1098}
1099
1100/**
1101 * ptp_ek_getserial:
1102 * params:	PTPParams*
1103 *		char**	serial		- contains the serial number of the camera
1104 *		uint32_t* size		- contains the string length
1105 *
1106 * Gets the serial number from the device. (ptp serial)
1107 *
1108 * Return values: Some PTP_RC_* code.
1109 *
1110 */
1111uint16_t
1112ptp_ek_getserial (PTPParams* params, unsigned char **data, unsigned int *size)
1113{
1114	PTPContainer ptp;
1115
1116	PTP_CNT_INIT(ptp);
1117	ptp.Code   = PTP_OC_EK_GetSerial;
1118	ptp.Nparam = 0;
1119	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
1120}
1121
1122/**
1123 * ptp_ek_setserial:
1124 * params:	PTPParams*
1125 *		char*	serial		- contains the new serial number
1126 *		uint32_t size		- string length
1127 *
1128 * Sets the serial number of the device. (ptp serial)
1129 *
1130 * Return values: Some PTP_RC_* code.
1131 *
1132 */
1133uint16_t
1134ptp_ek_setserial (PTPParams* params, unsigned char *data, unsigned int size)
1135{
1136	PTPContainer ptp;
1137
1138	PTP_CNT_INIT(ptp);
1139	ptp.Code   = PTP_OC_EK_SetSerial;
1140	ptp.Nparam = 0;
1141	return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
1142}
1143
1144/* unclear what it does yet */
1145uint16_t
1146ptp_ek_9007 (PTPParams* params, unsigned char **data, unsigned int *size)
1147{
1148	PTPContainer ptp;
1149
1150	PTP_CNT_INIT(ptp);
1151	ptp.Code   = 0x9007;
1152	ptp.Nparam = 0;
1153	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
1154}
1155
1156/* unclear what it does yet */
1157uint16_t
1158ptp_ek_9009 (PTPParams* params, uint32_t *p1, uint32_t *p2)
1159{
1160	PTPContainer	ptp;
1161	uint16_t	ret;
1162
1163	PTP_CNT_INIT(ptp);
1164	ptp.Code   = 0x9009;
1165	ptp.Nparam = 0;
1166	ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
1167	*p1 = ptp.Param1;
1168	*p2 = ptp.Param2;
1169	return ret;
1170}
1171
1172/* unclear yet, but I guess it returns the info from 9008 */
1173uint16_t
1174ptp_ek_900c (PTPParams* params, unsigned char **data, unsigned int *size)
1175{
1176	PTPContainer ptp;
1177
1178	PTP_CNT_INIT(ptp);
1179	ptp.Code   = 0x900c;
1180	ptp.Nparam = 0;
1181	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
1182	/* returned data is 16bit,16bit,32bit,32bit */
1183}
1184
1185/**
1186 * ptp_ek_settext:
1187 * params:	PTPParams*
1188 *		PTPEKTextParams*	- contains the texts to display.
1189 *
1190 * Displays the specified texts on the TFT of the camera.
1191 *
1192 * Return values: Some PTP_RC_* code.
1193 *
1194 */
1195uint16_t
1196ptp_ek_settext (PTPParams* params, PTPEKTextParams *text)
1197{
1198	PTPContainer ptp;
1199	uint16_t ret;
1200	unsigned int size;
1201	unsigned char *data;
1202
1203	PTP_CNT_INIT(ptp);
1204	ptp.Code   = PTP_OC_EK_SetText;
1205	ptp.Nparam = 0;
1206	if (0 == (size = ptp_pack_EK_text(params, text, &data)))
1207		return PTP_ERROR_BADPARAM;
1208	ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
1209	free(data);
1210	return ret;
1211}
1212
1213/**
1214 * ptp_ek_sendfileobject:
1215 * params:	PTPParams*
1216 *		char*	object		- contains the object that is to be sent
1217 *		uint32_t size		- object size
1218 *
1219 * Sends object to Responder.
1220 *
1221 * Return values: Some PTP_RC_* code.
1222 *
1223 */
1224uint16_t
1225ptp_ek_sendfileobject (PTPParams* params, unsigned char* object, uint32_t size)
1226{
1227	PTPContainer ptp;
1228
1229	PTP_CNT_INIT(ptp);
1230	ptp.Code=PTP_OC_EK_SendFileObject;
1231	ptp.Nparam=0;
1232
1233	return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object, NULL);
1234}
1235
1236/**
1237 * ptp_ek_sendfileobject_from_handler:
1238 * params:	PTPParams*
1239 *		PTPDataHandler*	handler	- contains the handler of the object that is to be sent
1240 *		uint32_t size		- object size
1241 *
1242 * Sends object to Responder.
1243 *
1244 * Return values: Some PTP_RC_* code.
1245 *
1246 */
1247uint16_t
1248ptp_ek_sendfileobject_from_handler (PTPParams* params, PTPDataHandler*handler, uint32_t size)
1249{
1250	PTPContainer ptp;
1251
1252	PTP_CNT_INIT(ptp);
1253	ptp.Code=PTP_OC_EK_SendFileObject;
1254	ptp.Nparam=0;
1255	return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler);
1256}
1257
1258/*************************************************************************
1259 *
1260 * Canon PTP extensions support
1261 *
1262 * (C) Nikolai Kopanygin 2003
1263 *
1264 *************************************************************************/
1265
1266
1267/**
1268 * ptp_canon_getpartialobjectinfo:
1269 * params:	PTPParams*
1270 *		uint32_t handle		- ObjectHandle
1271 *		uint32_t p2 		- Not fully understood parameter
1272 *					  0 - returns full size
1273 *					  1 - returns thumbnail size (or EXIF?)
1274 *
1275 * Gets form the responder the size of the specified object.
1276 *
1277 * Return values: Some PTP_RC_* code.
1278 * Upon success : uint32_t* size	- The object size
1279 *		  uint32_t* rp2		- Still unknown return parameter
1280 *                                        (perhaps upper 32bit of size)
1281 *
1282 *
1283 **/
1284uint16_t
1285ptp_canon_getpartialobjectinfo (PTPParams* params, uint32_t handle, uint32_t p2,
1286			uint32_t* size, uint32_t* rp2)
1287{
1288	uint16_t ret;
1289	PTPContainer ptp;
1290
1291	PTP_CNT_INIT(ptp);
1292	ptp.Code=PTP_OC_CANON_GetPartialObjectInfo;
1293	ptp.Param1=handle;
1294	ptp.Param2=p2;
1295	ptp.Nparam=2;
1296	ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
1297	*size=ptp.Param1;
1298	*rp2=ptp.Param2;
1299	return ret;
1300}
1301
1302/**
1303 * ptp_canon_get_mac_address:
1304 * params:	PTPParams*
1305 *					  value 0 works.
1306 * Gets the MAC address of the wireless transmitter.
1307 *
1308 * Return values: Some PTP_RC_* code.
1309 * Upon success : unsigned char* mac	- The MAC address
1310 *
1311 **/
1312uint16_t
1313ptp_canon_get_mac_address (PTPParams* params, unsigned char **mac)
1314{
1315	PTPContainer ptp;
1316	unsigned int size = 0;
1317
1318	PTP_CNT_INIT(ptp);
1319	ptp.Code=PTP_OC_CANON_GetMACAddress;
1320	ptp.Nparam=0;
1321	*mac = NULL;
1322	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, mac, &size);
1323}
1324
1325/**
1326 * ptp_canon_get_directory:
1327 * params:	PTPParams*
1328
1329 * Gets the full directory of the camera.
1330 *
1331 * Return values: Some PTP_RC_* code.
1332 * Upon success : PTPObjectHandles        *handles	- filled out with handles
1333 * 		  PTPObjectInfo           **oinfos	- allocated array of PTP Object Infos
1334 * 		  uint32_t                **flags	- allocated array of CANON Flags
1335 *
1336 **/
1337uint16_t
1338ptp_canon_get_directory (PTPParams* params,
1339	PTPObjectHandles	*handles,
1340	PTPObjectInfo		**oinfos,	/* size(handles->n) */
1341	uint32_t		**flags		/* size(handles->n) */
1342) {
1343	PTPContainer	ptp;
1344	unsigned char	*dir = NULL;
1345	unsigned int	size = 0;
1346	uint16_t	ret;
1347
1348	PTP_CNT_INIT(ptp);
1349	ptp.Code=PTP_OC_CANON_GetDirectory;
1350	ptp.Nparam=0;
1351	ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dir, &size);
1352	if (ret != PTP_RC_OK)
1353		return ret;
1354	ret = ptp_unpack_canon_directory(params, dir, ptp.Param1, handles, oinfos, flags);
1355	free (dir);
1356	return ret;
1357}
1358
1359/**
1360 * ptp_canon_gettreeinfo:
1361 * params:	PTPParams*
1362 *              uint32_t *out
1363 *
1364 * Switches the camera display to on and lets the user
1365 * select what to transfer. Sends a 0xc011 event when started
1366 * and 0xc013 if direct transfer aborted.
1367 *
1368 * Return values: Some PTP_RC_* code.
1369 *
1370 **/
1371uint16_t
1372ptp_canon_gettreeinfo (PTPParams* params, uint32_t *out)
1373{
1374	PTPContainer ptp;
1375	uint16_t ret;
1376
1377	PTP_CNT_INIT(ptp);
1378	ptp.Code   = PTP_OC_CANON_GetTreeInfo;
1379	ptp.Nparam = 1;
1380	ptp.Param1 = 0xf;
1381	ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
1382	if ((ret == PTP_RC_OK) && (ptp.Nparam>0))
1383		*out = ptp.Param1;
1384	return ret;
1385}
1386
1387/**
1388 * ptp_canon_getpairinginfo:
1389 * params:	PTPParams*
1390 *              int nr
1391 *
1392 * Get the pairing information.
1393 *
1394 * Return values: Some PTP_RC_* code.
1395 *
1396 **/
1397uint16_t
1398ptp_canon_getpairinginfo (PTPParams* params, uint32_t nr, unsigned char **data, unsigned int *size)
1399{
1400	PTPContainer ptp;
1401	uint16_t ret;
1402
1403	PTP_CNT_INIT(ptp);
1404	ptp.Code   = PTP_OC_CANON_GetPairingInfo;
1405	ptp.Nparam = 1;
1406	ptp.Param1 = nr;
1407	*data = NULL;
1408	*size = 0;
1409	ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
1410	if (ret != PTP_RC_OK)
1411		return ret;
1412	return PTP_RC_OK;
1413}
1414
1415/**
1416 * ptp_canon_get_target_handles:
1417 * params:	PTPParams*
1418 *              PTPCanon_directtransfer_entry **out
1419 *              unsigned int *outsize
1420 *
1421 * Retrieves direct transfer entries specifying the images to transfer
1422 * from the camera (to be retrieved after 0xc011 event).
1423 *
1424 * Return values: Some PTP_RC_* code.
1425 *
1426 **/
1427uint16_t
1428ptp_canon_gettreesize (PTPParams* params,
1429	PTPCanon_directtransfer_entry **entries, unsigned int *cnt)
1430{
1431	PTPContainer ptp;
1432	uint16_t ret;
1433	unsigned char *out = NULL, *cur;
1434	int i;
1435	unsigned int size;
1436
1437	PTP_CNT_INIT(ptp);
1438	ptp.Code   = PTP_OC_CANON_GetTreeSize;
1439	ptp.Nparam = 0;
1440	ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &out, &size);
1441	if (ret != PTP_RC_OK)
1442		return ret;
1443	*cnt = dtoh32a(out);
1444	*entries = malloc(sizeof(PTPCanon_directtransfer_entry)*(*cnt));
1445	cur = out+4;
1446	for (i=0;i<*cnt;i++) {
1447		unsigned char len;
1448		(*entries)[i].oid = dtoh32a(cur);
1449		(*entries)[i].str = ptp_unpack_string(params, cur, 4, &len);
1450		cur += 4+(cur[4]*2+1);
1451	}
1452	free (out);
1453	return PTP_RC_OK;
1454}
1455
1456/**
1457 * ptp_canon_checkevent:
1458 * params:	PTPParams*
1459 *
1460 * The camera has a FIFO stack, in which it accumulates events.
1461 * Partially these events are communicated also via the USB interrupt pipe
1462 * according to the PTP USB specification, partially not.
1463 * This operation returns from the device a block of data, empty,
1464 * if the event stack is empty, or filled with an event's data otherwise.
1465 * The event is removed from the stack in the latter case.
1466 * The Remote Capture app sends this command to the camera all the time
1467 * of connection, filling with it the gaps between other operations.
1468 *
1469 * Return values: Some PTP_RC_* code.
1470 * Upon success : PTPUSBEventContainer* event	- is filled with the event data
1471 *						  if any
1472 *                int *isevent			- returns 1 in case of event
1473 *						  or 0 otherwise
1474 **/
1475uint16_t
1476ptp_canon_checkevent (PTPParams* params, PTPContainer* event, int* isevent)
1477{
1478	uint16_t ret;
1479	PTPContainer ptp;
1480	unsigned char *evdata = NULL;
1481	unsigned int len;
1482
1483	*isevent=0;
1484	PTP_CNT_INIT(ptp);
1485	ptp.Code=PTP_OC_CANON_CheckEvent;
1486	ptp.Nparam=0;
1487	len=0;
1488	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &evdata, &len);
1489	if (evdata!=NULL) {
1490		if (ret == PTP_RC_OK) {
1491        		ptp_unpack_EC(params, evdata, event, len);
1492    			*isevent=1;
1493        	}
1494		free(evdata);
1495	}
1496	return ret;
1497}
1498
1499uint16_t
1500ptp_check_event (PTPParams *params) {
1501	PTPContainer		event;
1502	uint16_t		ret;
1503
1504	if (	(params->deviceinfo.VendorExtensionID == PTP_VENDOR_NIKON) &&
1505		ptp_operation_issupported(params, PTP_OC_NIKON_CheckEvent)
1506	) {
1507		int evtcnt;
1508		PTPContainer	*xevent = NULL;
1509
1510		ret = ptp_nikon_check_event(params, &xevent, &evtcnt);
1511		if (ret != PTP_RC_OK)
1512			return ret;
1513
1514		if (evtcnt) {
1515			if (params->nrofevents)
1516				params->events = realloc(params->events, sizeof(PTPContainer)*(evtcnt+params->nrofevents));
1517			else
1518				params->events = malloc(sizeof(PTPContainer)*evtcnt);
1519			memcpy (&params->events[params->nrofevents],xevent,evtcnt*sizeof(PTPContainer));
1520			params->nrofevents += evtcnt;
1521			free (xevent);
1522		}
1523		return PTP_RC_OK;
1524	}
1525	if (	(params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) &&
1526		ptp_operation_issupported(params, PTP_OC_CANON_CheckEvent)
1527	) {
1528		int isevent;
1529
1530		ret = ptp_canon_checkevent (params,&event,&isevent);
1531		if (ret!=PTP_RC_OK)
1532			return ret;
1533		if (isevent)
1534			goto store_event;
1535		/* FIXME: fallthrough or return? */
1536	}
1537	ret = params->event_check(params,&event);
1538
1539store_event:
1540	if (ret == PTP_RC_OK) {
1541		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);
1542		if (params->nrofevents)
1543			params->events = realloc(params->events, sizeof(PTPContainer)*(params->nrofevents+1));
1544		else
1545			params->events = malloc(sizeof(PTPContainer)*1);
1546		memcpy (&params->events[params->nrofevents],&event,1*sizeof(PTPContainer));
1547		params->nrofevents += 1;
1548	}
1549	if (ret == PTP_ERROR_TIMEOUT) /* ok, just new events */
1550		ret = PTP_RC_OK;
1551	return ret;
1552}
1553
1554int
1555ptp_get_one_event(PTPParams *params, PTPContainer *event) {
1556	if (!params->nrofevents)
1557		return 0;
1558	memcpy (event, params->events, sizeof(PTPContainer));
1559	memmove (params->events, params->events+1, sizeof(PTPContainer)*(params->nrofevents-1));
1560	/* do not realloc on shrink. */
1561	params->nrofevents--;
1562	return 1;
1563}
1564
1565/**
1566 * ptp_canon_eos_getevent:
1567 *
1568 * This retrieves configuration status/updates/changes
1569 * on EOS cameras. It reads a datablock which has a list of variable
1570 * sized structures.
1571 *
1572 * params:	PTPParams*
1573 *
1574 * Return values: Some PTP_RC_* code.
1575 *
1576 **/
1577uint16_t
1578ptp_canon_eos_getevent (PTPParams* params, PTPCanon_changes_entry **entries, int *nrofentries)
1579{
1580	PTPContainer ptp;
1581	uint16_t	ret;
1582	unsigned int 	size = 0;
1583	unsigned char	*data = NULL;
1584
1585	*nrofentries = 0;
1586	*entries = NULL;
1587	PTP_CNT_INIT(ptp);
1588	ptp.Code = PTP_OC_CANON_EOS_GetEvent;
1589	ptp.Nparam = 0;
1590	ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
1591	if (ret != PTP_RC_OK) return ret;
1592        *nrofentries = ptp_unpack_CANON_changes(params,data,size,entries);
1593	return PTP_RC_OK;
1594}
1595
1596uint16_t
1597ptp_canon_eos_getdevicepropdesc (PTPParams* params, uint16_t propcode,
1598	PTPDevicePropDesc *dpd)
1599{
1600	int i;
1601
1602	for (i=0;i<params->nrofcanon_props;i++)
1603		if (params->canon_props[i].proptype == propcode)
1604			break;
1605	if (params->nrofcanon_props == i)
1606		return PTP_RC_Undefined;
1607	memcpy (dpd, &params->canon_props[i].dpd, sizeof (*dpd));
1608	if (dpd->FormFlag == PTP_DPFF_Enumeration) {
1609		/* need to duplicate the Enumeration alloc */
1610		dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*dpd->FORM.Enum.NumberOfValues);
1611		memcpy (dpd->FORM.Enum.SupportedValue,
1612			params->canon_props[i].dpd.FORM.Enum.SupportedValue,
1613			sizeof (PTPPropertyValue)*dpd->FORM.Enum.NumberOfValues
1614		);
1615	}
1616	if (dpd->DataType == PTP_DTC_STR) {
1617		dpd->FactoryDefaultValue.str = strdup( params->canon_props[i].dpd.FactoryDefaultValue.str );
1618		dpd->CurrentValue.str = strdup( params->canon_props[i].dpd.CurrentValue.str );
1619	}
1620
1621	return PTP_RC_OK;
1622}
1623
1624
1625uint16_t
1626ptp_canon_eos_getstorageids (PTPParams* params, PTPStorageIDs* storageids)
1627{
1628	PTPContainer	ptp;
1629	unsigned int	len = 0;
1630	uint16_t	ret;
1631	unsigned char*	sids=NULL;
1632
1633	PTP_CNT_INIT(ptp);
1634	ptp.Code 	= PTP_OC_CANON_EOS_GetStorageIDs;
1635	ptp.Nparam	= 0;
1636	ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &sids, &len);
1637	if (ret == PTP_RC_OK) ptp_unpack_SIDs(params, sids, storageids, len);
1638	free(sids);
1639	return ret;
1640}
1641
1642uint16_t
1643ptp_canon_eos_getstorageinfo (PTPParams* params, uint32_t p1)
1644{
1645	PTPContainer ptp;
1646	unsigned char	*data = NULL;
1647	unsigned int	size = 0;
1648	uint16_t	ret;
1649
1650	PTP_CNT_INIT(ptp);
1651	ptp.Code 	= PTP_OC_CANON_EOS_GetStorageInfo;
1652	ptp.Nparam	= 1;
1653	ptp.Param1	= p1;
1654	ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
1655	/* FIXME: do stuff with data */
1656	return ret;
1657}
1658
1659/**
1660 * ptp_canon_eos_getpartialobject:
1661 *
1662 * This retrieves a part of an PTP object which you specify as object id.
1663 * The id originates from 0x9116 call.
1664 * After finishing it, we seem to need to call ptp_canon_eos_enddirecttransfer.
1665 *
1666 * params:	PTPParams*
1667 * 		oid		Object ID
1668 * 		offset		The offset where to start the data transfer
1669 *		xsize		Size in bytes of the transfer to do
1670 *		data		Pointer that receives the malloc()ed memory of the transfer.
1671 *
1672 * Return values: Some PTP_RC_* code.
1673 *
1674 */
1675uint16_t
1676ptp_canon_eos_getpartialobject (PTPParams* params, uint32_t oid, uint32_t offset, uint32_t xsize, unsigned char**data)
1677{
1678	PTPContainer	ptp;
1679	unsigned int	size = 0;
1680
1681	*data = NULL;
1682	PTP_CNT_INIT(ptp);
1683	ptp.Code 	= PTP_OC_CANON_EOS_GetPartialObject;
1684	ptp.Nparam	= 3;
1685	ptp.Param1	= oid;
1686	ptp.Param2	= offset;
1687	ptp.Param3	= xsize;
1688	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, &size);
1689}
1690
1691uint16_t
1692ptp_canon_eos_setdevicepropvalueex (PTPParams* params, unsigned char* data, unsigned int size)
1693{
1694	PTPContainer	ptp;
1695
1696	PTP_CNT_INIT(ptp);
1697	ptp.Code 	= PTP_OC_CANON_EOS_SetDevicePropValueEx;
1698	ptp.Nparam	= 0;
1699	return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
1700}
1701
1702uint16_t
1703ptp_canon_eos_setdevicepropvalue (PTPParams* params,
1704	uint16_t propcode, PTPPropertyValue *value, uint16_t datatype
1705) {
1706	PTPContainer	ptp;
1707	uint16_t	ret;
1708	int 		i;
1709	unsigned char	*data;
1710	unsigned int	size;
1711
1712	PTP_CNT_INIT(ptp);
1713	ptp.Code 	= PTP_OC_CANON_EOS_SetDevicePropValueEx;
1714	ptp.Nparam	= 0;
1715	for (i=0;i<params->nrofcanon_props;i++)
1716		if (params->canon_props[i].proptype == propcode)
1717			break;
1718	if (params->nrofcanon_props == i)
1719		return PTP_RC_Undefined;
1720
1721	switch (propcode) {
1722	case PTP_DPC_CANON_EOS_ImageFormat:
1723	case PTP_DPC_CANON_EOS_ImageFormatCF:
1724	case PTP_DPC_CANON_EOS_ImageFormatSD:
1725	case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1726		/* special handling of ImageFormat properties */
1727		size = 8 + ptp_pack_EOS_ImageFormat( params, NULL, value->u16 );
1728		data = malloc( size );
1729		params->canon_props[i].dpd.CurrentValue.u16 = value->u16;
1730		ptp_pack_EOS_ImageFormat( params, data + 8, value->u16 );
1731		break;
1732	default:
1733		if (datatype != PTP_DTC_STR) {
1734			data = calloc(sizeof(uint32_t),3);
1735			size = sizeof(uint32_t)*3;
1736		} else {
1737			size = strlen(value->str) + 1 + 8;
1738			data = calloc(sizeof(char),size);
1739		}
1740		switch (datatype) {
1741		case PTP_DTC_UINT8:
1742			/*fprintf (stderr, "%x -> %d\n", propcode, value->u8);*/
1743			htod8a(&data[8], value->u8);
1744			params->canon_props[i].dpd.CurrentValue.u8 = value->u8;
1745			break;
1746		case PTP_DTC_UINT16:
1747			/*fprintf (stderr, "%x -> %d\n", propcode, value->u16);*/
1748			htod16a(&data[8], value->u16);
1749			params->canon_props[i].dpd.CurrentValue.u16 = value->u16;
1750			break;
1751		case PTP_DTC_UINT32:
1752			/*fprintf (stderr, "%x -> %d\n", propcode, value->u32);*/
1753			htod32a(&data[8], value->u32);
1754			params->canon_props[i].dpd.CurrentValue.u32 = value->u32;
1755			break;
1756		case PTP_DTC_STR:
1757			strcpy((char*)data + 8, value->str);
1758			free (params->canon_props[i].dpd.CurrentValue.str);
1759			params->canon_props[i].dpd.CurrentValue.str = strdup(value->str);
1760			break;
1761		}
1762	}
1763
1764	htod32a(&data[0], size);
1765	htod32a(&data[4], propcode);
1766
1767	ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
1768	free (data);
1769	return ret;
1770}
1771
1772/**
1773 * ptp_canon_getpartialobject:
1774 *
1775 * This operation is used to read from the device a data
1776 * block of an object from a specified offset.
1777 *
1778 * params:	PTPParams*
1779 *      uint32_t handle - the handle of the requested object
1780 *      uint32_t offset - the offset in bytes from the beginning of the object
1781 *      uint32_t size - the requested size of data block to read
1782 *      uint32_t pos - 1 for the first block, 2 - for a block in the middle,
1783 *                  3 - for the last block
1784 *
1785 * Return values: Some PTP_RC_* code.
1786 *      char **block - the pointer to the block of data read
1787 *      uint32_t* readnum - the number of bytes read
1788 *
1789 **/
1790uint16_t
1791ptp_canon_getpartialobject (PTPParams* params, uint32_t handle,
1792				uint32_t offset, uint32_t size,
1793				uint32_t pos, unsigned char** block,
1794				uint32_t* readnum)
1795{
1796	uint16_t ret;
1797	PTPContainer ptp;
1798	unsigned char *data=NULL;
1799	unsigned int len;
1800
1801	PTP_CNT_INIT(ptp);
1802	ptp.Code=PTP_OC_CANON_GetPartialObjectEx;
1803	ptp.Param1=handle;
1804	ptp.Param2=offset;
1805	ptp.Param3=size;
1806	ptp.Param4=pos;
1807	ptp.Nparam=4;
1808	len=0;
1809	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &len);
1810	if (ret==PTP_RC_OK) {
1811		*block=data;
1812		*readnum=ptp.Param1;
1813	}
1814	return ret;
1815}
1816
1817/**
1818 * ptp_canon_getviewfinderimage:
1819 *
1820 * This operation can be used to read the image which is currently
1821 * in the camera's viewfinder. The image size is 320x240, format is JPEG.
1822 * Of course, prior to calling this operation, one must turn the viewfinder
1823 * on with the CANON_ViewfinderOn command.
1824 * Invoking this operation many times, one can get live video from the camera!
1825 *
1826 * params:	PTPParams*
1827 *
1828 * Return values: Some PTP_RC_* code.
1829 *      char **image - the pointer to the read image
1830 *      unit32_t *size - the size of the image in bytes
1831 *
1832 **/
1833uint16_t
1834ptp_canon_getviewfinderimage (PTPParams* params, unsigned char** image, uint32_t* size)
1835{
1836	uint16_t ret;
1837	PTPContainer ptp;
1838	unsigned int len;
1839
1840	PTP_CNT_INIT(ptp);
1841	ptp.Code=PTP_OC_CANON_GetViewfinderImage;
1842	ptp.Nparam=0;
1843	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, image, &len);
1844	if (ret==PTP_RC_OK) *size=ptp.Param1;
1845	return ret;
1846}
1847
1848/**
1849 * ptp_canon_getchanges:
1850 *
1851 * This is an interesting operation, about the effect of which I am not sure.
1852 * This command is called every time when a device property has been changed
1853 * with the SetDevicePropValue operation, and after some other operations.
1854 * This operation reads the array of Device Properties which have been changed
1855 * by the previous operation.
1856 * Probably, this operation is even required to make those changes work.
1857 *
1858 * params:	PTPParams*
1859 *
1860 * Return values: Some PTP_RC_* code.
1861 *      uint16_t** props - the pointer to the array of changed properties
1862 *      uint32_t* propnum - the number of elements in the *props array
1863 *
1864 **/
1865uint16_t
1866ptp_canon_getchanges (PTPParams* params, uint16_t** props, uint32_t* propnum)
1867{
1868	uint16_t ret;
1869	PTPContainer ptp;
1870	unsigned char* data=NULL;
1871	unsigned int len;
1872
1873	PTP_CNT_INIT(ptp);
1874	ptp.Code=PTP_OC_CANON_GetChanges;
1875	ptp.Nparam=0;
1876	len=0;
1877	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &len);
1878	if (ret == PTP_RC_OK)
1879        	*propnum=ptp_unpack_uint16_t_array(params,data,0,props);
1880	free(data);
1881	return ret;
1882}
1883
1884/**
1885 * ptp_canon_getobjectinfo:
1886 *
1887 * This command reads a specified object's record in a device's filesystem,
1888 * or the records of all objects belonging to a specified folder (association).
1889 *
1890 * params:	PTPParams*
1891 *      uint32_t store - StorageID,
1892 *      uint32_t p2 - Yet unknown (0 value works OK)
1893 *      uint32_t parent - Parent Object Handle
1894 *                      # If Parent Object Handle is 0xffffffff,
1895 *                      # the Parent Object is the top level folder.
1896 *      uint32_t handle - Object Handle
1897 *                      # If Object Handle is 0, the records of all objects
1898 *                      # belonging to the Parent Object are read.
1899 *                      # If Object Handle is not 0, only the record of this
1900 *                      # Object is read.
1901 *
1902 * Return values: Some PTP_RC_* code.
1903 *      PTPCANONFolderEntry** entries - the pointer to the folder entry array
1904 *      uint32_t* entnum - the number of elements of the array
1905 *
1906 **/
1907uint16_t
1908ptp_canon_getobjectinfo (PTPParams* params, uint32_t store, uint32_t p2,
1909			    uint32_t parent, uint32_t handle,
1910			    PTPCANONFolderEntry** entries, uint32_t* entnum)
1911{
1912	uint16_t ret;
1913	PTPContainer ptp;
1914	unsigned char *data = NULL;
1915	unsigned int len;
1916
1917	PTP_CNT_INIT(ptp);
1918	ptp.Code=PTP_OC_CANON_GetObjectInfoEx;
1919	ptp.Param1=store;
1920	ptp.Param2=p2;
1921	ptp.Param3=parent;
1922	ptp.Param4=handle;
1923	ptp.Nparam=4;
1924	len=0;
1925	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &len);
1926	if (ret == PTP_RC_OK) {
1927		int i;
1928		*entnum=ptp.Param1;
1929		*entries=calloc(*entnum, sizeof(PTPCANONFolderEntry));
1930		if (*entries!=NULL) {
1931			for(i=0; i<(*entnum); i++)
1932				ptp_unpack_Canon_FE(params,
1933					data+i*PTP_CANON_FolderEntryLen,
1934					&((*entries)[i]) );
1935		} else {
1936			ret=PTP_ERROR_IO; /* Cannot allocate memory */
1937		}
1938	}
1939	free(data);
1940	return ret;
1941}
1942
1943/**
1944 * ptp_canon_get_objecthandle_by_name:
1945 *
1946 * This command looks up the specified object on the camera.
1947 *
1948 * Format is "A:\\PATH".
1949 *
1950 * The 'A' is the VolumeLabel from GetStorageInfo,
1951 * my IXUS has "A" for the card and "V" for internal memory.
1952 *
1953 * params:	PTPParams*
1954 *      char* name - path name
1955 *
1956 * Return values: Some PTP_RC_* code.
1957 *      uint32_t *oid - PTP object id.
1958 *
1959 **/
1960uint16_t
1961ptp_canon_get_objecthandle_by_name (PTPParams* params, char* name, uint32_t* objectid)
1962{
1963	uint16_t ret;
1964	PTPContainer ptp;
1965	unsigned char *data = NULL;
1966	uint8_t len;
1967
1968	PTP_CNT_INIT (ptp);
1969	ptp.Code=PTP_OC_CANON_GetObjectHandleByName;
1970	ptp.Nparam=0;
1971	len=0;
1972	data = malloc (2*(strlen(name)+1)+2);
1973	memset (data, 0, 2*(strlen(name)+1)+2);
1974	ptp_pack_string (params, name, data, 0, &len);
1975	ret=ptp_transaction (params, &ptp, PTP_DP_SENDDATA, (len+1)*2+1, &data, NULL);
1976	free (data);
1977	*objectid = ptp.Param1;
1978	return ret;
1979}
1980
1981/**
1982 * ptp_canon_get_customize_data:
1983 *
1984 * This command downloads the specified theme slot, including jpegs
1985 * and wav files.
1986 *
1987 * params:	PTPParams*
1988 *      uint32_t themenr - nr of theme
1989 *
1990 * Return values: Some PTP_RC_* code.
1991 *      unsigned char **data - pointer to data pointer
1992 *      unsigned int  *size - size of data returned
1993 *
1994 **/
1995uint16_t
1996ptp_canon_get_customize_data (PTPParams* params, uint32_t themenr,
1997		unsigned char **data, unsigned int *size)
1998{
1999	PTPContainer ptp;
2000
2001	*data = NULL;
2002	*size = 0;
2003	PTP_CNT_INIT(ptp);
2004	ptp.Code	= PTP_OC_CANON_GetCustomizeData;
2005	ptp.Param1	= themenr;
2006	ptp.Nparam	= 1;
2007	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2008}
2009
2010
2011uint16_t
2012ptp_nikon_curve_download (PTPParams* params, unsigned char **data, unsigned int *size) {
2013	PTPContainer ptp;
2014	*data = NULL;
2015	*size = 0;
2016	PTP_CNT_INIT(ptp);
2017	ptp.Code	= PTP_OC_NIKON_CurveDownload;
2018	ptp.Nparam	= 0;
2019	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2020}
2021
2022/**
2023 * ptp_canon_get_vendorpropcodes:
2024 *
2025 * This command downloads the vendor specific property codes.
2026 *
2027 * params:	PTPParams*
2028 *
2029 * Return values: Some PTP_RC_* code.
2030 *      unsigned char **data - pointer to data pointer
2031 *      unsigned int  *size - size of data returned
2032 *
2033 **/
2034uint16_t
2035ptp_nikon_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size) {
2036	PTPContainer	ptp;
2037	uint16_t	ret;
2038	unsigned char	*xdata;
2039	unsigned int 	xsize;
2040
2041	*props = NULL;
2042	*size = 0;
2043	PTP_CNT_INIT(ptp);
2044	ptp.Code	= PTP_OC_NIKON_GetVendorPropCodes;
2045	ptp.Nparam	= 0;
2046	ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize);
2047	if (ret == PTP_RC_OK)
2048        	*size = ptp_unpack_uint16_t_array(params,xdata,0,props);
2049	return ret;
2050}
2051
2052uint16_t
2053ptp_nikon_getfileinfoinblock ( PTPParams* params,
2054	uint32_t p1, uint32_t p2, uint32_t p3,
2055	unsigned char **data, unsigned int *size
2056) {
2057	PTPContainer ptp;
2058	*data = NULL;
2059	*size = 0;
2060	PTP_CNT_INIT(ptp);
2061	ptp.Code	= PTP_OC_NIKON_GetFileInfoInBlock;
2062	ptp.Nparam	= 3;
2063	ptp.Param1	= p1;
2064	ptp.Param2	= p2;
2065	ptp.Param3	= p3;
2066	return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2067}
2068
2069/**
2070 * ptp_nikon_get_liveview_image:
2071 *
2072 * This command gets a LiveView image from newer Nikons DSLRs.
2073 *
2074 * params:	PTPParams*
2075 *
2076 * Return values: Some PTP_RC_* code.
2077 *
2078 **/
2079uint16_t
2080ptp_nikon_get_liveview_image (PTPParams* params, unsigned char **data, unsigned int *size)
2081{
2082        PTPContainer ptp;
2083
2084        PTP_CNT_INIT(ptp);
2085        ptp.Code=PTP_OC_NIKON_GetLiveViewImg;
2086        ptp.Nparam=0;
2087        return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2088}
2089
2090/**
2091 * ptp_nikon_get_preview_image:
2092 *
2093 * This command gets a Preview image from newer Nikons DSLRs.
2094 *
2095 * params:	PTPParams*
2096 *
2097 * Return values: Some PTP_RC_* code.
2098 *
2099 **/
2100uint16_t
2101ptp_nikon_get_preview_image (PTPParams* params, unsigned char **xdata, unsigned int *xsize,
2102	uint32_t *handle)
2103{
2104        PTPContainer	ptp;
2105	uint16_t	ret;
2106
2107        PTP_CNT_INIT(ptp);
2108        ptp.Code=PTP_OC_NIKON_GetPreviewImg;
2109        ptp.Nparam=0;
2110        ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, xdata, xsize);
2111	if (ret == PTP_RC_OK) {
2112		if (ptp.Nparam > 0)
2113			*handle = ptp.Param1;
2114	}
2115	return ret;
2116}
2117
2118/**
2119 * ptp_canon_eos_get_viewfinder_image:
2120 *
2121 * This command gets a Viewfinder image from newer Nikons DSLRs.
2122 *
2123 * params:	PTPParams*
2124 *
2125 * Return values: Some PTP_RC_* code.
2126 *
2127 **/
2128uint16_t
2129ptp_canon_eos_get_viewfinder_image (PTPParams* params, unsigned char **data, unsigned int *size)
2130{
2131        PTPContainer ptp;
2132
2133        PTP_CNT_INIT(ptp);
2134        ptp.Code=PTP_OC_CANON_EOS_GetViewFinderData;
2135        ptp.Nparam=1;
2136        ptp.Param1=0x00100000; /* from trace */
2137        return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2138}
2139
2140/**
2141 * ptp_nikon_check_event:
2142 *
2143 * This command checks the event queue on the Nikon.
2144 *
2145 * params:	PTPParams*
2146 *      PTPUSBEventContainer **event - list of usb events.
2147 *	int *evtcnt - number of usb events in event structure.
2148 *
2149 * Return values: Some PTP_RC_* code.
2150 *
2151 **/
2152uint16_t
2153ptp_nikon_check_event (PTPParams* params, PTPContainer** event, int* evtcnt)
2154{
2155        PTPContainer ptp;
2156	uint16_t ret;
2157	unsigned char *data = NULL;
2158	unsigned int size = 0;
2159
2160	PTP_CNT_INIT(ptp);
2161	ptp.Code=PTP_OC_NIKON_CheckEvent;
2162	ptp.Nparam=0;
2163	*evtcnt = 0;
2164	ret = ptp_transaction (params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
2165	if (ret == PTP_RC_OK) {
2166		ptp_unpack_Nikon_EC (params, data, size, event, evtcnt);
2167		free (data);
2168	}
2169	return ret;
2170}
2171
2172/**
2173 * ptp_nikon_getptpipinfo:
2174 *
2175 * This command gets the ptpip info data.
2176 *
2177 * params:	PTPParams*
2178 *	unsigned char *data	- data
2179 *	unsigned int size	- size of returned data
2180 *
2181 * Return values: Some PTP_RC_* code.
2182 *
2183 **/
2184uint16_t
2185ptp_nikon_getptpipinfo (PTPParams* params, unsigned char **data, unsigned int *size)
2186{
2187        PTPContainer ptp;
2188
2189        PTP_CNT_INIT(ptp);
2190        ptp.Code=PTP_OC_NIKON_GetDevicePTPIPInfo;
2191        ptp.Nparam=0;
2192        return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
2193}
2194
2195/**
2196 * ptp_nikon_getwifiprofilelist:
2197 *
2198 * This command gets the wifi profile list.
2199 *
2200 * params:	PTPParams*
2201 *
2202 * Return values: Some PTP_RC_* code.
2203 *
2204 **/
2205uint16_t
2206ptp_nikon_getwifiprofilelist (PTPParams* params)
2207{
2208        PTPContainer ptp;
2209	unsigned char* data;
2210	unsigned int size;
2211	unsigned int pos;
2212	unsigned int profn;
2213	unsigned int n;
2214	char* buffer;
2215	uint8_t len;
2216
2217        PTP_CNT_INIT(ptp);
2218        ptp.Code=PTP_OC_NIKON_GetProfileAllData;
2219        ptp.Nparam=0;
2220	size = 0;
2221	data = NULL;
2222	CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
2223
2224	if (size < 2) return PTP_RC_Undefined; /* FIXME: Add more precise error code */
2225
2226	params->wifi_profiles_version = data[0];
2227	params->wifi_profiles_number = data[1];
2228	if (params->wifi_profiles)
2229		free(params->wifi_profiles);
2230
2231	params->wifi_profiles = malloc(params->wifi_profiles_number*sizeof(PTPNIKONWifiProfile));
2232	memset(params->wifi_profiles, 0, params->wifi_profiles_number*sizeof(PTPNIKONWifiProfile));
2233
2234	pos = 2;
2235	profn = 0;
2236	while (profn < params->wifi_profiles_number && pos < size) {
2237		if (pos+6 >= size) return PTP_RC_Undefined;
2238		params->wifi_profiles[profn].id = data[pos++];
2239		params->wifi_profiles[profn].valid = data[pos++];
2240
2241		n = dtoh32a(&data[pos]);
2242		pos += 4;
2243		if (pos+n+4 >= size) return PTP_RC_Undefined;
2244		strncpy(params->wifi_profiles[profn].profile_name, (char*)&data[pos], n);
2245		params->wifi_profiles[profn].profile_name[16] = '\0';
2246		pos += n;
2247
2248		params->wifi_profiles[profn].display_order = data[pos++];
2249		params->wifi_profiles[profn].device_type = data[pos++];
2250		params->wifi_profiles[profn].icon_type = data[pos++];
2251
2252		buffer = ptp_unpack_string(params, data, pos, &len);
2253		strncpy(params->wifi_profiles[profn].creation_date, buffer, sizeof(params->wifi_profiles[profn].creation_date));
2254		free (buffer);
2255		pos += (len*2+1);
2256		if (pos+1 >= size) return PTP_RC_Undefined;
2257		/* FIXME: check if it is really last usage date */
2258		buffer = ptp_unpack_string(params, data, pos, &len);
2259		strncpy(params->wifi_profiles[profn].lastusage_date, buffer, sizeof(params->wifi_profiles[profn].lastusage_date));
2260		free (buffer);
2261		pos += (len*2+1);
2262		if (pos+5 >= size) return PTP_RC_Undefined;
2263
2264		n = dtoh32a(&data[pos]);
2265		pos += 4;
2266		if (pos+n >= size) return PTP_RC_Undefined;
2267		strncpy(params->wifi_profiles[profn].essid, (char*)&data[pos], n);
2268		params->wifi_profiles[profn].essid[32] = '\0';
2269		pos += n;
2270		pos += 1;
2271		profn++;
2272	}
2273
2274#if 0
2275	PTPNIKONWifiProfile test;
2276	memset(&test, 0, sizeof(PTPNIKONWifiProfile));
2277	strcpy(test.profile_name, "MyTest");
2278	test.icon_type = 1;
2279	strcpy(test.essid, "nikon");
2280	test.ip_address = 10 + 11 << 16 + 11 << 24;
2281	test.subnet_mask = 24;
2282	test.access_mode = 1;
2283	test.wifi_channel = 1;
2284	test.key_nr = 1;
2285
2286	ptp_nikon_writewifiprofile(params, &test);
2287#endif
2288
2289	return PTP_RC_OK;
2290}
2291
2292/**
2293 * ptp_nikon_writewifiprofile:
2294 *
2295 * This command gets the ptpip info data.
2296 *
2297 * params:	PTPParams*
2298 *	unsigned int profilenr	- profile number
2299 *	unsigned char *data	- data
2300 *	unsigned int size	- size of returned data
2301 *
2302 * Return values: Some PTP_RC_* code.
2303 *
2304 **/
2305uint16_t
2306ptp_nikon_writewifiprofile (PTPParams* params, PTPNIKONWifiProfile* profile)
2307{
2308	unsigned char guid[16];
2309
2310	PTPContainer ptp;
2311	unsigned char buffer[1024];
2312	unsigned char* data = buffer;
2313	int size = 0;
2314	int i;
2315	uint8_t len;
2316	int profilenr = -1;
2317
2318	ptp_nikon_getptpipguid(guid);
2319
2320	if (!params->wifi_profiles)
2321		CHECK_PTP_RC(ptp_nikon_getwifiprofilelist(params));
2322
2323	for (i = 0; i < params->wifi_profiles_number; i++) {
2324		if (!params->wifi_profiles[i].valid) {
2325			profilenr = params->wifi_profiles[i].id;
2326			break;
2327		}
2328	}
2329
2330	if (profilenr == -1) {
2331		/* No free profile! */
2332		return PTP_RC_StoreFull;
2333	}
2334
2335	memset(buffer, 0, 1024);
2336
2337	buffer[0x00] = 0x64; /* Version */
2338
2339	/* Profile name */
2340	htod32a(&buffer[0x01], 17);
2341	/* 16 as third parameter, so there will always be a null-byte in the end */
2342	strncpy((char*)&buffer[0x05], profile->profile_name, 16);
2343
2344	buffer[0x16] = 0x00; /* Display order */
2345	buffer[0x17] = profile->device_type;
2346	buffer[0x18] = profile->icon_type;
2347
2348	/* FIXME: Creation date: put a real date here */
2349	ptp_pack_string(params, "19990909T090909", data, 0x19, &len);
2350
2351	/* IP parameters */
2352	*((unsigned int*)&buffer[0x3A]) = profile->ip_address; /* Do not reverse bytes */
2353	buffer[0x3E] = profile->subnet_mask;
2354	*((unsigned int*)&buffer[0x3F]) = profile->gateway_address; /* Do not reverse bytes */
2355	buffer[0x43] = profile->address_mode;
2356
2357	/* Wifi parameters */
2358	buffer[0x44] = profile->access_mode;
2359	buffer[0x45] = profile->wifi_channel;
2360
2361	htod32a(&buffer[0x46], 33); /* essid */
2362	 /* 32 as third parameter, so there will always be a null-byte in the end */
2363	strncpy((char*)&buffer[0x4A], profile->essid, 32);
2364
2365	buffer[0x6B] = profile->authentification;
2366	buffer[0x6C] = profile->encryption;
2367	htod32a(&buffer[0x6D], 64);
2368	for (i = 0; i < 64; i++) {
2369		buffer[0x71+i] = profile->key[i];
2370	}
2371	buffer[0xB1] = profile->key_nr;
2372	memcpy(&buffer[0xB2], guid, 16);
2373
2374	switch(profile->encryption) {
2375	case 1: /* WEP 64bit */
2376		htod16a(&buffer[0xC2], 5); /* (64-24)/8 = 5 */
2377		break;
2378	case 2: /* WEP 128bit */
2379		htod16a(&buffer[0xC2], 13); /* (128-24)/8 = 13 */
2380		break;
2381	default:
2382		htod16a(&buffer[0xC2], 0);
2383	}
2384	size = 0xC4;
2385
2386	PTP_CNT_INIT(ptp);
2387	ptp.Code=PTP_OC_NIKON_SendProfileData;
2388	ptp.Nparam=1;
2389	ptp.Param1=profilenr;
2390	return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
2391}
2392
2393/**
2394 * ptp_mtp_getobjectpropssupported:
2395 *
2396 * This command gets the object properties possible from the device.
2397 *
2398 * params:	PTPParams*
2399 *	uint ofc		- object format code
2400 *	unsigned int *propnum	- number of elements in returned array
2401 *	uint16_t *props		- array of supported properties
2402 *
2403 * Return values: Some PTP_RC_* code.
2404 *
2405 **/
2406uint16_t
2407ptp_mtp_getobjectpropssupported (PTPParams* params, uint16_t ofc,
2408		 uint32_t *propnum, uint16_t **props
2409) {
2410        PTPContainer ptp;
2411	uint16_t ret;
2412	unsigned char *data = NULL;
2413	unsigned int size = 0;
2414
2415        PTP_CNT_INIT(ptp);
2416        ptp.Code=PTP_OC_MTP_GetObjectPropsSupported;
2417        ptp.Nparam = 1;
2418        ptp.Param1 = ofc;
2419        ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
2420	if (ret == PTP_RC_OK)
2421        	*propnum=ptp_unpack_uint16_t_array(params,data,0,props);
2422	free(data);
2423	return ret;
2424}
2425
2426/**
2427 * ptp_mtp_getobjectpropdesc:
2428 *
2429 * This command gets the object property description.
2430 *
2431 * params:	PTPParams*
2432 *	uint16_t opc	- object property code
2433 *	uint16_t ofc	- object format code
2434 *
2435 * Return values: Some PTP_RC_* code.
2436 *
2437 **/
2438uint16_t
2439ptp_mtp_getobjectpropdesc (
2440	PTPParams* params, uint16_t opc, uint16_t ofc, PTPObjectPropDesc *opd
2441) {
2442        PTPContainer ptp;
2443	uint16_t ret;
2444	unsigned char *data = NULL;
2445	unsigned int size = 0;
2446
2447        PTP_CNT_INIT(ptp);
2448        ptp.Code=PTP_OC_MTP_GetObjectPropDesc;
2449        ptp.Nparam = 2;
2450        ptp.Param1 = opc;
2451        ptp.Param2 = ofc;
2452        ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
2453	if (ret == PTP_RC_OK)
2454		ptp_unpack_OPD (params, data, opd, size);
2455	free(data);
2456	return ret;
2457}
2458
2459/**
2460 * ptp_mtp_getobjectpropvalue:
2461 *
2462 * This command gets the object properties of an object handle.
2463 *
2464 * params:	PTPParams*
2465 *	uint32_t objectid	- object format code
2466 *	uint16_t opc		- object prop code
2467 *
2468 * Return values: Some PTP_RC_* code.
2469 *
2470 **/
2471uint16_t
2472ptp_mtp_getobjectpropvalue (
2473	PTPParams* params, uint32_t oid, uint16_t opc,
2474	PTPPropertyValue *value, uint16_t datatype
2475) {
2476        PTPContainer ptp;
2477	uint16_t ret;
2478	unsigned char *data = NULL;
2479	unsigned int size = 0;
2480	int offset = 0;
2481
2482        PTP_CNT_INIT(ptp);
2483        ptp.Code=PTP_OC_MTP_GetObjectPropValue;
2484        ptp.Nparam = 2;
2485        ptp.Param1 = oid;
2486        ptp.Param2 = opc;
2487        ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
2488	if (ret == PTP_RC_OK)
2489		ptp_unpack_DPV(params, data, &offset, size, value, datatype);
2490	free(data);
2491	return ret;
2492}
2493
2494/**
2495 * ptp_mtp_setobjectpropvalue:
2496 *
2497 * This command gets the object properties of an object handle.
2498 *
2499 * params:	PTPParams*
2500 *	uint32_t objectid	- object format code
2501 *	uint16_t opc		- object prop code
2502 *
2503 * Return values: Some PTP_RC_* code.
2504 *
2505 **/
2506uint16_t
2507ptp_mtp_setobjectpropvalue (
2508	PTPParams* params, uint32_t oid, uint16_t opc,
2509	PTPPropertyValue *value, uint16_t datatype
2510) {
2511        PTPContainer ptp;
2512	uint16_t ret;
2513	unsigned char *data = NULL;
2514	unsigned int size ;
2515
2516        PTP_CNT_INIT(ptp);
2517        ptp.Code=PTP_OC_MTP_SetObjectPropValue;
2518        ptp.Nparam = 2;
2519        ptp.Param1 = oid;
2520        ptp.Param2 = opc;
2521	size = ptp_pack_DPV(params, value, &data, datatype);
2522        ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
2523	free(data);
2524	return ret;
2525}
2526
2527uint16_t
2528ptp_mtp_getobjectreferences (PTPParams* params, uint32_t handle, uint32_t** ohArray, uint32_t* arraylen)
2529{
2530	PTPContainer ptp;
2531	uint16_t ret;
2532	unsigned char* dpv=NULL;
2533	unsigned int dpvlen = 0;
2534
2535	PTP_CNT_INIT(ptp);
2536	ptp.Code=PTP_OC_MTP_GetObjectReferences;
2537	ptp.Param1=handle;
2538	ptp.Nparam=1;
2539	ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpv, &dpvlen);
2540	if (ret == PTP_RC_OK) {
2541		/* Sandisk Sansa skips the DATA phase, but returns OK as response.
2542		 * this will gives us a NULL here. Handle it. -Marcus */
2543		if ((dpv == NULL) || (dpvlen == 0)) {
2544			*arraylen = 0;
2545			*ohArray = NULL;
2546		} else {
2547			*arraylen = ptp_unpack_uint32_t_array(params, dpv, 0, ohArray);
2548		}
2549	}
2550	free(dpv);
2551	return ret;
2552}
2553
2554uint16_t
2555ptp_mtp_setobjectreferences (PTPParams* params, uint32_t handle, uint32_t* ohArray, uint32_t arraylen)
2556{
2557	PTPContainer ptp;
2558	uint16_t ret;
2559	uint32_t size;
2560	unsigned char* dpv=NULL;
2561
2562	PTP_CNT_INIT(ptp);
2563	ptp.Code   = PTP_OC_MTP_SetObjectReferences;
2564	ptp.Param1 = handle;
2565	ptp.Nparam = 1;
2566	size = ptp_pack_uint32_t_array(params, ohArray, arraylen, &dpv);
2567	ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, (unsigned char **)&dpv, NULL);
2568	free(dpv);
2569	return ret;
2570}
2571
2572uint16_t
2573ptp_mtp_getobjectproplist (PTPParams* params, uint32_t handle, MTPProperties **props, int *nrofprops)
2574{
2575	uint16_t ret;
2576	PTPContainer ptp;
2577	unsigned char* opldata = NULL;
2578	unsigned int oplsize;
2579
2580	PTP_CNT_INIT(ptp);
2581	ptp.Code = PTP_OC_MTP_GetObjPropList;
2582	ptp.Param1 = handle;
2583	ptp.Param2 = 0x00000000U;  /* 0x00000000U should be "all formats" */
2584	ptp.Param3 = 0xFFFFFFFFU;  /* 0xFFFFFFFFU should be "all properties" */
2585	ptp.Param4 = 0x00000000U;
2586	ptp.Param5 = 0x00000000U;
2587	ptp.Nparam = 5;
2588	ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &opldata, &oplsize);
2589	if (ret == PTP_RC_OK) *nrofprops = ptp_unpack_OPL(params, opldata, props, oplsize);
2590	if (opldata != NULL)
2591		free(opldata);
2592	return ret;
2593}
2594
2595uint16_t
2596ptp_mtp_sendobjectproplist (PTPParams* params, uint32_t* store, uint32_t* parenthandle, uint32_t* handle,
2597			    uint16_t objecttype, uint64_t objectsize, MTPProperties *props, int nrofprops)
2598{
2599	uint16_t ret;
2600	PTPContainer ptp;
2601	unsigned char* opldata=NULL;
2602	uint32_t oplsize;
2603
2604	PTP_CNT_INIT(ptp);
2605	ptp.Code = PTP_OC_MTP_SendObjectPropList;
2606	ptp.Param1 = *store;
2607	ptp.Param2 = *parenthandle;
2608	ptp.Param3 = (uint32_t) objecttype;
2609	ptp.Param4 = (uint32_t) (objectsize >> 32);
2610	ptp.Param5 = (uint32_t) (objectsize & 0xffffffffU);
2611	ptp.Nparam = 5;
2612
2613	/* Set object handle to 0 for a new object */
2614	oplsize = ptp_pack_OPL(params,props,nrofprops,&opldata);
2615	ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, oplsize, &opldata, NULL);
2616	free(opldata);
2617	*store = ptp.Param1;
2618	*parenthandle = ptp.Param2;
2619	*handle = ptp.Param3;
2620
2621	return ret;
2622}
2623
2624uint16_t
2625ptp_mtp_setobjectproplist (PTPParams* params, MTPProperties *props, int nrofprops)
2626{
2627	uint16_t ret;
2628	PTPContainer ptp;
2629	unsigned char* opldata=NULL;
2630	uint32_t oplsize;
2631
2632	PTP_CNT_INIT(ptp);
2633	ptp.Code = PTP_OC_MTP_SetObjPropList;
2634	ptp.Nparam = 0;
2635
2636	oplsize = ptp_pack_OPL(params,props,nrofprops,&opldata);
2637	ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, oplsize, &opldata, NULL);
2638	free(opldata);
2639
2640	return ret;
2641}
2642
2643/* Non PTP protocol functions */
2644/* devinfo testing functions */
2645
2646int
2647ptp_operation_issupported(PTPParams* params, uint16_t operation)
2648{
2649	int i=0;
2650
2651	for (;i<params->deviceinfo.OperationsSupported_len;i++) {
2652		if (params->deviceinfo.OperationsSupported[i]==operation)
2653			return 1;
2654	}
2655	return 0;
2656}
2657
2658
2659int
2660ptp_event_issupported(PTPParams* params, uint16_t event)
2661{
2662	int i=0;
2663
2664	for (;i<params->deviceinfo.EventsSupported_len;i++) {
2665		if (params->deviceinfo.EventsSupported[i]==event)
2666			return 1;
2667	}
2668	return 0;
2669}
2670
2671
2672int
2673ptp_property_issupported(PTPParams* params, uint16_t property)
2674{
2675	int i;
2676
2677	for (i=0;i<params->deviceinfo.DevicePropertiesSupported_len;i++)
2678		if (params->deviceinfo.DevicePropertiesSupported[i]==property)
2679			return 1;
2680	return 0;
2681}
2682
2683/* ptp structures freeing functions */
2684void
2685ptp_free_devicepropvalue(uint16_t dt, PTPPropertyValue* dpd) {
2686	switch (dt) {
2687	case PTP_DTC_INT8:	case PTP_DTC_UINT8:
2688	case PTP_DTC_UINT16:	case PTP_DTC_INT16:
2689	case PTP_DTC_UINT32:	case PTP_DTC_INT32:
2690	case PTP_DTC_UINT64:	case PTP_DTC_INT64:
2691	case PTP_DTC_UINT128:	case PTP_DTC_INT128:
2692		/* Nothing to free */
2693		break;
2694	case PTP_DTC_AINT8:	case PTP_DTC_AUINT8:
2695	case PTP_DTC_AUINT16:	case PTP_DTC_AINT16:
2696	case PTP_DTC_AUINT32:	case PTP_DTC_AINT32:
2697	case PTP_DTC_AUINT64:	case PTP_DTC_AINT64:
2698	case PTP_DTC_AUINT128:	case PTP_DTC_AINT128:
2699		if (dpd->a.v)
2700			free(dpd->a.v);
2701		break;
2702	case PTP_DTC_STR:
2703		if (dpd->str)
2704			free(dpd->str);
2705		break;
2706	}
2707}
2708
2709void
2710ptp_free_devicepropdesc(PTPDevicePropDesc* dpd)
2711{
2712	uint16_t i;
2713
2714	ptp_free_devicepropvalue (dpd->DataType, &dpd->FactoryDefaultValue);
2715	ptp_free_devicepropvalue (dpd->DataType, &dpd->CurrentValue);
2716	switch (dpd->FormFlag) {
2717	case PTP_DPFF_Range:
2718		ptp_free_devicepropvalue (dpd->DataType, &dpd->FORM.Range.MinimumValue);
2719		ptp_free_devicepropvalue (dpd->DataType, &dpd->FORM.Range.MaximumValue);
2720		ptp_free_devicepropvalue (dpd->DataType, &dpd->FORM.Range.StepSize);
2721		break;
2722	case PTP_DPFF_Enumeration:
2723		if (dpd->FORM.Enum.SupportedValue) {
2724			for (i=0;i<dpd->FORM.Enum.NumberOfValues;i++)
2725				ptp_free_devicepropvalue (dpd->DataType, dpd->FORM.Enum.SupportedValue+i);
2726			free (dpd->FORM.Enum.SupportedValue);
2727		}
2728	}
2729}
2730
2731void
2732ptp_free_objectpropdesc(PTPObjectPropDesc* opd)
2733{
2734	uint16_t i;
2735
2736	ptp_free_devicepropvalue (opd->DataType, &opd->FactoryDefaultValue);
2737	switch (opd->FormFlag) {
2738	case PTP_OPFF_None:
2739		break;
2740	case PTP_OPFF_Range:
2741		ptp_free_devicepropvalue (opd->DataType, &opd->FORM.Range.MinimumValue);
2742		ptp_free_devicepropvalue (opd->DataType, &opd->FORM.Range.MaximumValue);
2743		ptp_free_devicepropvalue (opd->DataType, &opd->FORM.Range.StepSize);
2744		break;
2745	case PTP_OPFF_Enumeration:
2746		if (opd->FORM.Enum.SupportedValue) {
2747			for (i=0;i<opd->FORM.Enum.NumberOfValues;i++)
2748				ptp_free_devicepropvalue (opd->DataType, opd->FORM.Enum.SupportedValue+i);
2749			free (opd->FORM.Enum.SupportedValue);
2750		}
2751		break;
2752	case PTP_OPFF_DateTime:
2753	case PTP_OPFF_FixedLengthArray:
2754	case PTP_OPFF_RegularExpression:
2755	case PTP_OPFF_ByteArray:
2756	case PTP_OPFF_LongString:
2757		/* Ignore these presently, we cannot unpack them, so there is nothing to be freed. */
2758		break;
2759	default:
2760		fprintf (stderr, "Unknown OPFF type %d\n", opd->FormFlag);
2761		break;
2762	}
2763}
2764
2765void
2766ptp_free_objectinfo (PTPObjectInfo *oi)
2767{
2768	if (!oi) return;
2769        free (oi->Filename); oi->Filename = NULL;
2770        free (oi->Keywords); oi->Keywords = NULL;
2771}
2772
2773void
2774ptp_free_object (PTPObject *ob)
2775{
2776	int i;
2777	if (!ob) return;
2778
2779	ptp_free_objectinfo (&ob->oi);
2780	for (i=0;i<ob->nrofmtpprops;i++)
2781		ptp_destroy_object_prop(&ob->mtpprops[i]);
2782	ob->flags = 0;
2783}
2784
2785void
2786ptp_perror(PTPParams* params, uint16_t error) {
2787
2788	int i;
2789	/* PTP error descriptions */
2790	static struct {
2791		short n;
2792		const char *txt;
2793	} ptp_errors[] = {
2794	{PTP_RC_Undefined, 		N_("PTP: Undefined Error")},
2795	{PTP_RC_OK, 			N_("PTP: OK!")},
2796	{PTP_RC_GeneralError, 		N_("PTP: General Error")},
2797	{PTP_RC_SessionNotOpen, 	N_("PTP: Session Not Open")},
2798	{PTP_RC_InvalidTransactionID, 	N_("PTP: Invalid Transaction ID")},
2799	{PTP_RC_OperationNotSupported, 	N_("PTP: Operation Not Supported")},
2800	{PTP_RC_ParameterNotSupported, 	N_("PTP: Parameter Not Supported")},
2801	{PTP_RC_IncompleteTransfer, 	N_("PTP: Incomplete Transfer")},
2802	{PTP_RC_InvalidStorageId, 	N_("PTP: Invalid Storage ID")},
2803	{PTP_RC_InvalidObjectHandle, 	N_("PTP: Invalid Object Handle")},
2804	{PTP_RC_DevicePropNotSupported, N_("PTP: Device Prop Not Supported")},
2805	{PTP_RC_InvalidObjectFormatCode, N_("PTP: Invalid Object Format Code")},
2806	{PTP_RC_StoreFull, 		N_("PTP: Store Full")},
2807	{PTP_RC_ObjectWriteProtected, 	N_("PTP: Object Write Protected")},
2808	{PTP_RC_StoreReadOnly, 		N_("PTP: Store Read Only")},
2809	{PTP_RC_AccessDenied,		N_("PTP: Access Denied")},
2810	{PTP_RC_NoThumbnailPresent, 	N_("PTP: No Thumbnail Present")},
2811	{PTP_RC_SelfTestFailed, 	N_("PTP: Self Test Failed")},
2812	{PTP_RC_PartialDeletion, 	N_("PTP: Partial Deletion")},
2813	{PTP_RC_StoreNotAvailable, 	N_("PTP: Store Not Available")},
2814	{PTP_RC_SpecificationByFormatUnsupported,
2815				N_("PTP: Specification By Format Unsupported")},
2816	{PTP_RC_NoValidObjectInfo, 	N_("PTP: No Valid Object Info")},
2817	{PTP_RC_InvalidCodeFormat, 	N_("PTP: Invalid Code Format")},
2818	{PTP_RC_UnknownVendorCode, 	N_("PTP: Unknown Vendor Code")},
2819	{PTP_RC_CaptureAlreadyTerminated,
2820					N_("PTP: Capture Already Terminated")},
2821	{PTP_RC_DeviceBusy, 		N_("PTP: Device Busy")},
2822	{PTP_RC_InvalidParentObject, 	N_("PTP: Invalid Parent Object")},
2823	{PTP_RC_InvalidDevicePropFormat, N_("PTP: Invalid Device Prop Format")},
2824	{PTP_RC_InvalidDevicePropValue, N_("PTP: Invalid Device Prop Value")},
2825	{PTP_RC_InvalidParameter, 	N_("PTP: Invalid Parameter")},
2826	{PTP_RC_SessionAlreadyOpened, 	N_("PTP: Session Already Opened")},
2827	{PTP_RC_TransactionCanceled, 	N_("PTP: Transaction Canceled")},
2828	{PTP_RC_SpecificationOfDestinationUnsupported,
2829			N_("PTP: Specification Of Destination Unsupported")},
2830	{PTP_RC_EK_FilenameRequired,	N_("PTP: EK Filename Required")},
2831	{PTP_RC_EK_FilenameConflicts,	N_("PTP: EK Filename Conflicts")},
2832	{PTP_RC_EK_FilenameInvalid,	N_("PTP: EK Filename Invalid")},
2833
2834	{PTP_ERROR_IO,		  N_("PTP: I/O error")},
2835	{PTP_ERROR_BADPARAM,	  N_("PTP: Error: bad parameter")},
2836	{PTP_ERROR_DATA_EXPECTED, N_("PTP: Protocol error, data expected")},
2837	{PTP_ERROR_RESP_EXPECTED, N_("PTP: Protocol error, response expected")},
2838	{0, NULL}
2839};
2840
2841	for (i=0; ptp_errors[i].txt!=NULL; i++)
2842		if (ptp_errors[i].n == error)
2843			ptp_error(params, ptp_errors[i].txt);
2844}
2845
2846const char*
2847ptp_get_property_description(PTPParams* params, uint16_t dpc)
2848{
2849	int i;
2850	/* Device Property descriptions */
2851	struct {
2852		uint16_t dpc;
2853		const char *txt;
2854	} ptp_device_properties[] = {
2855		{PTP_DPC_Undefined,		N_("Undefined PTP Property")},
2856		{PTP_DPC_BatteryLevel,		N_("Battery Level")},
2857		{PTP_DPC_FunctionalMode,	N_("Functional Mode")},
2858		{PTP_DPC_ImageSize,		N_("Image Size")},
2859		{PTP_DPC_CompressionSetting,	N_("Compression Setting")},
2860		{PTP_DPC_WhiteBalance,		N_("White Balance")},
2861		{PTP_DPC_RGBGain,		N_("RGB Gain")},
2862		{PTP_DPC_FNumber,		N_("F-Number")},
2863		{PTP_DPC_FocalLength,		N_("Focal Length")},
2864		{PTP_DPC_FocusDistance,		N_("Focus Distance")},
2865		{PTP_DPC_FocusMode,		N_("Focus Mode")},
2866		{PTP_DPC_ExposureMeteringMode,	N_("Exposure Metering Mode")},
2867		{PTP_DPC_FlashMode,		N_("Flash Mode")},
2868		{PTP_DPC_ExposureTime,		N_("Exposure Time")},
2869		{PTP_DPC_ExposureProgramMode,	N_("Exposure Program Mode")},
2870		{PTP_DPC_ExposureIndex,
2871					N_("Exposure Index (film speed ISO)")},
2872		{PTP_DPC_ExposureBiasCompensation,
2873					N_("Exposure Bias Compensation")},
2874		{PTP_DPC_DateTime,		N_("Date & Time")},
2875		{PTP_DPC_CaptureDelay,		N_("Pre-Capture Delay")},
2876		{PTP_DPC_StillCaptureMode,	N_("Still Capture Mode")},
2877		{PTP_DPC_Contrast,		N_("Contrast")},
2878		{PTP_DPC_Sharpness,		N_("Sharpness")},
2879		{PTP_DPC_DigitalZoom,		N_("Digital Zoom")},
2880		{PTP_DPC_EffectMode,		N_("Effect Mode")},
2881		{PTP_DPC_BurstNumber,		N_("Burst Number")},
2882		{PTP_DPC_BurstInterval,		N_("Burst Interval")},
2883		{PTP_DPC_TimelapseNumber,	N_("Timelapse Number")},
2884		{PTP_DPC_TimelapseInterval,	N_("Timelapse Interval")},
2885		{PTP_DPC_FocusMeteringMode,	N_("Focus Metering Mode")},
2886		{PTP_DPC_UploadURL,		N_("Upload URL")},
2887		{PTP_DPC_Artist,		N_("Artist")},
2888		{PTP_DPC_CopyrightInfo,		N_("Copyright Info")},
2889		{0,NULL}
2890	};
2891	struct {
2892		uint16_t dpc;
2893		const char *txt;
2894	} ptp_device_properties_EK[] = {
2895		{PTP_DPC_EK_ColorTemperature,	N_("Color Temperature")},
2896		{PTP_DPC_EK_DateTimeStampFormat,
2897					N_("Date Time Stamp Format")},
2898		{PTP_DPC_EK_BeepMode,		N_("Beep Mode")},
2899		{PTP_DPC_EK_VideoOut,		N_("Video Out")},
2900		{PTP_DPC_EK_PowerSaving,	N_("Power Saving")},
2901		{PTP_DPC_EK_UI_Language,	N_("UI Language")},
2902		{0,NULL}
2903	};
2904
2905	struct {
2906		uint16_t dpc;
2907		const char *txt;
2908	} ptp_device_properties_Canon[] = {
2909		{PTP_DPC_CANON_BeepMode,	N_("Beep Mode")},
2910		{PTP_DPC_CANON_BatteryKind,	N_("Battery Type")},
2911		{PTP_DPC_CANON_BatteryStatus,	N_("Battery Mode")},
2912		{PTP_DPC_CANON_UILockType,	N_("UILockType")},
2913		{PTP_DPC_CANON_CameraMode,	N_("Camera Mode")},
2914		{PTP_DPC_CANON_ImageQuality,	N_("Image Quality")},
2915		{PTP_DPC_CANON_FullViewFileFormat,	N_("Full View File Format")},
2916		{PTP_DPC_CANON_ImageSize,	N_("Image Size")},
2917		{PTP_DPC_CANON_SelfTime,	N_("Self Time")},
2918		{PTP_DPC_CANON_FlashMode,	N_("Flash Mode")},
2919		{PTP_DPC_CANON_Beep,		N_("Beep")},
2920		{PTP_DPC_CANON_ShootingMode,	N_("Shooting Mode")},
2921		{PTP_DPC_CANON_ImageMode,	N_("Image Mode")},
2922		{PTP_DPC_CANON_DriveMode,	N_("Drive Mode")},
2923		{PTP_DPC_CANON_EZoom,		N_("Zoom")},
2924		{PTP_DPC_CANON_MeteringMode,	N_("Metering Mode")},
2925		{PTP_DPC_CANON_AFDistance,	N_("AF Distance")},
2926		{PTP_DPC_CANON_FocusingPoint,	N_("Focusing Point")},
2927		{PTP_DPC_CANON_WhiteBalance,	N_("White Balance")},
2928		{PTP_DPC_CANON_SlowShutterSetting,	N_("Slow Shutter Setting")},
2929		{PTP_DPC_CANON_AFMode,		N_("AF Mode")},
2930		{PTP_DPC_CANON_ImageStabilization,		N_("Image Stabilization")},
2931		{PTP_DPC_CANON_Contrast,	N_("Contrast")},
2932		{PTP_DPC_CANON_ColorGain,	N_("Color Gain")},
2933		{PTP_DPC_CANON_Sharpness,	N_("Sharpness")},
2934		{PTP_DPC_CANON_Sensitivity,	N_("Sensitivity")},
2935		{PTP_DPC_CANON_ParameterSet,	N_("Parameter Set")},
2936		{PTP_DPC_CANON_ISOSpeed,	N_("ISO Speed")},
2937		{PTP_DPC_CANON_Aperture,	N_("Aperture")},
2938		{PTP_DPC_CANON_ShutterSpeed,	N_("Shutter Speed")},
2939		{PTP_DPC_CANON_ExpCompensation,	N_("Exposure Compensation")},
2940		{PTP_DPC_CANON_FlashCompensation,	N_("Flash Compensation")},
2941		{PTP_DPC_CANON_AEBExposureCompensation,	N_("AEB Exposure Compensation")},
2942		{PTP_DPC_CANON_AvOpen,		N_("Av Open")},
2943		{PTP_DPC_CANON_AvMax,		N_("Av Max")},
2944		{PTP_DPC_CANON_FocalLength,	N_("Focal Length")},
2945		{PTP_DPC_CANON_FocalLengthTele,	N_("Focal Length Tele")},
2946		{PTP_DPC_CANON_FocalLengthWide,	N_("Focal Length Wide")},
2947		{PTP_DPC_CANON_FocalLengthDenominator,	N_("Focal Length Denominator")},
2948		{PTP_DPC_CANON_CaptureTransferMode,	N_("Capture Transfer Mode")},
2949		{PTP_DPC_CANON_Zoom,		N_("Zoom")},
2950		{PTP_DPC_CANON_NamePrefix,	N_("Name Prefix")},
2951		{PTP_DPC_CANON_SizeQualityMode,	N_("Size Quality Mode")},
2952		{PTP_DPC_CANON_SupportedThumbSize,	N_("Supported Thumb Size")},
2953		{PTP_DPC_CANON_SizeOfOutputDataFromCamera,	N_("Size of Output Data from Camera")},
2954		{PTP_DPC_CANON_SizeOfInputDataToCamera,		N_("Size of Input Data to Camera")},
2955		{PTP_DPC_CANON_RemoteAPIVersion,N_("Remote API Version")},
2956		{PTP_DPC_CANON_FirmwareVersion,	N_("Firmware Version")},
2957		{PTP_DPC_CANON_CameraModel,	N_("Camera Model")},
2958		{PTP_DPC_CANON_CameraOwner,	N_("Camera Owner")},
2959		{PTP_DPC_CANON_UnixTime,	N_("UNIX Time")},
2960		{PTP_DPC_CANON_CameraBodyID,	N_("Camera Body ID")},
2961		{PTP_DPC_CANON_CameraOutput,	N_("Camera Output")},
2962		{PTP_DPC_CANON_DispAv,		N_("Disp Av")},
2963		{PTP_DPC_CANON_AvOpenApex,	N_("Av Open Apex")},
2964		{PTP_DPC_CANON_DZoomMagnification,	N_("Digital Zoom Magnification")},
2965		{PTP_DPC_CANON_MlSpotPos,	N_("Ml Spot Position")},
2966		{PTP_DPC_CANON_DispAvMax,	N_("Disp Av Max")},
2967		{PTP_DPC_CANON_AvMaxApex,	N_("Av Max Apex")},
2968		{PTP_DPC_CANON_EZoomStartPosition,	N_("EZoom Start Position")},
2969		{PTP_DPC_CANON_FocalLengthOfTele,	N_("Focal Length Tele")},
2970		{PTP_DPC_CANON_EZoomSizeOfTele,	N_("EZoom Size of Tele")},
2971		{PTP_DPC_CANON_PhotoEffect,	N_("Photo Effect")},
2972		{PTP_DPC_CANON_AssistLight,	N_("Assist Light")},
2973		{PTP_DPC_CANON_FlashQuantityCount,	N_("Flash Quantity Count")},
2974		{PTP_DPC_CANON_RotationAngle,	N_("Rotation Angle")},
2975		{PTP_DPC_CANON_RotationScene,	N_("Rotation Scene")},
2976		{PTP_DPC_CANON_EventEmulateMode,N_("Event Emulate Mode")},
2977		{PTP_DPC_CANON_DPOFVersion,	N_("DPOF Version")},
2978		{PTP_DPC_CANON_TypeOfSupportedSlideShow,	N_("Type of Slideshow")},
2979		{PTP_DPC_CANON_AverageFilesizes,N_("Average Filesizes")},
2980		{PTP_DPC_CANON_ModelID,		N_("Model ID")},
2981		{0,NULL}
2982	};
2983
2984	struct {
2985		uint16_t dpc;
2986		const char *txt;
2987	} ptp_device_properties_Nikon[] = {
2988		{PTP_DPC_NIKON_ShootingBank, 			/* 0xD010 */
2989		 N_("Shooting Bank")},
2990		{PTP_DPC_NIKON_ShootingBankNameA,		/* 0xD011 */
2991		 N_("Shooting Bank Name A")},
2992		{PTP_DPC_NIKON_ShootingBankNameB,		/* 0xD012 */
2993		 N_("Shooting Bank Name B")},
2994		{PTP_DPC_NIKON_ShootingBankNameC,		/* 0xD013 */
2995		 N_("Shooting Bank Name C")},
2996		{PTP_DPC_NIKON_ShootingBankNameD,		/* 0xD014 */
2997		 N_("Shooting Bank Name D")},
2998		{PTP_DPC_NIKON_ResetBank0,			/* 0xD015 */
2999		 N_("Reset Bank 0")},
3000		{PTP_DPC_NIKON_RawCompression,			/* 0xD016 */
3001		 N_("Raw Compression")},
3002		{PTP_DPC_NIKON_WhiteBalanceAutoBias,		/* 0xD017 */
3003		 N_("Auto White Balance Bias")},
3004		{PTP_DPC_NIKON_WhiteBalanceTungstenBias,	/* 0xD018 */
3005		 N_("Tungsten White Balance Bias")},
3006		{PTP_DPC_NIKON_WhiteBalanceFluorescentBias,	/* 0xD019 */
3007		 N_("Fluorescent White Balance Bias")},
3008		{PTP_DPC_NIKON_WhiteBalanceDaylightBias,	/* 0xD01a */
3009		 N_("Daylight White Balance Bias")},
3010		{PTP_DPC_NIKON_WhiteBalanceFlashBias,		/* 0xD01b */
3011		 N_("Flash White Balance Bias")},
3012		{PTP_DPC_NIKON_WhiteBalanceCloudyBias,		/* 0xD01c */
3013		 N_("Cloudy White Balance Bias")},
3014		{PTP_DPC_NIKON_WhiteBalanceShadeBias,		/* 0xD01d */
3015		 N_("Shady White Balance Bias")},
3016		{PTP_DPC_NIKON_WhiteBalanceColorTemperature,	/* 0xD01e */
3017		 N_("White Balance Colour Temperature")},
3018		{PTP_DPC_NIKON_WhiteBalancePresetNo,		/* 0xD01f */
3019		 N_("White Balance Preset Number")},
3020		{PTP_DPC_NIKON_WhiteBalancePresetName0,		/* 0xD020 */
3021		 N_("White Balance Preset Name 0")},
3022		{PTP_DPC_NIKON_WhiteBalancePresetName1,		/* 0xD021 */
3023		 N_("White Balance Preset Name 1")},
3024		{PTP_DPC_NIKON_WhiteBalancePresetName2,		/* 0xD022 */
3025		 N_("White Balance Preset Name 2")},
3026		{PTP_DPC_NIKON_WhiteBalancePresetName3,		/* 0xD023 */
3027		 N_("White Balance Preset Name 3")},
3028		{PTP_DPC_NIKON_WhiteBalancePresetName4,		/* 0xD024 */
3029		 N_("White Balance Preset Name 4")},
3030		{PTP_DPC_NIKON_WhiteBalancePresetVal0,		/* 0xD025 */
3031		 N_("White Balance Preset Value 0")},
3032		{PTP_DPC_NIKON_WhiteBalancePresetVal1,		/* 0xD026 */
3033		 N_("White Balance Preset Value 1")},
3034		{PTP_DPC_NIKON_WhiteBalancePresetVal2,		/* 0xD027 */
3035		 N_("White Balance Preset Value 2")},
3036		{PTP_DPC_NIKON_WhiteBalancePresetVal3,		/* 0xD028 */
3037		 N_("White Balance Preset Value 3")},
3038		{PTP_DPC_NIKON_WhiteBalancePresetVal4,		/* 0xD029 */
3039		 N_("White Balance Preset Value 4")},
3040		{PTP_DPC_NIKON_ImageSharpening,			/* 0xD02a */
3041		 N_("Sharpening")},
3042		{PTP_DPC_NIKON_ToneCompensation,		/* 0xD02b */
3043		 N_("Tone Compensation")},
3044		{PTP_DPC_NIKON_ColorModel,			/* 0xD02c */
3045		 N_("Color Model")},
3046		{PTP_DPC_NIKON_HueAdjustment,			/* 0xD02d */
3047		 N_("Hue Adjustment")},
3048		{PTP_DPC_NIKON_NonCPULensDataFocalLength,	/* 0xD02e */
3049		 N_("Lens Focal Length (Non CPU)")},
3050		{PTP_DPC_NIKON_NonCPULensDataMaximumAperture,	/* 0xD02f */
3051		 N_("Lens Maximum Aperture (Non CPU)")},
3052		{PTP_DPC_NIKON_ShootingMode,			/* 0xD030 */
3053		 N_("Shooting Mode")},
3054		{PTP_DPC_NIKON_JPEG_Compression_Policy,		/* 0xD031 */
3055		 N_("JPEG Compression Policy")},
3056		{PTP_DPC_NIKON_ColorSpace,			/* 0xD032 */
3057		 N_("Color Space")},
3058		{PTP_DPC_NIKON_AutoDXCrop,			/* 0xD033 */
3059		 N_("Auto DX Crop")},
3060		{PTP_DPC_NIKON_CSMMenuBankSelect,		/* 0xD040 */
3061		 "PTP_DPC_NIKON_CSMMenuBankSelect"},
3062		{PTP_DPC_NIKON_MenuBankNameA,			/* 0xD041 */
3063		 N_("Menu Bank Name A")},
3064		{PTP_DPC_NIKON_MenuBankNameB,			/* 0xD042 */
3065		 N_("Menu Bank Name B")},
3066		{PTP_DPC_NIKON_MenuBankNameC,			/* 0xD043 */
3067		 N_("Menu Bank Name C")},
3068		{PTP_DPC_NIKON_MenuBankNameD,			/* 0xD044 */
3069		 N_("Menu Bank Name D")},
3070		{PTP_DPC_NIKON_ResetBank,			/* 0xD045 */
3071		 N_("Reset Menu Bank")},
3072		{PTP_DPC_NIKON_A1AFCModePriority,		/* 0xD048 */
3073		 "PTP_DPC_NIKON_A1AFCModePriority"},
3074		{PTP_DPC_NIKON_A2AFSModePriority,		/* 0xD049 */
3075		 "PTP_DPC_NIKON_A2AFSModePriority"},
3076		{PTP_DPC_NIKON_A3GroupDynamicAF,		/* 0xD04a */
3077		 "PTP_DPC_NIKON_A3GroupDynamicAF"},
3078		{PTP_DPC_NIKON_A4AFActivation,			/* 0xD04b */
3079		 "PTP_DPC_NIKON_A4AFActivation"},
3080		{PTP_DPC_NIKON_FocusAreaIllumManualFocus,	/* 0xD04c */
3081		 "PTP_DPC_NIKON_FocusAreaIllumManualFocus"},
3082		{PTP_DPC_NIKON_FocusAreaIllumContinuous,	/* 0xD04d */
3083		 "PTP_DPC_NIKON_FocusAreaIllumContinuous"},
3084		{PTP_DPC_NIKON_FocusAreaIllumWhenSelected,	/* 0xD04e */
3085		 "PTP_DPC_NIKON_FocusAreaIllumWhenSelected"},
3086		{PTP_DPC_NIKON_FocusAreaWrap,			/* 0xD04f */
3087		 N_("Focus Area Wrap")},
3088		{PTP_DPC_NIKON_VerticalAFON,			/* 0xD050 */
3089		 N_("Vertical AF On")},
3090		{PTP_DPC_NIKON_AFLockOn,			/* 0xD051 */
3091		 N_("AF Lock On")},
3092		{PTP_DPC_NIKON_FocusAreaZone,			/* 0xD052 */
3093		 N_("Focus Area Zone")},
3094		{PTP_DPC_NIKON_EnableCopyright,			/* 0xD053 */
3095		 N_("Enable Copyright")},
3096		{PTP_DPC_NIKON_ISOAuto,				/* 0xD054 */
3097		 N_("Auto ISO")},
3098		{PTP_DPC_NIKON_EVISOStep,			/* 0xD055 */
3099		 N_("Exposure ISO Step")},
3100		{PTP_DPC_NIKON_EVStep,				/* 0xD056 */
3101		 N_("Exposure Step")},
3102		{PTP_DPC_NIKON_EVStepExposureComp,		/* 0xD057 */
3103		 N_("Exposure Compensation (EV)")},
3104		{PTP_DPC_NIKON_ExposureCompensation,		/* 0xD058 */
3105		 N_("Exposure Compensation")},
3106		{PTP_DPC_NIKON_CenterWeightArea,		/* 0xD059 */
3107		 N_("Centre Weight Area")},
3108		{PTP_DPC_NIKON_ExposureBaseMatrix,		/* 0xD05A */
3109		 N_("Exposure Base Matrix")},
3110		{PTP_DPC_NIKON_ExposureBaseCenter,		/* 0xD05B */
3111		 N_("Exposure Base Center")},
3112		{PTP_DPC_NIKON_ExposureBaseSpot,		/* 0xD05C */
3113		 N_("Exposure Base Spot")},
3114		{PTP_DPC_NIKON_LiveViewAF,			/* 0xD05D */
3115		 N_("Live View AF")},
3116		{PTP_DPC_NIKON_AELockMode,			/* 0xD05E */
3117		 N_("Exposure Lock")},
3118		{PTP_DPC_NIKON_AELAFLMode,			/* 0xD05F */
3119		 N_("Focus Lock")},
3120		{PTP_DPC_NIKON_MeterOff,			/* 0xD062 */
3121		 N_("Auto Meter Off Time")},
3122		{PTP_DPC_NIKON_SelfTimer,			/* 0xD063 */
3123		 N_("Self Timer Delay")},
3124		{PTP_DPC_NIKON_MonitorOff,			/* 0xD064 */
3125		 N_("LCD Off Time")},
3126		{PTP_DPC_NIKON_ImgConfTime,			/* 0xD065 */
3127		 N_("Img Conf Time")},
3128		{PTP_DPC_NIKON_AngleLevel,			/* 0xD067 */
3129		 N_("Angle Level")},
3130		{PTP_DPC_NIKON_D1ShootingSpeed,			/* 0xD068 */
3131		 N_("Shooting Speed")},
3132		{PTP_DPC_NIKON_D2MaximumShots,			/* 0xD069 */
3133		 N_("Maximum Shots")},
3134		{PTP_DPC_NIKON_D3ExpDelayMode,			/* 0xD06A */
3135		 N_("Exposure delay mode")},
3136		{PTP_DPC_NIKON_LongExposureNoiseReduction,	/* 0xD06B */
3137		 N_("Long Exposure Noise Reduction")},
3138		{PTP_DPC_NIKON_FileNumberSequence,		/* 0xD06C */
3139		 N_("File Number Sequencing")},
3140		{PTP_DPC_NIKON_ControlPanelFinderRearControl,	/* 0xD06D */
3141		 "PTP_DPC_NIKON_ControlPanelFinderRearControl"},
3142		{PTP_DPC_NIKON_ControlPanelFinderViewfinder,	/* 0xD06E */
3143		 "PTP_DPC_NIKON_ControlPanelFinderViewfinder"},
3144		{PTP_DPC_NIKON_D7Illumination,			/* 0xD06F */
3145		 N_("LCD Illumination")},
3146		{PTP_DPC_NIKON_NrHighISO,			/* 0xD070 */
3147		 N_("High ISO noise reduction")},
3148		{PTP_DPC_NIKON_SHSET_CH_GUID_DISP,		/* 0xD071 */
3149		 N_("On screen tips")},
3150		{PTP_DPC_NIKON_ArtistName,			/* 0xD072 */
3151		 N_("Artist Name")},
3152		{PTP_DPC_NIKON_CopyrightInfo,			/* 0xD073 */
3153		 N_("Copyright Information")},
3154		{PTP_DPC_NIKON_FlashSyncSpeed,			/* 0xD074 */
3155		 N_("Flash Sync. Speed")},
3156		{PTP_DPC_NIKON_FlashShutterSpeed,		/* 0xD075 */
3157		 N_("Flash Shutter Speed")},
3158		{PTP_DPC_NIKON_E3AAFlashMode,			/* 0xD076 */
3159		 N_("Flash Mode")},
3160		{PTP_DPC_NIKON_E4ModelingFlash,			/* 0xD077 */
3161		 N_("Modeling Flash")},
3162		{PTP_DPC_NIKON_BracketSet,			/* 0xD078 */
3163		 N_("Bracket Set")},
3164		{PTP_DPC_NIKON_E6ManualModeBracketing,		/* 0xD079 */
3165		 N_("Manual Mode Bracketing")},
3166		{PTP_DPC_NIKON_BracketOrder,			/* 0xD07A */
3167		 N_("Bracket Order")},
3168		{PTP_DPC_NIKON_E8AutoBracketSelection,		/* 0xD07B */
3169		 N_("Auto Bracket Selection")},
3170		{PTP_DPC_NIKON_BracketingSet, N_("NIKON Auto Bracketing Set")},	/* 0xD07C */
3171		{PTP_DPC_NIKON_F1CenterButtonShootingMode,	/* 0xD080 */
3172		 N_("Center Button Shooting Mode")},
3173		{PTP_DPC_NIKON_CenterButtonPlaybackMode,	/* 0xD081 */
3174		 N_("Center Button Playback Mode")},
3175		{PTP_DPC_NIKON_F2Multiselector,			/* 0xD082 */
3176		 N_("Multiselector")},
3177		{PTP_DPC_NIKON_F3PhotoInfoPlayback,		/* 0xD083 */
3178		 N_("Photo Info. Playback")},
3179		{PTP_DPC_NIKON_F4AssignFuncButton,		/* 0xD084 */
3180		 N_("Assign Func. Button")},
3181		{PTP_DPC_NIKON_F5CustomizeCommDials,		/* 0xD085 */
3182		 N_("Customise Command Dials")},
3183		{PTP_DPC_NIKON_ReverseCommandDial,		/* 0xD086 */
3184		 N_("Reverse Command Dial")},
3185		{PTP_DPC_NIKON_ApertureSetting,			/* 0xD087 */
3186		 N_("Aperture Setting")},
3187		{PTP_DPC_NIKON_MenusAndPlayback,		/* 0xD088 */
3188		 N_("Menus and Playback")},
3189		{PTP_DPC_NIKON_F6ButtonsAndDials,		/* 0xD089 */
3190		 N_("Buttons and Dials")},
3191		{PTP_DPC_NIKON_NoCFCard,			/* 0xD08A */
3192		 N_("No CF Card Release")},
3193		{PTP_DPC_NIKON_CenterButtonZoomRatio,		/* 0xD08B */
3194		 N_("Center Button Zoom Ratio")},
3195		{PTP_DPC_NIKON_FunctionButton2,			/* 0xD08C */
3196		 N_("Function Button 2")},
3197		{PTP_DPC_NIKON_AFAreaPoint,			/* 0xD08D */
3198		 N_("AF Area Point")},
3199		{PTP_DPC_NIKON_NormalAFOn,			/* 0xD08E */
3200		 N_("Normal AF On")},
3201		{PTP_DPC_NIKON_ImageCommentString,		/* 0xD090 */
3202		 N_("Image Comment String")},
3203		{PTP_DPC_NIKON_ImageCommentEnable,		/* 0xD091 */
3204		 N_("Image Comment Enable")},
3205		{PTP_DPC_NIKON_ImageRotation,			/* 0xD092 */
3206		 N_("Image Rotation")},
3207		{PTP_DPC_NIKON_ManualSetLensNo,			/* 0xD093 */
3208		 N_("Manual Set Lens Number")},
3209		{PTP_DPC_NIKON_MovScreenSize,			/* 0xD0A0 */
3210		 N_("Movie Screen Size")},
3211		{PTP_DPC_NIKON_MovVoice,			/* 0xD0A1 */
3212		 N_("Movie Voice")},
3213		{PTP_DPC_NIKON_Bracketing,			/* 0xD0C0 */
3214		 N_("Bracketing Enable")},
3215		{PTP_DPC_NIKON_AutoExposureBracketStep,		/* 0xD0C1 */
3216		 N_("Exposure Bracketing Step")},
3217		{PTP_DPC_NIKON_AutoExposureBracketProgram,	/* 0xD0C2 */
3218		 N_("Exposure Bracketing Program")},
3219		{PTP_DPC_NIKON_AutoExposureBracketCount,	/* 0xD0C3 */
3220		 N_("Auto Exposure Bracket Count")},
3221		{PTP_DPC_NIKON_WhiteBalanceBracketStep, N_("White Balance Bracket Step")}, /* 0xD0C4 */
3222		{PTP_DPC_NIKON_WhiteBalanceBracketProgram, N_("White Balance Bracket Program")}, /* 0xD0C5 */
3223		{PTP_DPC_NIKON_LensID,				/* 0xD0E0 */
3224		 N_("Lens ID")},
3225		{PTP_DPC_NIKON_LensSort,			/* 0xD0E1 */
3226		 N_("Lens Sort")},
3227		{PTP_DPC_NIKON_LensType,			/* 0xD0E2 */
3228		 N_("Lens Type")},
3229		{PTP_DPC_NIKON_FocalLengthMin,			/* 0xD0E3 */
3230		 N_("Min. Focal Length")},
3231		{PTP_DPC_NIKON_FocalLengthMax,			/* 0xD0E4 */
3232		 N_("Max. Focal Length")},
3233		{PTP_DPC_NIKON_MaxApAtMinFocalLength,		/* 0xD0E5 */
3234		 N_("Max. Aperture at Min. Focal Length")},
3235		{PTP_DPC_NIKON_MaxApAtMaxFocalLength,		/* 0xD0E6 */
3236		 N_("Max. Aperture at Max. Focal Length")},
3237		{PTP_DPC_NIKON_FinderISODisp,			/* 0xD0F0 */
3238		 N_("Finder ISO Display")},
3239		{PTP_DPC_NIKON_AutoOffPhoto,			/* 0xD0F2 */
3240		 N_("Auto Off Photo")},
3241		{PTP_DPC_NIKON_AutoOffMenu,			/* 0xD0F3 */
3242		 N_("Auto Off Menu")},
3243		{PTP_DPC_NIKON_AutoOffInfo,			/* 0xD0F4 */
3244		 N_("Auto Off Info")},
3245		{PTP_DPC_NIKON_SelfTimerShootNum,		/* 0xD0F5 */
3246		 N_("Self Timer Shot Number")},
3247		{PTP_DPC_NIKON_VignetteCtrl,			/* 0xD0F7 */
3248		 N_("Vignette Control")},
3249		{PTP_DPC_NIKON_ExposureTime,			/* 0xD100 */
3250		 N_("Nikon Exposure Time")},
3251		{PTP_DPC_NIKON_ACPower, N_("AC Power")},	/* 0xD101 */
3252		{PTP_DPC_NIKON_WarningStatus, N_("Warning Status")},/* 0xD102 */
3253		{PTP_DPC_NIKON_MaximumShots,			/* 0xD103 */
3254		 N_("Maximum Shots")},
3255		{PTP_DPC_NIKON_AFLockStatus, N_("AF Locked")},/* 0xD104 */
3256		{PTP_DPC_NIKON_AELockStatus, N_("AE Locked")},/* 0xD105 */
3257		{PTP_DPC_NIKON_FVLockStatus, N_("FV Locked")},/* 0xD106 */
3258		{PTP_DPC_NIKON_AutofocusLCDTopMode2,		/* 0xD107 */
3259		 N_("AF LCD Top Mode 2")},
3260		{PTP_DPC_NIKON_AutofocusArea,			/* 0xD108 */
3261		 N_("Active AF Sensor")},
3262		{PTP_DPC_NIKON_FlexibleProgram,			/* 0xD109 */
3263		 N_("Flexible Program")},
3264		{PTP_DPC_NIKON_LightMeter,			/* 0xD10A */
3265		 N_("Exposure Meter")},
3266		{PTP_DPC_NIKON_RecordingMedia,			/* 0xD10B */
3267		 N_("Recording Media")},
3268		{PTP_DPC_NIKON_USBSpeed,			/* 0xD10C */
3269		 N_("USB Speed")},
3270		{PTP_DPC_NIKON_CCDNumber,			/* 0xD10D */
3271		 N_("CCD Serial Number")},
3272		{PTP_DPC_NIKON_CameraOrientation,		/* 0xD10E */
3273		 N_("Camera Orientation")},
3274		{PTP_DPC_NIKON_GroupPtnType,			/* 0xD10F */
3275		 N_("Group PTN Type")},
3276		{PTP_DPC_NIKON_FNumberLock,			/* 0xD110 */
3277		 N_("FNumber Lock")},
3278		{PTP_DPC_NIKON_ExposureApertureLock,		/* 0xD111 */
3279		 N_("Exposure Aperture Lock")},
3280		{PTP_DPC_NIKON_TVLockSetting,			/* 0xD112 */
3281		 N_("TV Lock Setting")},
3282		{PTP_DPC_NIKON_AVLockSetting,			/* 0xD113 */
3283		 N_("AV Lock Setting")},
3284		{PTP_DPC_NIKON_IllumSetting,			/* 0xD114 */
3285		 N_("Illum Setting")},
3286		{PTP_DPC_NIKON_FocusPointBright,		/* 0xD115 */
3287		 N_("Focus Point Bright")},
3288		{PTP_DPC_NIKON_ExternalFlashAttached,		/* 0xD120 */
3289		 N_("External Flash Attached")},
3290		{PTP_DPC_NIKON_ExternalFlashStatus,		/* 0xD121 */
3291		 N_("External Flash Status")},
3292		{PTP_DPC_NIKON_ExternalFlashSort,		/* 0xD122 */
3293		 N_("External Flash Sort")},
3294		{PTP_DPC_NIKON_ExternalFlashMode,		/* 0xD123 */
3295		 N_("External Flash Mode")},
3296		{PTP_DPC_NIKON_ExternalFlashCompensation,	/* 0xD124 */
3297		 N_("External Flash Compensation")},
3298		{PTP_DPC_NIKON_NewExternalFlashMode,		/* 0xD125 */
3299		 N_("External Flash Mode")},
3300		{PTP_DPC_NIKON_FlashExposureCompensation,	/* 0xD126 */
3301		 N_("Flash Exposure Compensation")},
3302		{PTP_DPC_NIKON_OptimizeImage,			/* 0xD140 */
3303		 N_("Optimize Image")},
3304		{PTP_DPC_NIKON_Saturation,			/* 0xD142 */
3305		 N_("Saturation")},
3306		{PTP_DPC_NIKON_BW_FillerEffect,			/* 0xD143 */
3307		 N_("BW Filler Effect")},
3308		{PTP_DPC_NIKON_BW_Sharpness,			/* 0xD144 */
3309		 N_("BW Sharpness")},
3310		{PTP_DPC_NIKON_BW_Contrast,			/* 0xD145 */
3311		 N_("BW Contrast")},
3312		{PTP_DPC_NIKON_BW_Setting_Type,			/* 0xD146 */
3313		 N_("BW Setting Type")},
3314		{PTP_DPC_NIKON_Slot2SaveMode,			/* 0xD148 */
3315		 N_("Slot 2 Save Mode")},
3316		{PTP_DPC_NIKON_RawBitMode,			/* 0xD149 */
3317		 N_("Raw Bit Mode")},
3318		{PTP_DPC_NIKON_ISOAutoTime,			/* 0xD14E */
3319		 N_("ISO Auto Time")},
3320		{PTP_DPC_NIKON_FlourescentType,			/* 0xD14F */
3321		 N_("Flourescent Type")},
3322		{PTP_DPC_NIKON_TuneColourTemperature,		/* 0xD150 */
3323		 N_("Tune Colour Temperature")},
3324		{PTP_DPC_NIKON_TunePreset0,			/* 0xD151 */
3325		 N_("Tune Preset 0")},
3326		{PTP_DPC_NIKON_TunePreset1,			/* 0xD152 */
3327		 N_("Tune Preset 1")},
3328		{PTP_DPC_NIKON_TunePreset2,			/* 0xD153 */
3329		 N_("Tune Preset 2")},
3330		{PTP_DPC_NIKON_TunePreset3,			/* 0xD154 */
3331		 N_("Tune Preset 3")},
3332		{PTP_DPC_NIKON_TunePreset4,			/* 0xD155 */
3333		 N_("Tune Preset 4")},
3334		{PTP_DPC_NIKON_BeepOff,				/* 0xD160 */
3335		 N_("AF Beep Mode")},
3336		{PTP_DPC_NIKON_AutofocusMode,			/* 0xD161 */
3337		 N_("Autofocus Mode")},
3338		{PTP_DPC_NIKON_AFAssist,			/* 0xD163 */
3339		 N_("AF Assist Lamp")},
3340		{PTP_DPC_NIKON_PADVPMode,			/* 0xD164 */
3341		 N_("Auto ISO P/A/DVP Setting")},
3342		{PTP_DPC_NIKON_ImageReview,			/* 0xD165 */
3343		 N_("Image Review")},
3344		{PTP_DPC_NIKON_AFAreaIllumination,		/* 0xD166 */
3345		 N_("AF Area Illumination")},
3346		{PTP_DPC_NIKON_FlashMode,			/* 0xD167 */
3347		 N_("Flash Mode")},
3348		{PTP_DPC_NIKON_FlashCommanderMode,	 	/* 0xD168 */
3349		 N_("Flash Commander Mode")},
3350		{PTP_DPC_NIKON_FlashSign,			/* 0xD169 */
3351		 N_("Flash Sign")},
3352		{PTP_DPC_NIKON_ISOAuto,				/* 0xD16A */
3353		 N_("ISO Auto")},
3354		{PTP_DPC_NIKON_RemoteTimeout,			/* 0xD16B */
3355		 N_("Remote Timeout")},
3356		{PTP_DPC_NIKON_GridDisplay,			/* 0xD16C */
3357		 N_("Viewfinder Grid Display")},
3358		{PTP_DPC_NIKON_FlashModeManualPower,		/* 0xD16D */
3359		 N_("Flash Mode Manual Power")},
3360		{PTP_DPC_NIKON_FlashModeCommanderPower,		/* 0xD16E */
3361		 N_("Flash Mode Commander Power")},
3362		{PTP_DPC_NIKON_AutoFP,				/* 0xD16F */
3363		 N_("Auto FP")},
3364		{PTP_DPC_NIKON_CSMMenu,				/* 0xD180 */
3365		 N_("CSM Menu")},
3366		{PTP_DPC_NIKON_WarningDisplay,			/* 0xD181 */
3367		 N_("Warning Display")},
3368		{PTP_DPC_NIKON_BatteryCellKind,			/* 0xD182 */
3369		 N_("Battery Cell Kind")},
3370		{PTP_DPC_NIKON_ISOAutoHiLimit,			/* 0xD183 */
3371		 N_("ISO Auto High Limit")},
3372		{PTP_DPC_NIKON_DynamicAFArea,			/* 0xD184 */
3373		 N_("Dynamic AF Area")},
3374		{PTP_DPC_NIKON_ContinuousSpeedHigh,		/* 0xD186 */
3375		 N_("Continuous Speed High")},
3376		{PTP_DPC_NIKON_InfoDispSetting,			/* 0xD187 */
3377		 N_("Info Disp Setting")},
3378		{PTP_DPC_NIKON_PreviewButton,			/* 0xD189 */
3379		 N_("Preview Button")},
3380		{PTP_DPC_NIKON_PreviewButton2,			/* 0xD18A */
3381		 N_("Preview Button 2")},
3382		{PTP_DPC_NIKON_AEAFLockButton2,			/* 0xD18B */
3383		 N_("AEAF Lock Button 2")},
3384		{PTP_DPC_NIKON_IndicatorDisp,			/* 0xD18D */
3385		 N_("Indicator Display")},
3386		{PTP_DPC_NIKON_CellKindPriority,		/* 0xD18E */
3387		 N_("Cell Kind Priority")},
3388		{PTP_DPC_NIKON_BracketingFramesAndSteps,	/* 0xD190 */
3389		 N_("Bracketing Frames and Steps")},
3390		{PTP_DPC_NIKON_LiveViewMode,			/* 0xD1A0 */
3391		 N_("Live View Mode")},
3392		{PTP_DPC_NIKON_LiveViewDriveMode,		/* 0xD1A1 */
3393		 N_("Live View Drive Mode")},
3394		{PTP_DPC_NIKON_LiveViewStatus,			/* 0xD1A2 */
3395		 N_("Live View Status")},
3396		{PTP_DPC_NIKON_LiveViewImageZoomRatio,		/* 0xD1A3 */
3397		 N_("Live View Image Zoom Ratio")},
3398		{PTP_DPC_NIKON_LiveViewProhibitCondition,	/* 0xD1A4 */
3399		 N_("Live View Prohibit Condition")},
3400		{PTP_DPC_NIKON_ExposureDisplayStatus,		/* 0xD1B0 */
3401		 N_("Exposure Display Status")},
3402		{PTP_DPC_NIKON_ExposureIndicateStatus,		/* 0xD1B1 */
3403		 N_("Exposure Indicate Status")},
3404		{PTP_DPC_NIKON_ExposureIndicateLightup,		/* 0xD1B2 */
3405		 N_("Exposure Indicate Lightup")},
3406		{PTP_DPC_NIKON_FlashOpen,			/* 0xD1C0 */
3407		 N_("Flash Open")},
3408		{PTP_DPC_NIKON_FlashCharged,			/* 0xD1C1 */
3409		 N_("Flash Charged")},
3410		{PTP_DPC_NIKON_FlashMRepeatValue,		/* 0xD1D0 */
3411		 N_("Flash MRepeat Value")},
3412		{PTP_DPC_NIKON_FlashMRepeatCount,		/* 0xD1D1 */
3413		 N_("Flash MRepeat Count")},
3414		{PTP_DPC_NIKON_FlashMRepeatInterval,		/* 0xD1D2 */
3415		 N_("Flash MRepeat Interval")},
3416		{PTP_DPC_NIKON_FlashCommandChannel,		/* 0xD1D3 */
3417		 N_("Flash Command Channel")},
3418		{PTP_DPC_NIKON_FlashCommandSelfMode,		/* 0xD1D4 */
3419		 N_("Flash Command Self Mode")},
3420		{PTP_DPC_NIKON_FlashCommandSelfCompensation,	/* 0xD1D5 */
3421		 N_("Flash Command Self Compensation")},
3422		{PTP_DPC_NIKON_FlashCommandSelfValue,		/* 0xD1D6 */
3423		 N_("Flash Command Self Value")},
3424		{PTP_DPC_NIKON_FlashCommandAMode,		/* 0xD1D7 */
3425		 N_("Flash Command A Mode")},
3426		{PTP_DPC_NIKON_FlashCommandACompensation,	/* 0xD1D8 */
3427		 N_("Flash Command A Compensation")},
3428		{PTP_DPC_NIKON_FlashCommandAValue,		/* 0xD1D9 */
3429		 N_("Flash Command A Value")},
3430		{PTP_DPC_NIKON_FlashCommandBMode,		/* 0xD1DA */
3431		 N_("Flash Command B Mode")},
3432		{PTP_DPC_NIKON_FlashCommandBCompensation,	/* 0xD1DB */
3433		 N_("Flash Command B Compensation")},
3434		{PTP_DPC_NIKON_FlashCommandBValue,		/* 0xD1DC */
3435		 N_("Flash Command B Value")},
3436		{PTP_DPC_NIKON_ActivePicCtrlItem,		/* 0xD200 */
3437		 N_("Active Pic Ctrl Item")},
3438		{PTP_DPC_NIKON_ChangePicCtrlItem,		/* 0xD201 */
3439		 N_("Change Pic Ctrl Item")},
3440		{0,NULL}
3441	};
3442        struct {
3443		uint16_t dpc;
3444		const char *txt;
3445        } ptp_device_properties_MTP[] = {
3446		{PTP_DPC_MTP_SecureTime,        N_("Secure Time")},		/* D101 */
3447		{PTP_DPC_MTP_DeviceCertificate, N_("Device Certificate")},	/* D102 */
3448		{PTP_DPC_MTP_RevocationInfo,    N_("Revocation Info")},		/* D103 */
3449		{PTP_DPC_MTP_SynchronizationPartner,				/* D401 */
3450		 N_("Synchronization Partner")},
3451		{PTP_DPC_MTP_DeviceFriendlyName,				/* D402 */
3452		 N_("Friendly Device Name")},
3453		{PTP_DPC_MTP_VolumeLevel,       N_("Volume Level")},		/* D403 */
3454		{PTP_DPC_MTP_DeviceIcon,        N_("Device Icon")},		/* D405 */
3455		{PTP_DPC_MTP_SessionInitiatorInfo,	N_("Session Initiator Info")},/* D406 */
3456		{PTP_DPC_MTP_PerceivedDeviceType,	N_("Perceived Device Type")},/* D407 */
3457		{PTP_DPC_MTP_PlaybackRate,      N_("Playback Rate")},		/* D410 */
3458		{PTP_DPC_MTP_PlaybackObject,    N_("Playback Object")},		/* D411 */
3459		{PTP_DPC_MTP_PlaybackContainerIndex,				/* D412 */
3460		 N_("Playback Container Index")},
3461		{PTP_DPC_MTP_PlaybackPosition,  N_("Playback Position")},	/* D413 */
3462		{PTP_DPC_MTP_PlaysForSureID,    N_("PlaysForSure ID")},		/* D131 (?) */
3463		{0,NULL}
3464        };
3465
3466	for (i=0; ptp_device_properties[i].txt!=NULL; i++)
3467		if (ptp_device_properties[i].dpc==dpc)
3468			return (ptp_device_properties[i].txt);
3469
3470	if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_MICROSOFT
3471	    || params->deviceinfo.VendorExtensionID==PTP_VENDOR_MTP)
3472		for (i=0; ptp_device_properties_MTP[i].txt!=NULL; i++)
3473			if (ptp_device_properties_MTP[i].dpc==dpc)
3474				return (ptp_device_properties_MTP[i].txt);
3475
3476	if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_EASTMAN_KODAK)
3477		for (i=0; ptp_device_properties_EK[i].txt!=NULL; i++)
3478			if (ptp_device_properties_EK[i].dpc==dpc)
3479				return (ptp_device_properties_EK[i].txt);
3480
3481	if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_CANON)
3482		for (i=0; ptp_device_properties_Canon[i].txt!=NULL; i++)
3483			if (ptp_device_properties_Canon[i].dpc==dpc)
3484				return (ptp_device_properties_Canon[i].txt);
3485
3486	if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_NIKON)
3487		for (i=0; ptp_device_properties_Nikon[i].txt!=NULL; i++)
3488			if (ptp_device_properties_Nikon[i].dpc==dpc)
3489				return (ptp_device_properties_Nikon[i].txt);
3490
3491	return NULL;
3492}
3493
3494static int64_t
3495_value_to_num(PTPPropertyValue *data, uint16_t dt) {
3496	if (dt == PTP_DTC_STR) {
3497		if (!data->str)
3498			return 0;
3499		return atol(data->str);
3500	}
3501	if (dt & PTP_DTC_ARRAY_MASK) {
3502		return 0;
3503	} else {
3504		switch (dt) {
3505		case PTP_DTC_UNDEF:
3506			return 0;
3507		case PTP_DTC_INT8:
3508			return data->i8;
3509		case PTP_DTC_UINT8:
3510			return data->u8;
3511		case PTP_DTC_INT16:
3512			return data->i16;
3513		case PTP_DTC_UINT16:
3514			return data->u16;
3515		case PTP_DTC_INT32:
3516			return data->i32;
3517		case PTP_DTC_UINT32:
3518			return data->u32;
3519	/*
3520		PTP_DTC_INT64
3521		PTP_DTC_UINT64
3522		PTP_DTC_INT128
3523		PTP_DTC_UINT128
3524	*/
3525		default:
3526			return 0;
3527		}
3528	}
3529
3530	return 0;
3531}
3532
3533#define PTP_VAL_BOOL(dpc) {dpc, 0, N_("Off")}, {dpc, 1, N_("On")}
3534#define PTP_VENDOR_VAL_BOOL(dpc,vendor) {dpc, vendor, 0, N_("Off")}, {dpc, vendor, 1, N_("On")}
3535#define PTP_VENDOR_VAL_RBOOL(dpc,vendor) {dpc, vendor, 0, N_("On")}, {dpc, vendor, 1, N_("Off")}
3536#define PTP_VENDOR_VAL_YN(dpc,vendor) {dpc, vendor, 0, N_("No")}, {dpc, vendor, 1, N_("Yes")}
3537
3538int
3539ptp_render_property_value(PTPParams* params, uint16_t dpc,
3540			  PTPDevicePropDesc *dpd, int length, char *out)
3541{
3542	int i;
3543	int64_t	kval;
3544
3545	struct {
3546		uint16_t dpc;
3547		uint16_t vendor;
3548		double coef;
3549		double bias;
3550		const char *format;
3551	} ptp_value_trans[] = {
3552		{PTP_DPC_BatteryLevel, 0, 1.0, 0.0, "%.0f%%"},		/* 5001 */
3553		{PTP_DPC_FNumber, 0, 0.01, 0.0, "f/%.2g"},		/* 5007 */
3554		{PTP_DPC_FocalLength, 0, 0.01, 0.0, "%.0f mm"},		/* 5008 */
3555		{PTP_DPC_FocusDistance, 0, 0.01, 0.0, "%.0f mm"},	/* 5009 */
3556		{PTP_DPC_ExposureTime, 0, 0.00001, 0.0, "%.2g sec"},	/* 500D */
3557		{PTP_DPC_ExposureIndex, 0, 1.0, 0.0, "ISO %.0f"},	/* 500F */
3558		{PTP_DPC_ExposureBiasCompensation, 0, 0.001, 0.0, N_("%.1f stops")},/* 5010 */
3559		{PTP_DPC_DigitalZoom, 0, 0.1, 0.0, "%.1f"},		/* 5016 */
3560
3561		/* Nikon device properties */
3562		{PTP_DPC_NIKON_LightMeter, PTP_VENDOR_NIKON, 0.08333, 0.0, N_("%.1f stops")},/* D10A */
3563		{PTP_DPC_NIKON_FlashExposureCompensation, PTP_VENDOR_NIKON, 0.16666, 0.0, N_("%.1f stops")}, /* D126 */
3564		{PTP_DPC_NIKON_CenterWeightArea, PTP_VENDOR_NIKON, 2.0, 6.0, N_("%.0f mm")},/* D059 */
3565		{PTP_DPC_NIKON_FocalLengthMin, PTP_VENDOR_NIKON, 0.01, 0.0, "%.0f mm"}, /* D0E3 */
3566		{PTP_DPC_NIKON_FocalLengthMax, PTP_VENDOR_NIKON, 0.01, 0.0, "%.0f mm"}, /* D0E4 */
3567		{PTP_DPC_NIKON_MaxApAtMinFocalLength, PTP_VENDOR_NIKON, 0.01, 0.0, "f/%.2g"}, /* D0E5 */
3568		{PTP_DPC_NIKON_MaxApAtMaxFocalLength, PTP_VENDOR_NIKON, 0.01, 0.0, "f/%.2g"}, /* D0E6 */
3569		{PTP_DPC_NIKON_ExternalFlashCompensation, PTP_VENDOR_NIKON, 1.0/6.0, 0.0,"%.0f"}, /* D124 */
3570		{PTP_DPC_NIKON_ExposureIndicateStatus, PTP_VENDOR_NIKON, 0.08333, 0.0, N_("%.1f stops")},/* D1B1 - FIXME: check if correct. */
3571		{0, 0, 0.0, 0.0, NULL}
3572	};
3573
3574	struct {
3575		uint16_t dpc;
3576		uint16_t vendor;
3577		int64_t key;
3578		char *value;
3579	} ptp_value_list[] = {
3580		{PTP_DPC_CompressionSetting, 0, 0, N_("JPEG Basic")},	/* 5004 */
3581		{PTP_DPC_CompressionSetting, 0, 1, N_("JPEG Norm")},
3582		{PTP_DPC_CompressionSetting, 0, 2, N_("JPEG Fine")},
3583		{PTP_DPC_CompressionSetting, 0, 4, N_("RAW")},
3584		{PTP_DPC_CompressionSetting, 0, 5, N_("RAW + JPEG Basic")},
3585		{PTP_DPC_WhiteBalance, 0, 1, N_("Manual")},
3586		{PTP_DPC_WhiteBalance, 0, 2, N_("Automatic")},		/* 5005 */
3587		{PTP_DPC_WhiteBalance, 0, 3, N_("One-push Automatic")},
3588		{PTP_DPC_WhiteBalance, 0, 4, N_("Daylight")},
3589		{PTP_DPC_WhiteBalance, 0, 5, N_("Fluorescent")},
3590		{PTP_DPC_WhiteBalance, 0, 6, N_("Incandescent")},
3591		{PTP_DPC_WhiteBalance, 0, 7, N_("Flash")},
3592		{PTP_DPC_WhiteBalance, PTP_VENDOR_NIKON, 32784, N_("Cloudy")},
3593		{PTP_DPC_WhiteBalance, PTP_VENDOR_NIKON, 32785, N_("Shade")},
3594		{PTP_DPC_WhiteBalance, PTP_VENDOR_NIKON, 32786, N_("Color Temperature")},
3595		{PTP_DPC_WhiteBalance, PTP_VENDOR_NIKON, 32787, N_("Preset")},
3596		{PTP_DPC_FocusMode, 0, 1, N_("Manual Focus")},		/* 500A */
3597		{PTP_DPC_FocusMode, 0, 2, N_("Automatic")},
3598		{PTP_DPC_FocusMode, 0, 3, N_("Automatic Macro (close-up)")},
3599		{PTP_DPC_FocusMode, PTP_VENDOR_NIKON, 32784, "AF-S"},
3600		{PTP_DPC_FocusMode, PTP_VENDOR_NIKON, 32785, "AF-C"},
3601		{PTP_DPC_FocusMode, PTP_VENDOR_NIKON, 32786, "AF-A"},
3602		{PTP_DPC_ExposureMeteringMode, 0, 1, N_("Average")},	/* 500B */
3603		{PTP_DPC_ExposureMeteringMode, 0, 2, N_("Center Weighted Average")},
3604		{PTP_DPC_ExposureMeteringMode, 0, 3, N_("Multi-spot")},
3605		{PTP_DPC_ExposureMeteringMode, 0, 4, N_("Center-spot")},
3606		{PTP_DPC_FlashMode, 0, 0, N_("Undefined")},		/* 500C */
3607		{PTP_DPC_FlashMode, 0, 1, N_("Automatic flash")},
3608		{PTP_DPC_FlashMode, 0, 2, N_("Flash off")},
3609		{PTP_DPC_FlashMode, 0, 3, N_("Fill flash")},
3610		{PTP_DPC_FlashMode, 0, 4, N_("Automatic Red-eye Reduction")},
3611		{PTP_DPC_FlashMode, 0, 5, N_("Red-eye fill flash")},
3612		{PTP_DPC_FlashMode, 0, 6, N_("External sync")},
3613		{PTP_DPC_FlashMode, PTP_VENDOR_NIKON, 32784, N_("Default")},
3614		{PTP_DPC_FlashMode, PTP_VENDOR_NIKON, 32785, N_("Slow Sync")},
3615		{PTP_DPC_FlashMode, PTP_VENDOR_NIKON, 32786, N_("Rear Curtain Sync + Slow Sync")},
3616		{PTP_DPC_FlashMode, PTP_VENDOR_NIKON, 32787, N_("Red-eye Reduction + Slow Sync")},
3617		{PTP_DPC_ExposureProgramMode, 0, 1, "M"},		/* 500E */
3618		{PTP_DPC_ExposureProgramMode, 0, 3, "A"},
3619		{PTP_DPC_ExposureProgramMode, 0, 4, "S"},
3620		{PTP_DPC_ExposureProgramMode, 0, 2, "P"},
3621		{PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32784, N_("Auto")},
3622		{PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32785, N_("Portrait")},
3623		{PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32786, N_("Landscape")},
3624		{PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32787, N_("Macro")},
3625		{PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32788, N_("Sports")},
3626		{PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32790, N_("Night Landscape")},
3627		{PTP_DPC_ExposureProgramMode, PTP_VENDOR_NIKON, 32789, N_("Night Portrait")},
3628		{PTP_DPC_StillCaptureMode, 0, 1, N_("Single Shot")},	/* 5013 */
3629		{PTP_DPC_StillCaptureMode, 0, 2, N_("Power Wind")},
3630		{PTP_DPC_StillCaptureMode, 0, 3, N_("Timelapse")},
3631		{PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32784, N_("Continuous Low Speed")},
3632		{PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32785, N_("Timer")},
3633		{PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32787, N_("Remote")},
3634		{PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32787, N_("Mirror Up")},
3635		{PTP_DPC_StillCaptureMode, PTP_VENDOR_NIKON, 32788, N_("Timer + Remote")},
3636		{PTP_DPC_FocusMeteringMode, 0, 1, N_("Centre-spot")},	/* 501C */
3637		{PTP_DPC_FocusMeteringMode, 0, 2, N_("Multi-spot")},
3638		{PTP_DPC_FocusMeteringMode, PTP_VENDOR_NIKON, 32784, N_("Single Area")},
3639		{PTP_DPC_FocusMeteringMode, PTP_VENDOR_NIKON, 32785, N_("Closest Subject")},
3640		{PTP_DPC_FocusMeteringMode, PTP_VENDOR_NIKON, 32786, N_("Group Dynamic")},
3641
3642
3643		/* Nikon specific device properties */
3644		{PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 0, N_("Auto")},	/* D02A */
3645		{PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 1, N_("Normal")},
3646		{PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 2, N_("Low")},
3647		{PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 3, N_("Medium Low")},
3648		{PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 4, N_("Medium high")},
3649		{PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 5, N_("High")},
3650		{PTP_DPC_NIKON_ImageSharpening, PTP_VENDOR_NIKON, 6, N_("None")},
3651
3652		{PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 0, N_("Auto")},	/* D02B */
3653		{PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 1, N_("Normal")},
3654		{PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 2, N_("Low contrast")},
3655		{PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 3, N_("Medium Low")},
3656		{PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 4, N_("Medium High")},
3657		{PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 5, N_("High control")},
3658		{PTP_DPC_NIKON_ToneCompensation, PTP_VENDOR_NIKON, 6, N_("Custom")},
3659
3660		{PTP_DPC_NIKON_ColorModel, PTP_VENDOR_NIKON, 0, "sRGB"},		/* D02C */
3661		{PTP_DPC_NIKON_ColorModel, PTP_VENDOR_NIKON, 1, "AdobeRGB"},
3662		{PTP_DPC_NIKON_ColorModel, PTP_VENDOR_NIKON, 2, "sRGB"},
3663
3664		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_AutoDXCrop,PTP_VENDOR_NIKON),	   	/* D033 */
3665
3666		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_FocusAreaWrap,PTP_VENDOR_NIKON),   	/* D04F */
3667
3668		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_EnableCopyright,PTP_VENDOR_NIKON),   	/* D053 */
3669		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_ISOAuto,PTP_VENDOR_NIKON),	   	/* D054 */
3670
3671		/* FIXME! this is not ISO Auto (which is a bool) Perhaps ISO Auto Time?*/
3672		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 0, "1/125"},			/* D054 */
3673		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 1, "1/60"},
3674		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 2, "1/30"},
3675		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 3, "1/15"},
3676		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 4, "1/8"},
3677		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 5, "1/4"},
3678		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 6, "1/2"},
3679		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 7, "1"},
3680		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 8, "2"},
3681		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 9, "4"},
3682		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 10, "8"},
3683		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 11, "15"},
3684		{PTP_DPC_NIKON_ISOAuto,	PTP_VENDOR_NIKON, 12, "30"},
3685
3686		{PTP_DPC_NIKON_EVStep, PTP_VENDOR_NIKON, 0, "1/3"},			/* D056 */
3687		{PTP_DPC_NIKON_EVStep, PTP_VENDOR_NIKON, 1, "1/2"},
3688
3689		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_ExposureCompensation,PTP_VENDOR_NIKON),/*D058 */
3690		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_AELockMode,PTP_VENDOR_NIKON),    	/* D05E */
3691
3692		{PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 0, N_("AE/AF Lock")},	/* D05F */
3693		{PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 1, N_("AF Lock only")},
3694		{PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 2, N_("AE Lock only")},
3695		{PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 3, N_("AF Lock Hold")},
3696		{PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 4, N_("AF On")},
3697		{PTP_DPC_NIKON_AELAFLMode, PTP_VENDOR_NIKON, 5, N_("Flash Lock")},
3698
3699		{PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 0, N_("4 seconds")},		/* D062 */
3700		{PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 1, N_("6 seconds")},
3701		{PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 2, N_("8 seconds")},
3702		{PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 3, N_("16 seconds")},
3703		{PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 4, N_("30 minutes")},
3704		{PTP_DPC_NIKON_MeterOff, PTP_VENDOR_NIKON, 5, N_("30 seconds")},
3705
3706		{PTP_DPC_NIKON_SelfTimer, PTP_VENDOR_NIKON, 0, N_("2 seconds")},	/* D063 */
3707		{PTP_DPC_NIKON_SelfTimer, PTP_VENDOR_NIKON, 1, N_("5 seconds")},
3708		{PTP_DPC_NIKON_SelfTimer, PTP_VENDOR_NIKON, 2, N_("10 seconds")},
3709		{PTP_DPC_NIKON_SelfTimer, PTP_VENDOR_NIKON, 3, N_("20 seconds")},
3710
3711		{PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 0, N_("10 seconds")},	/* D064 */
3712		{PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 1, N_("20 seconds")},
3713		{PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 2, N_("1 minute")},
3714		{PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 3, N_("5 minutes")},
3715		{PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 4, N_("10 minutes")},
3716		{PTP_DPC_NIKON_MonitorOff, PTP_VENDOR_NIKON, 5, N_("5 seconds")}, /* d80 observed */
3717
3718		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_D3ExpDelayMode,PTP_VENDOR_NIKON),	/* D06A */
3719		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_LongExposureNoiseReduction,PTP_VENDOR_NIKON),	/* D06B */
3720		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_FileNumberSequence,PTP_VENDOR_NIKON),	/* D06C */
3721		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_D7Illumination,PTP_VENDOR_NIKON),	/* D06F */
3722
3723		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_SHSET_CH_GUID_DISP,PTP_VENDOR_NIKON),	/* D071 */
3724
3725		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 0, "1/60s"},		/* D075 */
3726		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 1, "1/30s"},
3727		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 2, "1/15s"},
3728		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 3, "1/8s"},
3729		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 4, "1/4s"},
3730		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 5, "1/2s"},
3731		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 6, "1s"},
3732		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 7, "2s"},
3733		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 8, "4s"},
3734		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 9, "8s"},
3735		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 10, "15s"},
3736		{PTP_DPC_NIKON_FlashShutterSpeed, PTP_VENDOR_NIKON, 11, "30s"},
3737
3738		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_E4ModelingFlash,PTP_VENDOR_NIKON),	/* D077 */
3739
3740		{PTP_DPC_NIKON_BracketSet, PTP_VENDOR_NIKON, 0, N_("AE & Flash")},	/* D078 */
3741		{PTP_DPC_NIKON_BracketSet, PTP_VENDOR_NIKON, 1, N_("AE only")},
3742		{PTP_DPC_NIKON_BracketSet, PTP_VENDOR_NIKON, 2, N_("Flash only")},
3743		{PTP_DPC_NIKON_BracketSet, PTP_VENDOR_NIKON, 3, N_("WB bracketing")},
3744
3745		{PTP_DPC_NIKON_BracketOrder, PTP_VENDOR_NIKON, 0, N_("MTR > Under")},	/* D07A */
3746		{PTP_DPC_NIKON_BracketOrder, PTP_VENDOR_NIKON, 1, N_("Under > MTR")},
3747
3748		{PTP_DPC_NIKON_F1CenterButtonShootingMode, PTP_VENDOR_NIKON, 0, N_("Reset focus point to center")}, /* D080 */
3749		{PTP_DPC_NIKON_F1CenterButtonShootingMode, PTP_VENDOR_NIKON, 1, N_("Highlight active focus point")},
3750		{PTP_DPC_NIKON_F1CenterButtonShootingMode, PTP_VENDOR_NIKON, 2, N_("Unused")},
3751
3752		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_F3PhotoInfoPlayback,PTP_VENDOR_NIKON),/* D083 */
3753		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_F5CustomizeCommDials,PTP_VENDOR_NIKON),/* D085 */
3754		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_ReverseCommandDial,PTP_VENDOR_NIKON),	/* D086 */
3755		PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_F6ButtonsAndDials,PTP_VENDOR_NIKON),	/* D089 */
3756		PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_NoCFCard,PTP_VENDOR_NIKON),		/* D08A */
3757		PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_AFAreaPoint,PTP_VENDOR_NIKON),	/* D08D */
3758
3759		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_ImageCommentEnable,PTP_VENDOR_NIKON),	/* D091 */
3760		PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_ImageRotation,PTP_VENDOR_NIKON),	/* D092 */
3761
3762		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_MovVoice,PTP_VENDOR_NIKON),		/* D0A1 */
3763
3764		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_Bracketing,PTP_VENDOR_NIKON),		/* D0C0 */
3765
3766		{PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 0, N_("Unknown")},		/* D0E0 */
3767		{PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 38, "Sigma 70-300mm 1:4-5.6 D APO Macro"},
3768		{PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 83, "AF Nikkor 80-200mm 1:2.8 D ED"},
3769		{PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 118, "AF Nikkor 50mm 1:1.8 D"},
3770		{PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 127, "AF-S Nikkor 18-70mm 1:3.5-4.5G ED DX"},
3771		{PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 139, "AF-S Nikkor 18-200mm 1:3.5-5.6 GED DX VR"},
3772		{PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 147, "AF-S Nikkor 24-70mm 1:2.8G ED DX"},
3773		{PTP_DPC_NIKON_LensID, PTP_VENDOR_NIKON, 154, "AF-S Nikkor 18-55mm 1:3.5-F5.6G DX VR"},
3774		{PTP_DPC_NIKON_FinderISODisp, PTP_VENDOR_NIKON, 0, "Show ISO sensitivity"},/* 0xD0F0 */
3775		{PTP_DPC_NIKON_FinderISODisp, PTP_VENDOR_NIKON, 1, "Show ISO/Easy ISO"},
3776		{PTP_DPC_NIKON_FinderISODisp, PTP_VENDOR_NIKON, 2, "Show frame count"},
3777
3778		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ACPower,PTP_VENDOR_NIKON),		/* D101 */
3779		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_AFLockStatus,PTP_VENDOR_NIKON),		/* D104 */
3780		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_AELockStatus,PTP_VENDOR_NIKON),		/* D105 */
3781		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_FVLockStatus,PTP_VENDOR_NIKON),		/* D106 */
3782
3783		{PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 0, N_("Centre")},	/* D108 */
3784		{PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 1, N_("Top")},
3785		{PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 2, N_("Bottom")},
3786		{PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 3, N_("Left")},
3787		{PTP_DPC_NIKON_AutofocusArea, PTP_VENDOR_NIKON, 4, N_("Right")},
3788
3789		{PTP_DPC_NIKON_RecordingMedia, PTP_VENDOR_NIKON, 0, N_("Card")},	/* D10B */
3790		{PTP_DPC_NIKON_RecordingMedia, PTP_VENDOR_NIKON, 1, N_("SDRam")},
3791
3792		{PTP_DPC_NIKON_USBSpeed, PTP_VENDOR_NIKON, 0, N_("USB 1.1")},		/* D10C */
3793		{PTP_DPC_NIKON_USBSpeed, PTP_VENDOR_NIKON, 1, N_("USB 2.0")},
3794
3795		{PTP_DPC_NIKON_CameraOrientation, PTP_VENDOR_NIKON, 0, "0'"},		/* D10E */
3796		{PTP_DPC_NIKON_CameraOrientation, PTP_VENDOR_NIKON, 1, "270'"},
3797		{PTP_DPC_NIKON_CameraOrientation, PTP_VENDOR_NIKON, 2, "90'"},
3798		{PTP_DPC_NIKON_CameraOrientation, PTP_VENDOR_NIKON, 3, "180'"},
3799
3800		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_FNumberLock,PTP_VENDOR_NIKON),		/* D110 */
3801		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExposureApertureLock,PTP_VENDOR_NIKON),	/* D111 */
3802		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_TVLockSetting,PTP_VENDOR_NIKON),	/* D112 */
3803		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_AVLockSetting,PTP_VENDOR_NIKON),	/* D113 */
3804
3805		{PTP_DPC_NIKON_IllumSetting,PTP_VENDOR_NIKON,0,N_("LCD Backlight")},	/* D114 */
3806		{PTP_DPC_NIKON_IllumSetting,PTP_VENDOR_NIKON,1,N_("LCD Backlight and Info Display")},
3807
3808		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExternalFlashAttached,PTP_VENDOR_NIKON),/* D120 */
3809		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExternalFlashStatus,PTP_VENDOR_NIKON),	/* D121 */
3810
3811		{PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 0, N_("Normal")},	/* D140 */
3812		{PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 1, N_("Vivid")},
3813		{PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 2, N_("Sharper")},
3814		{PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 3, N_("Softer")},
3815		{PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 4, N_("Direct Print")},
3816		{PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 5, N_("Portrait")},
3817		{PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 6, N_("Landscape")},
3818		{PTP_DPC_NIKON_OptimizeImage, PTP_VENDOR_NIKON, 7, N_("Custom")},
3819
3820		{PTP_DPC_NIKON_Saturation, PTP_VENDOR_NIKON, 0, N_("Normal")},		/* D142 */
3821		{PTP_DPC_NIKON_Saturation, PTP_VENDOR_NIKON, 1, N_("Moderate")},
3822		{PTP_DPC_NIKON_Saturation, PTP_VENDOR_NIKON, 2, N_("Enhanced")},
3823
3824		PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_BeepOff,PTP_VENDOR_NIKON),		/* D160 */
3825
3826		{PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 0, N_("AF-S")},	 	/* D161 */
3827		{PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 1, N_("AF-C")},
3828		{PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 2, N_("AF-A")},
3829		{PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 3, N_("MF (fixed)")},
3830		{PTP_DPC_NIKON_AutofocusMode, PTP_VENDOR_NIKON, 4, N_("MF (selection)")},
3831
3832		PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_AFAssist,PTP_VENDOR_NIKON),   	/* D163 */
3833
3834		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 0,  "1/125"},		/* D164 */
3835		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 1,  "1/60"},
3836		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 2,  "1/30"},
3837		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 3,  "1/15"},
3838		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 4,  "1/8"},
3839		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 5,  "1/4"},
3840		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 6,  "1/2"},
3841		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 7,  "1"},
3842		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 8,  "2"},
3843		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 9,  "4"},
3844		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 10, "8"},
3845		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 11, "15"},
3846		{PTP_DPC_NIKON_PADVPMode, PTP_VENDOR_NIKON, 12, "30"},
3847
3848		PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_ImageReview,PTP_VENDOR_NIKON),	/* D165 */
3849
3850		{PTP_DPC_NIKON_AFAreaIllumination, PTP_VENDOR_NIKON, 0, N_("Auto")},	/* D166 */
3851		{PTP_DPC_NIKON_AFAreaIllumination, PTP_VENDOR_NIKON, 1, N_("Off")},
3852		{PTP_DPC_NIKON_AFAreaIllumination, PTP_VENDOR_NIKON, 2, N_("On")},
3853
3854		{PTP_DPC_NIKON_FlashMode, PTP_VENDOR_NIKON, 0, "iTTL"},			/* D167 */
3855		{PTP_DPC_NIKON_FlashMode, PTP_VENDOR_NIKON, 1, N_("Manual")},
3856		{PTP_DPC_NIKON_FlashMode, PTP_VENDOR_NIKON, 2, N_("Commander")},
3857
3858		{PTP_DPC_NIKON_FlashCommanderMode, PTP_VENDOR_NIKON, 0, N_("TTL")},	/* D168 */
3859		{PTP_DPC_NIKON_FlashCommanderMode, PTP_VENDOR_NIKON, 1, N_("Auto Aperture")},
3860		{PTP_DPC_NIKON_FlashCommanderMode, PTP_VENDOR_NIKON, 2, N_("Full Manual")},
3861
3862		PTP_VENDOR_VAL_RBOOL(PTP_DPC_NIKON_FlashSign,PTP_VENDOR_NIKON),		/* D169 */
3863
3864		{PTP_DPC_NIKON_RemoteTimeout, PTP_VENDOR_NIKON, 0, N_("1 min")},	/* D16B */
3865		{PTP_DPC_NIKON_RemoteTimeout, PTP_VENDOR_NIKON, 1, N_("5 mins")},
3866		{PTP_DPC_NIKON_RemoteTimeout, PTP_VENDOR_NIKON, 2, N_("10 mins")},
3867		{PTP_DPC_NIKON_RemoteTimeout, PTP_VENDOR_NIKON, 3, N_("15 mins")},
3868
3869		PTP_VENDOR_VAL_BOOL(PTP_DPC_NIKON_GridDisplay,PTP_VENDOR_NIKON),	/* D16C */
3870
3871		{PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 0, N_("Full")},	/* D16D */
3872		{PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 1, "1/2"},
3873		{PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 2, "1/4"},
3874		{PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 3, "1/8"},
3875		{PTP_DPC_NIKON_FlashModeManualPower, PTP_VENDOR_NIKON, 4, "1/16"},
3876
3877		{PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 0, N_("Full")},/* D16E */
3878		{PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 1, "1/2"},
3879		{PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 2, "1/4"},
3880		{PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 3, "1/8"},
3881		{PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 4, "1/16"},
3882		{PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 5, "1/32"},
3883		{PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 6, "1/64"},
3884		{PTP_DPC_NIKON_FlashModeCommanderPower, PTP_VENDOR_NIKON, 7, "1/128"},
3885
3886		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_CSMMenu,PTP_VENDOR_NIKON),		/* D180 */
3887		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_WarningDisplay,PTP_VENDOR_NIKON),	/* D181 */
3888
3889		{PTP_DPC_NIKON_BatteryCellKind, PTP_VENDOR_NIKON, 0, "LR6 (AA alkaline)"},/* D182 */
3890		{PTP_DPC_NIKON_BatteryCellKind, PTP_VENDOR_NIKON, 1, "HR6 (AA Ni-Mh)"},
3891		{PTP_DPC_NIKON_BatteryCellKind, PTP_VENDOR_NIKON, 2, "FR6 (AA Lithium)"},
3892		{PTP_DPC_NIKON_BatteryCellKind, PTP_VENDOR_NIKON, 3, "ZR6 (AA Ni-Mn)"},
3893
3894		{PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 0, "400"},		/* D183 */
3895		{PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 1, "800"},
3896		{PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 2, "1600"},
3897		{PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 3, "3200"},
3898		{PTP_DPC_NIKON_ISOAutoHiLimit, PTP_VENDOR_NIKON, 4, "Hi 1"},
3899
3900		{PTP_DPC_NIKON_InfoDispSetting, PTP_VENDOR_NIKON, 0, N_("Auto")},	/* 0xD187 */
3901		{PTP_DPC_NIKON_InfoDispSetting, PTP_VENDOR_NIKON, 1, N_("Dark on light")},
3902		{PTP_DPC_NIKON_InfoDispSetting, PTP_VENDOR_NIKON, 2, N_("Light on dark")},
3903
3904		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_IndicatorDisp,PTP_VENDOR_NIKON),	/* D18D */
3905
3906		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_LiveViewStatus,PTP_VENDOR_NIKON),	/* D1A2 */
3907
3908		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExposureDisplayStatus,PTP_VENDOR_NIKON),/* D1B0 */
3909		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_InfoDispErrStatus,PTP_VENDOR_NIKON),	/* D1B2 */
3910		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_ExposureIndicateLightup,PTP_VENDOR_NIKON),/* D1B3 */
3911
3912		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_FlashOpen,PTP_VENDOR_NIKON),		/* D1C0 */
3913		PTP_VENDOR_VAL_YN(PTP_DPC_NIKON_FlashCharged,PTP_VENDOR_NIKON),		/* D1C1 */
3914
3915		/* Canon stuff */
3916		PTP_VENDOR_VAL_BOOL(PTP_DPC_CANON_AssistLight,PTP_VENDOR_CANON),
3917		PTP_VENDOR_VAL_RBOOL(PTP_DPC_CANON_RotationScene,PTP_VENDOR_CANON),
3918		PTP_VENDOR_VAL_RBOOL(PTP_DPC_CANON_BeepMode,PTP_VENDOR_CANON),
3919		PTP_VENDOR_VAL_BOOL(PTP_DPC_CANON_Beep,PTP_VENDOR_CANON),
3920
3921		{PTP_DPC_CANON_RotationAngle, PTP_VENDOR_CANON, 0, "0'"},
3922		{PTP_DPC_CANON_RotationAngle, PTP_VENDOR_CANON, 3, "270'"},
3923		{PTP_DPC_CANON_RotationAngle, PTP_VENDOR_CANON, 1, "90'"},
3924
3925		{PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 0, N_("Unknown")},
3926		{PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 1, N_("AC")},
3927		{PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 2, N_("Lithium Ion")},
3928		{PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 3, N_("Nickel hydride")},
3929		{PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 4, N_("Nickel cadmium")},
3930		{PTP_DPC_CANON_BatteryKind, PTP_VENDOR_CANON, 5, N_("Alkalium manganese")},
3931
3932		{PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 0, N_("Undefined")},
3933		{PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 1, N_("Normal")},
3934		{PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 2, N_("Warning Level 1")},
3935		{PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 3, N_("Emergency")},
3936		{PTP_DPC_CANON_BatteryStatus, PTP_VENDOR_CANON, 4, N_("Warning Level 0")},
3937
3938		{PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 0, N_("Undefined")},
3939		{PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 1, N_("Economy")},
3940		{PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 2, N_("Normal")},
3941		{PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 3, N_("Fine")},
3942		{PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 4, N_("Lossless")},
3943		{PTP_DPC_CANON_ImageQuality, PTP_VENDOR_CANON, 5, N_("SuperFine")},
3944
3945		{PTP_DPC_CANON_FullViewFileFormat, PTP_VENDOR_CANON, 0, N_("Undefined")},
3946		{PTP_DPC_CANON_FullViewFileFormat, PTP_VENDOR_CANON, 1, N_("JPEG")},
3947		{PTP_DPC_CANON_FullViewFileFormat, PTP_VENDOR_CANON, 2, N_("CRW")},
3948
3949		{PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 0, N_("Large")},
3950		{PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 1, N_("Medium 1")},
3951		{PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 2, N_("Small")},
3952		{PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 3, N_("Medium 2")},
3953		{PTP_DPC_CANON_ImageSize, PTP_VENDOR_CANON, 7, N_("Medium 3")},
3954
3955		{PTP_DPC_CANON_SelfTime, PTP_VENDOR_CANON, 0,   N_("Not used")},
3956		{PTP_DPC_CANON_SelfTime, PTP_VENDOR_CANON, 100, N_("10 seconds")},
3957		{PTP_DPC_CANON_SelfTime, PTP_VENDOR_CANON, 20,  N_("2 seconds")},
3958
3959		{PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 0,  N_("Off")},
3960		{PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 1,  N_("Auto")},
3961		{PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 2,  N_("On")},
3962		{PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 3,  N_("Red Eye Suppression")},
3963		{PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 4,  N_("Low Speed Synchronization")},
3964		{PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 5,  N_("Auto + Red Eye Suppression")},
3965		{PTP_DPC_CANON_FlashMode, PTP_VENDOR_CANON, 6,  N_("On + Red Eye Suppression")},
3966
3967		{PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 0,  N_("Auto")},
3968		{PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 1,  N_("P")},
3969		{PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 2,  N_("Tv")},
3970		{PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 3,  N_("Av")},
3971		{PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 4,  N_("M")},
3972		{PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 5,  N_("A_DEP")},
3973		{PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 6,  N_("M_DEP")},
3974		{PTP_DPC_CANON_ShootingMode, PTP_VENDOR_CANON, 7,  N_("Bulb")},
3975		/* more actually */
3976
3977		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 0,  N_("Auto")},
3978		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 1,  N_("Manual")},
3979		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 2,  N_("Distant View")},
3980		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 3,  N_("High-Speed Shutter")},
3981		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 4,  N_("Low-Speed Shutter")},
3982		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 5,  N_("Night View")},
3983		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 6,  N_("Grayscale")},
3984		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 7,  N_("Sepia")},
3985		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 8,  N_("Portrait")},
3986		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 9,  N_("Sports")},
3987		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 10,  N_("Macro")},
3988		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 11,  N_("Monochrome")},
3989		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 12,  N_("Pan Focus")},
3990		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 13,  N_("Neutral")},
3991		{PTP_DPC_CANON_ImageMode, PTP_VENDOR_CANON, 14,  N_("Soft")},
3992
3993		{PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 0,  N_("Single-Frame Shooting")},
3994		{PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 1,  N_("Continuous Shooting")},
3995		{PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 2,  N_("Timer (Single) Shooting")},
3996		{PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 4,  N_("Continuous Low-speed Shooting")},
3997		{PTP_DPC_CANON_DriveMode, PTP_VENDOR_CANON, 5,  N_("Continuous High-speed Shooting")},
3998
3999		{PTP_DPC_CANON_EZoom, PTP_VENDOR_CANON, 0,  N_("Off")},
4000		{PTP_DPC_CANON_EZoom, PTP_VENDOR_CANON, 1,  N_("2x")},
4001		{PTP_DPC_CANON_EZoom, PTP_VENDOR_CANON, 2,  N_("4x")},
4002		{PTP_DPC_CANON_EZoom, PTP_VENDOR_CANON, 3,  N_("Smooth")},
4003
4004		{PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 0,  N_("Center-weighted Metering")},
4005		{PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 1,  N_("Spot Metering")},
4006		{PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 2,  N_("Average Metering")},
4007		{PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 3,  N_("Evaluative Metering")},
4008		{PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 4,  N_("Partial Metering")},
4009		{PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 5,  N_("Center-weighted Average Metering")},
4010		{PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 6,  N_("Spot Metering Interlocked with AF Frame")},
4011		{PTP_DPC_CANON_MeteringMode, PTP_VENDOR_CANON, 7,  N_("Multi-Spot Metering")},
4012
4013		{PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 0,  N_("Manual")},
4014		{PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 1,  N_("Auto")},
4015		{PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 2,  N_("Unknown")},
4016		{PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 3,  N_("Zone Focus (Close-up)")},
4017		{PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 4,  N_("Zone Focus (Very Close)")},
4018		{PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 5,  N_("Zone Focus (Close)")},
4019		{PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 6,  N_("Zone Focus (Medium)")},
4020		{PTP_DPC_CANON_AFDistance, PTP_VENDOR_CANON, 7,  N_("Zone Focus (Far)")},
4021
4022		{PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0,  N_("Invalid")},
4023		{PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x1000,  N_("Focusing Point on Center Only, Manual")},
4024		{PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x1001,  N_("Focusing Point on Center Only, Auto")},
4025		{PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3000,  N_("Multiple Focusing Points (No Specification), Manual")},
4026		{PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3001,  N_("Multiple Focusing Points, Auto")},
4027		{PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3002,  N_("Multiple Focusing Points (Right)")},
4028		{PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3003,  N_("Multiple Focusing Points (Center)")},
4029		{PTP_DPC_CANON_FocusingPoint, PTP_VENDOR_CANON, 0x3004,  N_("Multiple Focusing Points (Left)")},
4030
4031		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 0,  N_("Auto")},
4032		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 1,  N_("Daylight")},
4033		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 2,  N_("Cloudy")},
4034		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 3,  N_("Tungsten")},
4035		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 4,  N_("Fluorescent")},
4036		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 6,  N_("Preset")},
4037		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 7,  N_("Fluorescent H")},
4038		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 9,  N_("Color Temperature")},
4039		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 10,  N_("Custom Whitebalance PC-1")},
4040		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 11,  N_("Custom Whitebalance PC-2")},
4041		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 12,  N_("Custom Whitebalance PC-3")},
4042		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 13,  N_("Missing Number")},
4043		{PTP_DPC_CANON_WhiteBalance, PTP_VENDOR_CANON, 14,  N_("Fluorescent H")}, /* dup? */
4044
4045		{PTP_DPC_CANON_SlowShutterSetting, PTP_VENDOR_CANON, 0,  N_("Off")},
4046		{PTP_DPC_CANON_SlowShutterSetting, PTP_VENDOR_CANON, 1,  N_("Night View")},
4047		{PTP_DPC_CANON_SlowShutterSetting, PTP_VENDOR_CANON, 2,  N_("On")},
4048		{PTP_DPC_CANON_SlowShutterSetting, PTP_VENDOR_CANON, 3,  N_("Low-speed shutter function not available")},
4049
4050		{PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 0,  N_("Single Shot")},
4051		{PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 1,  N_("AI Servo")},
4052		{PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 2,  N_("AI Focus")},
4053		{PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 3,  N_("Manual")},
4054		{PTP_DPC_CANON_AFMode, PTP_VENDOR_CANON, 4,  N_("Continuous")},
4055
4056		PTP_VENDOR_VAL_BOOL(PTP_DPC_CANON_ImageStabilization,PTP_VENDOR_CANON),
4057
4058		{PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, -2,  N_("Low 2")},
4059		{PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, -1,  N_("Low")},
4060		{PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, 0,  N_("Standard")},
4061		{PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, 1,  N_("High")},
4062		{PTP_DPC_CANON_Contrast, PTP_VENDOR_CANON, 2,  N_("High 2")},
4063
4064		{PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, -2,  N_("Low 2")},
4065		{PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, -1,  N_("Low")},
4066		{PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, 0,  N_("Standard")},
4067		{PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, 1,  N_("High")},
4068		{PTP_DPC_CANON_ColorGain, PTP_VENDOR_CANON, 2,  N_("High 2")},
4069
4070		{PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, -2,  N_("Low 2")},
4071		{PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, -1,  N_("Low")},
4072		{PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, 0,  N_("Standard")},
4073		{PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, 1,  N_("High")},
4074		{PTP_DPC_CANON_Sharpness, PTP_VENDOR_CANON, 2,  N_("High 2")},
4075
4076		{PTP_DPC_CANON_Sensitivity, PTP_VENDOR_CANON, 0,  N_("Standard")},
4077		{PTP_DPC_CANON_Sensitivity, PTP_VENDOR_CANON, 1,  N_("Upper 1")},
4078		{PTP_DPC_CANON_Sensitivity, PTP_VENDOR_CANON, 2,  N_("Upper 2")},
4079
4080		{PTP_DPC_CANON_ParameterSet, PTP_VENDOR_CANON, 0x08,  N_("Standard Development Parameters")},
4081		{PTP_DPC_CANON_ParameterSet, PTP_VENDOR_CANON, 0x10,  N_("Development Parameters 1")},
4082		{PTP_DPC_CANON_ParameterSet, PTP_VENDOR_CANON, 0x20,  N_("Development Parameters 2")},
4083		{PTP_DPC_CANON_ParameterSet, PTP_VENDOR_CANON, 0x40,  N_("Development Parameters 3")},
4084
4085		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x00,  N_("Auto")},
4086		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x28,  "6"},
4087		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x30,  "12"},
4088		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x38,  "25"},
4089		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x40,  "50"},
4090		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x43,  "64"},
4091		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x48,  "100"},
4092		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x50,  "200"},
4093		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x58,  "400"},
4094		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x60,  "800"},
4095		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x68,  "1600"},
4096		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x70,  "3200"},
4097		{PTP_DPC_CANON_ISOSpeed, PTP_VENDOR_CANON, 0x78,  "6400"},
4098
4099		/* 0xd01d - PTP_DPC_CANON_Aperture */
4100		/* 0xd01e - PTP_DPC_CANON_ShutterSpeed */
4101		/* 0xd01f - PTP_DPC_CANON_ExpCompensation */
4102		/* 0xd020 - PTP_DPC_CANON_FlashCompensation */
4103		/* 0xd021 - PTP_DPC_CANON_AEBExposureCompensation */
4104		/* 0xd023 - PTP_DPC_CANON_AvOpen */
4105		/* 0xd024 - PTP_DPC_CANON_AvMax */
4106
4107		{PTP_DPC_CANON_CameraOutput, PTP_VENDOR_CANON, 0,  N_("Undefined")},
4108		{PTP_DPC_CANON_CameraOutput, PTP_VENDOR_CANON, 1,  N_("LCD")},
4109		{PTP_DPC_CANON_CameraOutput, PTP_VENDOR_CANON, 2,  N_("Video OUT")},
4110		{PTP_DPC_CANON_CameraOutput, PTP_VENDOR_CANON, 3,  N_("Off")},
4111
4112		{PTP_DPC_CANON_MlSpotPos, PTP_VENDOR_CANON, 0, N_("MlSpotPosCenter")},
4113		{PTP_DPC_CANON_MlSpotPos, PTP_VENDOR_CANON, 1, N_("MlSpotPosAfLink")},
4114
4115		{PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 0, N_("Off")},
4116		{PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 1, N_("Vivid")},
4117		{PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 2, N_("Neutral")},
4118		{PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 3, N_("Soft")},
4119		{PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 4, N_("Sepia")},
4120		{PTP_DPC_CANON_PhotoEffect, PTP_VENDOR_CANON, 5, N_("Monochrome")},
4121
4122		{0, 0, 0, NULL}
4123	};
4124	for (i=0; ptp_value_trans[i].dpc!=0; i++) {
4125		if ((ptp_value_trans[i].dpc == dpc) &&
4126			(((ptp_value_trans[i].dpc & 0xf000) == 0x5000) ||
4127		         (ptp_value_trans[i].vendor == params->deviceinfo.VendorExtensionID))
4128		) {
4129			double value = _value_to_num(&(dpd->CurrentValue), dpd->DataType);
4130
4131			return snprintf(out, length,
4132				_(ptp_value_trans[i].format),
4133				value * ptp_value_trans[i].coef +
4134				ptp_value_trans[i].bias);
4135		}
4136	}
4137
4138	kval = _value_to_num(&(dpd->CurrentValue), dpd->DataType);
4139	for (i=0; ptp_value_list[i].dpc!=0; i++) {
4140		if ((ptp_value_list[i].dpc == dpc) &&
4141			(((ptp_value_list[i].dpc & 0xf000) == 0x5000) ||
4142		          (ptp_value_list[i].vendor == params->deviceinfo.VendorExtensionID)) &&
4143		    (ptp_value_list[i].key==kval)
4144		) {
4145			return snprintf(out, length, "%s", _(ptp_value_list[i].value));
4146		}
4147	}
4148	if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_MICROSOFT
4149	    || params->deviceinfo.VendorExtensionID==PTP_VENDOR_MTP) {
4150		switch (dpc) {
4151		case PTP_DPC_MTP_SynchronizationPartner:
4152		case PTP_DPC_MTP_DeviceFriendlyName:
4153			return snprintf(out, length, "%s", dpd->CurrentValue.str);
4154		case PTP_DPC_MTP_SecureTime:
4155		case PTP_DPC_MTP_DeviceCertificate: {
4156			/* FIXME: Convert to use unicode demux functions */
4157			for (i=0;(i<dpd->CurrentValue.a.count) && (i<length);i++)
4158				out[i] = dpd->CurrentValue.a.v[i].u16;
4159			if (	dpd->CurrentValue.a.count &&
4160				(dpd->CurrentValue.a.count < length)) {
4161				out[dpd->CurrentValue.a.count-1] = 0;
4162				return dpd->CurrentValue.a.count-1;
4163			} else {
4164				out[length-1] = 0;
4165				return length;
4166			}
4167			break;
4168		}
4169		default:
4170			break;
4171		}
4172	}
4173
4174	return 0;
4175}
4176
4177struct {
4178	uint16_t ofc;
4179	const char *format;
4180} ptp_ofc_trans[] = {
4181	{PTP_OFC_Undefined,"Undefined Type"},
4182	{PTP_OFC_Defined,"Defined Type"},
4183	{PTP_OFC_Association,"Association/Directory"},
4184	{PTP_OFC_Script,"Script"},
4185	{PTP_OFC_Executable,"Executable"},
4186	{PTP_OFC_Text,"Text"},
4187	{PTP_OFC_HTML,"HTML"},
4188	{PTP_OFC_DPOF,"DPOF"},
4189	{PTP_OFC_AIFF,"AIFF"},
4190	{PTP_OFC_WAV,"MS Wave"},
4191	{PTP_OFC_MP3,"MP3"},
4192	{PTP_OFC_AVI,"MS AVI"},
4193	{PTP_OFC_MPEG,"MPEG"},
4194	{PTP_OFC_ASF,"ASF"},
4195	{PTP_OFC_QT,"Apple Quicktime"},
4196	{PTP_OFC_EXIF_JPEG,"JPEG"},
4197	{PTP_OFC_TIFF_EP,"TIFF EP"},
4198	{PTP_OFC_FlashPix,"FlashPix"},
4199	{PTP_OFC_BMP,"BMP"},
4200	{PTP_OFC_CIFF,"CIFF"},
4201	{PTP_OFC_GIF,"GIF"},
4202	{PTP_OFC_JFIF,"JFIF"},
4203	{PTP_OFC_PCD,"PCD"},
4204	{PTP_OFC_PICT,"PICT"},
4205	{PTP_OFC_PNG,"PNG"},
4206	{PTP_OFC_TIFF,"TIFF"},
4207	{PTP_OFC_TIFF_IT,"TIFF_IT"},
4208	{PTP_OFC_JP2,"JP2"},
4209	{PTP_OFC_JPX,"JPX"},
4210	{PTP_OFC_DNG,"DNG"},
4211};
4212
4213struct {
4214	uint16_t ofc;
4215	const char *format;
4216} ptp_ofc_mtp_trans[] = {
4217	{PTP_OFC_MTP_MediaCard,N_("Media Card")},
4218	{PTP_OFC_MTP_MediaCardGroup,N_("Media Card Group")},
4219	{PTP_OFC_MTP_Encounter,N_("Encounter")},
4220	{PTP_OFC_MTP_EncounterBox,N_("Encounter Box")},
4221	{PTP_OFC_MTP_M4A,N_("M4A")},
4222	{PTP_OFC_MTP_Firmware,N_("Firmware")},
4223	{PTP_OFC_MTP_WindowsImageFormat,N_("Windows Image Format")},
4224	{PTP_OFC_MTP_UndefinedAudio,N_("Undefined Audio")},
4225	{PTP_OFC_MTP_WMA,"WMA"},
4226	{PTP_OFC_MTP_OGG,"OGG"},
4227	{PTP_OFC_MTP_AAC,"AAC"},
4228	{PTP_OFC_MTP_AudibleCodec,N_("Audible.com Codec")},
4229	{PTP_OFC_MTP_FLAC,"FLAC"},
4230	{PTP_OFC_MTP_UndefinedVideo,N_("Undefined Video")},
4231	{PTP_OFC_MTP_WMV,"WMV"},
4232	{PTP_OFC_MTP_MP4,"MP4"},
4233	{PTP_OFC_MTP_MP2,"MP2"},
4234	{PTP_OFC_MTP_3GP,"3GP"},
4235	{PTP_OFC_MTP_UndefinedCollection,N_("Undefined Collection")},
4236	{PTP_OFC_MTP_AbstractMultimediaAlbum,N_("Abstract Multimedia Album")},
4237	{PTP_OFC_MTP_AbstractImageAlbum,N_("Abstract Image Album")},
4238	{PTP_OFC_MTP_AbstractAudioAlbum,N_("Abstract Audio Album")},
4239	{PTP_OFC_MTP_AbstractVideoAlbum,N_("Abstract Video Album")},
4240	{PTP_OFC_MTP_AbstractAudioVideoPlaylist,N_("Abstract Audio Video Playlist")},
4241	{PTP_OFC_MTP_AbstractContactGroup,N_("Abstract Contact Group")},
4242	{PTP_OFC_MTP_AbstractMessageFolder,N_("Abstract Message Folder")},
4243	{PTP_OFC_MTP_AbstractChapteredProduction,N_("Abstract Chaptered Production")},
4244	{PTP_OFC_MTP_AbstractAudioPlaylist,N_("Abstract Audio Playlist")},
4245	{PTP_OFC_MTP_AbstractVideoPlaylist,N_("Abstract Video Playlist")},
4246	{PTP_OFC_MTP_AbstractMediacast,N_("Abstract Mediacast")},
4247	{PTP_OFC_MTP_WPLPlaylist,N_("WPL Playlist")},
4248	{PTP_OFC_MTP_M3UPlaylist,N_("M3U Playlist")},
4249	{PTP_OFC_MTP_MPLPlaylist,N_("MPL Playlist")},
4250	{PTP_OFC_MTP_ASXPlaylist,N_("ASX Playlist")},
4251	{PTP_OFC_MTP_PLSPlaylist,N_("PLS Playlist")},
4252	{PTP_OFC_MTP_UndefinedDocument,N_("Undefined Document")},
4253	{PTP_OFC_MTP_AbstractDocument,N_("Abstract Document")},
4254	{PTP_OFC_MTP_XMLDocument,N_("XMLDocument")},
4255	{PTP_OFC_MTP_MSWordDocument,N_("Microsoft Word Document")},
4256	{PTP_OFC_MTP_MHTCompiledHTMLDocument,N_("MHT Compiled HTML Document")},
4257	{PTP_OFC_MTP_MSExcelSpreadsheetXLS,N_("Microsoft Excel Spreadsheet (.xls)")},
4258	{PTP_OFC_MTP_MSPowerpointPresentationPPT,N_("Microsoft Powerpoint (.ppt)")},
4259	{PTP_OFC_MTP_UndefinedMessage,N_("Undefined Message")},
4260	{PTP_OFC_MTP_AbstractMessage,N_("Abstract Message")},
4261	{PTP_OFC_MTP_UndefinedContact,N_("Undefined Contact")},
4262	{PTP_OFC_MTP_AbstractContact,N_("Abstract Contact")},
4263	{PTP_OFC_MTP_vCard2,N_("vCard2")},
4264	{PTP_OFC_MTP_vCard3,N_("vCard3")},
4265	{PTP_OFC_MTP_UndefinedCalendarItem,N_("Undefined Calendar Item")},
4266	{PTP_OFC_MTP_AbstractCalendarItem,N_("Abstract Calendar Item")},
4267	{PTP_OFC_MTP_vCalendar1,N_("vCalendar1")},
4268	{PTP_OFC_MTP_vCalendar2,N_("vCalendar2")},
4269	{PTP_OFC_MTP_UndefinedWindowsExecutable,N_("Undefined Windows Executable")},
4270	{PTP_OFC_MTP_MediaCast,N_("Media Cast")},
4271	{PTP_OFC_MTP_Section,N_("Section")},
4272};
4273
4274int
4275ptp_render_ofc(PTPParams* params, uint16_t ofc, int spaceleft, char *txt)
4276{
4277	int i;
4278
4279	if (!(ofc & 0x8000)) {
4280		for (i=0;i<sizeof(ptp_ofc_trans)/sizeof(ptp_ofc_trans[0]);i++)
4281			if (ofc == ptp_ofc_trans[i].ofc)
4282				return snprintf(txt, spaceleft, "%s", _(ptp_ofc_trans[i].format));
4283	} else {
4284		switch (params->deviceinfo.VendorExtensionID) {
4285		case PTP_VENDOR_EASTMAN_KODAK:
4286			switch (ofc) {
4287			case PTP_OFC_EK_M3U:
4288				return snprintf (txt, spaceleft,"M3U");
4289			default:
4290				break;
4291			}
4292			break;
4293		case PTP_VENDOR_CANON:
4294			switch (ofc) {
4295			case PTP_OFC_CANON_CRW:
4296				return snprintf (txt, spaceleft,"CRW");
4297			default:
4298				break;
4299			}
4300			break;
4301		case PTP_VENDOR_MICROSOFT:
4302		case PTP_VENDOR_MTP:
4303			for (i=0;i<sizeof(ptp_ofc_mtp_trans)/sizeof(ptp_ofc_mtp_trans[0]);i++)
4304				if (ofc == ptp_ofc_mtp_trans[i].ofc)
4305					return snprintf(txt, spaceleft, "%s", _(ptp_ofc_mtp_trans[i].format));
4306			break;
4307		default:break;
4308		}
4309	}
4310	return snprintf (txt, spaceleft,_("Unknown(%04x)"), ofc);
4311}
4312
4313struct {
4314	uint16_t opcode;
4315	const char *name;
4316} ptp_opcode_trans[] = {
4317	{PTP_OC_Undefined,N_("Undefined")},
4318	{PTP_OC_GetDeviceInfo,N_("get device info")},
4319	{PTP_OC_OpenSession,N_("Open session")},
4320	{PTP_OC_CloseSession,N_("Close session")},
4321	{PTP_OC_GetStorageIDs,N_("Get storage IDs")},
4322	{PTP_OC_GetStorageInfo,N_("Get storage info")},
4323	{PTP_OC_GetNumObjects,N_("Get number of objects")},
4324	{PTP_OC_GetObjectHandles,N_("Get object handles")},
4325	{PTP_OC_GetObjectInfo,N_("Get object info")},
4326	{PTP_OC_GetObject,N_("Get object")},
4327	{PTP_OC_GetThumb,N_("Get thumbnail")},
4328	{PTP_OC_DeleteObject,N_("Delete object")},
4329	{PTP_OC_SendObjectInfo,N_("Send object info")},
4330	{PTP_OC_SendObject,N_("Send object")},
4331	{PTP_OC_InitiateCapture,N_("Initiate capture")},
4332	{PTP_OC_FormatStore,N_("Format storage")},
4333	{PTP_OC_ResetDevice,N_("Reset device")},
4334	{PTP_OC_SelfTest,N_("Self test device")},
4335	{PTP_OC_SetObjectProtection,N_("Set object protection")},
4336	{PTP_OC_PowerDown,N_("Power down device")},
4337	{PTP_OC_GetDevicePropDesc,N_("Get device property description")},
4338	{PTP_OC_GetDevicePropValue,N_("Get device property value")},
4339	{PTP_OC_SetDevicePropValue,N_("Set device property value")},
4340	{PTP_OC_ResetDevicePropValue,N_("Reset device property value")},
4341	{PTP_OC_TerminateOpenCapture,N_("Terminate open capture")},
4342	{PTP_OC_MoveObject,N_("Move object")},
4343	{PTP_OC_CopyObject,N_("Copy object")},
4344	{PTP_OC_GetPartialObject,N_("Get partial object")},
4345	{PTP_OC_InitiateOpenCapture,N_("Initiate open capture")}
4346};
4347
4348struct {
4349	uint16_t opcode;
4350	const char *name;
4351} ptp_opcode_mtp_trans[] = {
4352	{PTP_OC_MTP_GetObjectPropsSupported,N_("Get object properties supported")},
4353	{PTP_OC_MTP_GetObjectPropDesc,N_("Get object property description")},
4354	{PTP_OC_MTP_GetObjectPropValue,N_("Get object property value")},
4355	{PTP_OC_MTP_SetObjectPropValue,N_("Set object property value")},
4356	{PTP_OC_MTP_GetObjPropList,N_("Get object property list")},
4357	{PTP_OC_MTP_SetObjPropList,N_("Set object property list")},
4358	{PTP_OC_MTP_GetInterdependendPropdesc,N_("Get interdependent property description")},
4359	{PTP_OC_MTP_SendObjectPropList,N_("Send object property list")},
4360	{PTP_OC_MTP_GetObjectReferences,N_("Get object references")},
4361	{PTP_OC_MTP_SetObjectReferences,N_("Set object references")},
4362	{PTP_OC_MTP_UpdateDeviceFirmware,N_("Update device firmware")},
4363	{PTP_OC_MTP_Skip,N_("Skip to next position in playlist")},
4364
4365	/* WMDRMPD Extensions */
4366	{PTP_OC_MTP_WMDRMPD_GetSecureTimeChallenge,N_("Get secure time challenge")},
4367	{PTP_OC_MTP_WMDRMPD_GetSecureTimeResponse,N_("Get secure time response")},
4368	{PTP_OC_MTP_WMDRMPD_SetLicenseResponse,N_("Set license response")},
4369	{PTP_OC_MTP_WMDRMPD_GetSyncList,N_("Get sync list")},
4370	{PTP_OC_MTP_WMDRMPD_SendMeterChallengeQuery,N_("Send meter challenge query")},
4371	{PTP_OC_MTP_WMDRMPD_GetMeterChallenge,N_("Get meter challenge")},
4372	{PTP_OC_MTP_WMDRMPD_SetMeterResponse,N_("Get meter response")},
4373	{PTP_OC_MTP_WMDRMPD_CleanDataStore,N_("Clean data store")},
4374	{PTP_OC_MTP_WMDRMPD_GetLicenseState,N_("Get license state")},
4375	{PTP_OC_MTP_WMDRMPD_SendWMDRMPDCommand,N_("Send WMDRM-PD Command")},
4376	{PTP_OC_MTP_WMDRMPD_SendWMDRMPDRequest,N_("Send WMDRM-PD Request")},
4377
4378	/* WMPPD Extensions */
4379	{PTP_OC_MTP_WMPPD_ReportAddedDeletedItems,N_("Report Added/Deleted Items")},
4380	{PTP_OC_MTP_WMPPD_ReportAcquiredItems,N_("Report Acquired Items")},
4381	{PTP_OC_MTP_WMPPD_PlaylistObjectPref,N_("Get transferable playlist types")},
4382
4383	/* WMDRMPD Extensions... these have no identifiers associated with them */
4384	{PTP_OC_MTP_WMDRMPD_SendWMDRMPDAppRequest,N_("Send WMDRM-PD Application Request")},
4385	{PTP_OC_MTP_WMDRMPD_GetWMDRMPDAppResponse,N_("Get WMDRM-PD Application Response")},
4386	{PTP_OC_MTP_WMDRMPD_EnableTrustedFilesOperations,N_("Enable trusted file operations")},
4387	{PTP_OC_MTP_WMDRMPD_DisableTrustedFilesOperations,N_("Disable trusted file operations")},
4388	{PTP_OC_MTP_WMDRMPD_EndTrustedAppSession,N_("End trusted application session")},
4389
4390	/* AAVT Extensions */
4391	{PTP_OC_MTP_AAVT_OpenMediaSession,N_("Open Media Session")},
4392	{PTP_OC_MTP_AAVT_CloseMediaSession,N_("Close Media Session")},
4393	{PTP_OC_MTP_AAVT_GetNextDataBlock,N_("Get Next Data Block")},
4394	{PTP_OC_MTP_AAVT_SetCurrentTimePosition,N_("Set Current Time Position")},
4395
4396	/* WMDRMND Extensions */
4397	{PTP_OC_MTP_WMDRMND_SendRegistrationRequest,N_("Send Registration Request")},
4398	{PTP_OC_MTP_WMDRMND_GetRegistrationResponse,N_("Get Registration Response")},
4399	{PTP_OC_MTP_WMDRMND_GetProximityChallenge,N_("Get Proximity Challenge")},
4400	{PTP_OC_MTP_WMDRMND_SendProximityResponse,N_("Send Proximity Response")},
4401	{PTP_OC_MTP_WMDRMND_SendWMDRMNDLicenseRequest,N_("Send WMDRM-ND License Request")},
4402	{PTP_OC_MTP_WMDRMND_GetWMDRMNDLicenseResponse,N_("Get WMDRM-ND License Response")},
4403
4404	/* WiFi Provisioning MTP Extension Codes (microsoft.com/WPDWCN: 1.0) */
4405	{PTP_OC_MTP_WPDWCN_ProcessWFCObject,N_("Process WFC Object")}
4406};
4407
4408int
4409ptp_render_opcode(PTPParams* params, uint16_t opcode, int spaceleft, char *txt)
4410{
4411	int i;
4412
4413	if (!(opcode & 0x8000)) {
4414		for (i=0;i<sizeof(ptp_opcode_trans)/sizeof(ptp_opcode_trans[0]);i++)
4415			if (opcode == ptp_opcode_trans[i].opcode)
4416				return snprintf(txt, spaceleft, "%s", _(ptp_opcode_trans[i].name));
4417	} else {
4418		switch (params->deviceinfo.VendorExtensionID) {
4419		case PTP_VENDOR_MICROSOFT:
4420		case PTP_VENDOR_MTP:
4421			for (i=0;i<sizeof(ptp_opcode_mtp_trans)/sizeof(ptp_opcode_mtp_trans[0]);i++)
4422				if (opcode == ptp_opcode_mtp_trans[i].opcode)
4423					return snprintf(txt, spaceleft, "%s", _(ptp_opcode_mtp_trans[i].name));
4424			break;
4425		default:break;
4426		}
4427	}
4428	return snprintf (txt, spaceleft,_("Unknown (%04x)"), opcode);
4429}
4430
4431
4432struct {
4433	uint16_t id;
4434	const char *name;
4435} ptp_opc_trans[] = {
4436	{PTP_OPC_StorageID,"StorageID"},
4437	{PTP_OPC_ObjectFormat,"ObjectFormat"},
4438	{PTP_OPC_ProtectionStatus,"ProtectionStatus"},
4439	{PTP_OPC_ObjectSize,"ObjectSize"},
4440	{PTP_OPC_AssociationType,"AssociationType"},
4441	{PTP_OPC_AssociationDesc,"AssociationDesc"},
4442	{PTP_OPC_ObjectFileName,"ObjectFileName"},
4443	{PTP_OPC_DateCreated,"DateCreated"},
4444	{PTP_OPC_DateModified,"DateModified"},
4445	{PTP_OPC_Keywords,"Keywords"},
4446	{PTP_OPC_ParentObject,"ParentObject"},
4447	{PTP_OPC_AllowedFolderContents,"AllowedFolderContents"},
4448	{PTP_OPC_Hidden,"Hidden"},
4449	{PTP_OPC_SystemObject,"SystemObject"},
4450	{PTP_OPC_PersistantUniqueObjectIdentifier,"PersistantUniqueObjectIdentifier"},
4451	{PTP_OPC_SyncID,"SyncID"},
4452	{PTP_OPC_PropertyBag,"PropertyBag"},
4453	{PTP_OPC_Name,"Name"},
4454	{PTP_OPC_CreatedBy,"CreatedBy"},
4455	{PTP_OPC_Artist,"Artist"},
4456	{PTP_OPC_DateAuthored,"DateAuthored"},
4457	{PTP_OPC_Description,"Description"},
4458	{PTP_OPC_URLReference,"URLReference"},
4459	{PTP_OPC_LanguageLocale,"LanguageLocale"},
4460	{PTP_OPC_CopyrightInformation,"CopyrightInformation"},
4461	{PTP_OPC_Source,"Source"},
4462	{PTP_OPC_OriginLocation,"OriginLocation"},
4463	{PTP_OPC_DateAdded,"DateAdded"},
4464	{PTP_OPC_NonConsumable,"NonConsumable"},
4465	{PTP_OPC_CorruptOrUnplayable,"CorruptOrUnplayable"},
4466	{PTP_OPC_ProducerSerialNumber,"ProducerSerialNumber"},
4467	{PTP_OPC_RepresentativeSampleFormat,"RepresentativeSampleFormat"},
4468	{PTP_OPC_RepresentativeSampleSize,"RepresentativeSampleSize"},
4469	{PTP_OPC_RepresentativeSampleHeight,"RepresentativeSampleHeight"},
4470	{PTP_OPC_RepresentativeSampleWidth,"RepresentativeSampleWidth"},
4471	{PTP_OPC_RepresentativeSampleDuration,"RepresentativeSampleDuration"},
4472	{PTP_OPC_RepresentativeSampleData,"RepresentativeSampleData"},
4473	{PTP_OPC_Width,"Width"},
4474	{PTP_OPC_Height,"Height"},
4475	{PTP_OPC_Duration,"Duration"},
4476	{PTP_OPC_Rating,"Rating"},
4477	{PTP_OPC_Track,"Track"},
4478	{PTP_OPC_Genre,"Genre"},
4479	{PTP_OPC_Credits,"Credits"},
4480	{PTP_OPC_Lyrics,"Lyrics"},
4481	{PTP_OPC_SubscriptionContentID,"SubscriptionContentID"},
4482	{PTP_OPC_ProducedBy,"ProducedBy"},
4483	{PTP_OPC_UseCount,"UseCount"},
4484	{PTP_OPC_SkipCount,"SkipCount"},
4485	{PTP_OPC_LastAccessed,"LastAccessed"},
4486	{PTP_OPC_ParentalRating,"ParentalRating"},
4487	{PTP_OPC_MetaGenre,"MetaGenre"},
4488	{PTP_OPC_Composer,"Composer"},
4489	{PTP_OPC_EffectiveRating,"EffectiveRating"},
4490	{PTP_OPC_Subtitle,"Subtitle"},
4491	{PTP_OPC_OriginalReleaseDate,"OriginalReleaseDate"},
4492	{PTP_OPC_AlbumName,"AlbumName"},
4493	{PTP_OPC_AlbumArtist,"AlbumArtist"},
4494	{PTP_OPC_Mood,"Mood"},
4495	{PTP_OPC_DRMStatus,"DRMStatus"},
4496	{PTP_OPC_SubDescription,"SubDescription"},
4497	{PTP_OPC_IsCropped,"IsCropped"},
4498	{PTP_OPC_IsColorCorrected,"IsColorCorrected"},
4499	{PTP_OPC_ImageBitDepth,"ImageBitDepth"},
4500	{PTP_OPC_Fnumber,"Fnumber"},
4501	{PTP_OPC_ExposureTime,"ExposureTime"},
4502	{PTP_OPC_ExposureIndex,"ExposureIndex"},
4503	{PTP_OPC_DisplayName,"DisplayName"},
4504	{PTP_OPC_BodyText,"BodyText"},
4505	{PTP_OPC_Subject,"Subject"},
4506	{PTP_OPC_Priority,"Priority"},
4507	{PTP_OPC_GivenName,"GivenName"},
4508	{PTP_OPC_MiddleNames,"MiddleNames"},
4509	{PTP_OPC_FamilyName,"FamilyName"},
4510
4511	{PTP_OPC_Prefix,"Prefix"},
4512	{PTP_OPC_Suffix,"Suffix"},
4513	{PTP_OPC_PhoneticGivenName,"PhoneticGivenName"},
4514	{PTP_OPC_PhoneticFamilyName,"PhoneticFamilyName"},
4515	{PTP_OPC_EmailPrimary,"EmailPrimary"},
4516	{PTP_OPC_EmailPersonal1,"EmailPersonal1"},
4517	{PTP_OPC_EmailPersonal2,"EmailPersonal2"},
4518	{PTP_OPC_EmailBusiness1,"EmailBusiness1"},
4519	{PTP_OPC_EmailBusiness2,"EmailBusiness2"},
4520	{PTP_OPC_EmailOthers,"EmailOthers"},
4521	{PTP_OPC_PhoneNumberPrimary,"PhoneNumberPrimary"},
4522	{PTP_OPC_PhoneNumberPersonal,"PhoneNumberPersonal"},
4523	{PTP_OPC_PhoneNumberPersonal2,"PhoneNumberPersonal2"},
4524	{PTP_OPC_PhoneNumberBusiness,"PhoneNumberBusiness"},
4525	{PTP_OPC_PhoneNumberBusiness2,"PhoneNumberBusiness2"},
4526	{PTP_OPC_PhoneNumberMobile,"PhoneNumberMobile"},
4527	{PTP_OPC_PhoneNumberMobile2,"PhoneNumberMobile2"},
4528	{PTP_OPC_FaxNumberPrimary,"FaxNumberPrimary"},
4529	{PTP_OPC_FaxNumberPersonal,"FaxNumberPersonal"},
4530	{PTP_OPC_FaxNumberBusiness,"FaxNumberBusiness"},
4531	{PTP_OPC_PagerNumber,"PagerNumber"},
4532	{PTP_OPC_PhoneNumberOthers,"PhoneNumberOthers"},
4533	{PTP_OPC_PrimaryWebAddress,"PrimaryWebAddress"},
4534	{PTP_OPC_PersonalWebAddress,"PersonalWebAddress"},
4535	{PTP_OPC_BusinessWebAddress,"BusinessWebAddress"},
4536	{PTP_OPC_InstantMessengerAddress,"InstantMessengerAddress"},
4537	{PTP_OPC_InstantMessengerAddress2,"InstantMessengerAddress2"},
4538	{PTP_OPC_InstantMessengerAddress3,"InstantMessengerAddress3"},
4539	{PTP_OPC_PostalAddressPersonalFull,"PostalAddressPersonalFull"},
4540	{PTP_OPC_PostalAddressPersonalFullLine1,"PostalAddressPersonalFullLine1"},
4541	{PTP_OPC_PostalAddressPersonalFullLine2,"PostalAddressPersonalFullLine2"},
4542	{PTP_OPC_PostalAddressPersonalFullCity,"PostalAddressPersonalFullCity"},
4543	{PTP_OPC_PostalAddressPersonalFullRegion,"PostalAddressPersonalFullRegion"},
4544	{PTP_OPC_PostalAddressPersonalFullPostalCode,"PostalAddressPersonalFullPostalCode"},
4545	{PTP_OPC_PostalAddressPersonalFullCountry,"PostalAddressPersonalFullCountry"},
4546	{PTP_OPC_PostalAddressBusinessFull,"PostalAddressBusinessFull"},
4547	{PTP_OPC_PostalAddressBusinessLine1,"PostalAddressBusinessLine1"},
4548	{PTP_OPC_PostalAddressBusinessLine2,"PostalAddressBusinessLine2"},
4549	{PTP_OPC_PostalAddressBusinessCity,"PostalAddressBusinessCity"},
4550	{PTP_OPC_PostalAddressBusinessRegion,"PostalAddressBusinessRegion"},
4551	{PTP_OPC_PostalAddressBusinessPostalCode,"PostalAddressBusinessPostalCode"},
4552	{PTP_OPC_PostalAddressBusinessCountry,"PostalAddressBusinessCountry"},
4553	{PTP_OPC_PostalAddressOtherFull,"PostalAddressOtherFull"},
4554	{PTP_OPC_PostalAddressOtherLine1,"PostalAddressOtherLine1"},
4555	{PTP_OPC_PostalAddressOtherLine2,"PostalAddressOtherLine2"},
4556	{PTP_OPC_PostalAddressOtherCity,"PostalAddressOtherCity"},
4557	{PTP_OPC_PostalAddressOtherRegion,"PostalAddressOtherRegion"},
4558	{PTP_OPC_PostalAddressOtherPostalCode,"PostalAddressOtherPostalCode"},
4559	{PTP_OPC_PostalAddressOtherCountry,"PostalAddressOtherCountry"},
4560	{PTP_OPC_OrganizationName,"OrganizationName"},
4561	{PTP_OPC_PhoneticOrganizationName,"PhoneticOrganizationName"},
4562	{PTP_OPC_Role,"Role"},
4563	{PTP_OPC_Birthdate,"Birthdate"},
4564	{PTP_OPC_MessageTo,"MessageTo"},
4565	{PTP_OPC_MessageCC,"MessageCC"},
4566	{PTP_OPC_MessageBCC,"MessageBCC"},
4567	{PTP_OPC_MessageRead,"MessageRead"},
4568	{PTP_OPC_MessageReceivedTime,"MessageReceivedTime"},
4569	{PTP_OPC_MessageSender,"MessageSender"},
4570	{PTP_OPC_ActivityBeginTime,"ActivityBeginTime"},
4571	{PTP_OPC_ActivityEndTime,"ActivityEndTime"},
4572	{PTP_OPC_ActivityLocation,"ActivityLocation"},
4573	{PTP_OPC_ActivityRequiredAttendees,"ActivityRequiredAttendees"},
4574	{PTP_OPC_ActivityOptionalAttendees,"ActivityOptionalAttendees"},
4575	{PTP_OPC_ActivityResources,"ActivityResources"},
4576	{PTP_OPC_ActivityAccepted,"ActivityAccepted"},
4577	{PTP_OPC_Owner,"Owner"},
4578	{PTP_OPC_Editor,"Editor"},
4579	{PTP_OPC_Webmaster,"Webmaster"},
4580	{PTP_OPC_URLSource,"URLSource"},
4581	{PTP_OPC_URLDestination,"URLDestination"},
4582	{PTP_OPC_TimeBookmark,"TimeBookmark"},
4583	{PTP_OPC_ObjectBookmark,"ObjectBookmark"},
4584	{PTP_OPC_ByteBookmark,"ByteBookmark"},
4585	{PTP_OPC_LastBuildDate,"LastBuildDate"},
4586	{PTP_OPC_TimetoLive,"TimetoLive"},
4587	{PTP_OPC_MediaGUID,"MediaGUID"},
4588	{PTP_OPC_TotalBitRate,"TotalBitRate"},
4589	{PTP_OPC_BitRateType,"BitRateType"},
4590	{PTP_OPC_SampleRate,"SampleRate"},
4591	{PTP_OPC_NumberOfChannels,"NumberOfChannels"},
4592	{PTP_OPC_AudioBitDepth,"AudioBitDepth"},
4593	{PTP_OPC_ScanDepth,"ScanDepth"},
4594	{PTP_OPC_AudioWAVECodec,"AudioWAVECodec"},
4595	{PTP_OPC_AudioBitRate,"AudioBitRate"},
4596	{PTP_OPC_VideoFourCCCodec,"VideoFourCCCodec"},
4597	{PTP_OPC_VideoBitRate,"VideoBitRate"},
4598	{PTP_OPC_FramesPerThousandSeconds,"FramesPerThousandSeconds"},
4599	{PTP_OPC_KeyFrameDistance,"KeyFrameDistance"},
4600	{PTP_OPC_BufferSize,"BufferSize"},
4601	{PTP_OPC_EncodingQuality,"EncodingQuality"},
4602	{PTP_OPC_EncodingProfile,"EncodingProfile"},
4603	{PTP_OPC_BuyFlag,"BuyFlag"},
4604};
4605
4606int
4607ptp_render_mtp_propname(uint16_t propid, int spaceleft, char *txt) {
4608	int i;
4609	for (i=0;i<sizeof(ptp_opc_trans)/sizeof(ptp_opc_trans[0]);i++)
4610		if (propid == ptp_opc_trans[i].id)
4611			return snprintf(txt, spaceleft, "%s", ptp_opc_trans[i].name);
4612	return snprintf (txt, spaceleft,"unknown(%04x)", propid);
4613}
4614
4615/*
4616 * Allocate and default-initialize a few object properties.
4617 */
4618MTPProperties *
4619ptp_get_new_object_prop_entry(MTPProperties **props, int *nrofprops) {
4620	MTPProperties *newprops;
4621	MTPProperties *prop;
4622
4623	if (*props == NULL) {
4624		newprops = malloc(sizeof(MTPProperties)*(*nrofprops+1));
4625	} else {
4626		newprops = realloc(*props,sizeof(MTPProperties)*(*nrofprops+1));
4627	}
4628	if (newprops == NULL)
4629		return NULL;
4630	prop = &newprops[*nrofprops];
4631	prop->property = PTP_OPC_StorageID; /* Should be "unknown" */
4632	prop->datatype = PTP_DTC_UNDEF;
4633	prop->ObjectHandle = 0x00000000U;
4634	prop->propval.str = NULL;
4635
4636	(*props) = newprops;
4637	(*nrofprops)++;
4638	return prop;
4639}
4640
4641void
4642ptp_destroy_object_prop(MTPProperties *prop)
4643{
4644  if (!prop)
4645    return;
4646
4647  if (prop->datatype == PTP_DTC_STR && prop->propval.str != NULL)
4648    free(prop->propval.str);
4649  else if ((prop->datatype == PTP_DTC_AINT8 || prop->datatype == PTP_DTC_AINT16 ||
4650            prop->datatype == PTP_DTC_AINT32 || prop->datatype == PTP_DTC_AINT64 || prop->datatype == PTP_DTC_AINT128 ||
4651            prop->datatype == PTP_DTC_AUINT8 || prop->datatype == PTP_DTC_AUINT16 ||
4652            prop->datatype == PTP_DTC_AUINT32 || prop->datatype == PTP_DTC_AUINT64 || prop->datatype ==  PTP_DTC_AUINT128)
4653            && prop->propval.a.v != NULL)
4654    free(prop->propval.a.v);
4655}
4656
4657void
4658ptp_destroy_object_prop_list(MTPProperties *props, int nrofprops)
4659{
4660  int i;
4661  MTPProperties *prop = props;
4662
4663  for (i=0;i<nrofprops;i++,prop++)
4664    ptp_destroy_object_prop(prop);
4665  free(props);
4666}
4667
4668/*
4669 * Find a certain object property in the cache, i.e. a certain metadata
4670 * item for a certain object handle.
4671 */
4672MTPProperties *
4673ptp_find_object_prop_in_cache(PTPParams *params, uint32_t const handle, uint32_t const attribute_id)
4674{
4675	int	i;
4676	MTPProperties	*prop;
4677	PTPObject	*ob;
4678	uint16_t	ret;
4679
4680	ret = ptp_object_find (params, handle, &ob);
4681	if (ret != PTP_RC_OK)
4682		return NULL;
4683	prop = ob->mtpprops;
4684	for (i=0;i<ob->nrofmtpprops;i++) {
4685		if (attribute_id == prop->property)
4686			return prop;
4687		prop++;
4688	}
4689	return NULL;
4690}
4691
4692void
4693ptp_remove_object_from_cache(PTPParams *params, uint32_t handle)
4694{
4695	int i;
4696	PTPObject	*ob;
4697	uint16_t	ret;
4698
4699	ret = ptp_object_find (params, handle, &ob);
4700	if (ret != PTP_RC_OK)
4701		return;
4702	i = ob-params->objects;
4703	/* remove object from object info cache */
4704	ptp_free_object (ob);
4705
4706	if (i < params->nrofobjects-1)
4707		memmove (ob,ob+1,(params->nrofobjects-1-i)*sizeof(PTPObject));
4708	params->nrofobjects--;
4709	/* We use less memory than before so this shouldn't fail */
4710	params->objects = realloc(params->objects, sizeof(PTPObject)*params->nrofobjects);
4711}
4712
4713static int _cmp_ob (const void *a, const void *b) {
4714	PTPObject *oa = (PTPObject*)a;
4715	PTPObject *ob = (PTPObject*)b;
4716
4717	return oa->oid - ob->oid;
4718}
4719
4720void
4721ptp_objects_sort (PTPParams *params) {
4722	qsort (params->objects, params->nrofobjects, sizeof(PTPObject), _cmp_ob);
4723}
4724
4725/* Binary search in objects. Needs "objects" to be a sorted by objectid list!  */
4726uint16_t
4727ptp_object_find (PTPParams *params, uint32_t handle, PTPObject **retob) {
4728	PTPObject	tmpob;
4729
4730	tmpob.oid = handle;
4731	*retob = bsearch (&tmpob, params->objects, params->nrofobjects, sizeof(tmpob), _cmp_ob);
4732	if (!*retob)
4733		return PTP_RC_GeneralError;
4734	return PTP_RC_OK;
4735}
4736
4737/* Binary search in objects + insert of not found. Needs "objects" to be a sorted by objectid list!  */
4738uint16_t
4739ptp_object_find_or_insert (PTPParams *params, uint32_t handle, PTPObject **retob) {
4740	int 		begin, end, cursor;
4741	int		insertat;
4742	PTPObject	*newobs;
4743
4744	if (!handle) return PTP_RC_GeneralError;
4745	*retob = NULL;
4746	if (!params->nrofobjects) {
4747		params->objects = calloc(1,sizeof(PTPObject));
4748		params->nrofobjects = 1;
4749		params->objects[0].oid = handle;
4750		*retob = &params->objects[0];
4751		return PTP_RC_OK;
4752	}
4753	begin = 0;
4754	end = params->nrofobjects-1;
4755	/*ptp_debug (params, "searching %08x, total=%d", handle, params->nrofobjects);*/
4756	while (1) {
4757		cursor = (end-begin)/2+begin;
4758		/*ptp_debug (params, "ob %d: %08x [%d-%d]", cursor, params->objects[cursor].oid, begin, end);*/
4759		if (params->objects[cursor].oid == handle) {
4760			*retob = &params->objects[cursor];
4761			return PTP_RC_OK;
4762		}
4763		if (params->objects[cursor].oid < handle)
4764			begin = cursor;
4765		else
4766			end = cursor;
4767		if ((end - begin) <= 1)
4768			break;
4769	}
4770	if (params->objects[begin].oid == handle) {
4771		*retob = &params->objects[begin];
4772		return PTP_RC_OK;
4773	}
4774	if (params->objects[end].oid == handle) {
4775		*retob = &params->objects[end];
4776		return PTP_RC_OK;
4777	}
4778	if ((begin == 0) && (handle < params->objects[0].oid)) {
4779		insertat=begin;
4780	} else {
4781		if ((end == params->nrofobjects-1) && (handle > params->objects[end].oid))
4782			insertat=end+1;
4783		else
4784			insertat=begin+1;
4785	}
4786	/*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);*/
4787	newobs = realloc (params->objects, sizeof(PTPObject)*(params->nrofobjects+1));
4788	if (!newobs) return PTP_RC_GeneralError;
4789	params->objects = newobs;
4790	if (insertat<=params->nrofobjects)
4791		memmove (&params->objects[insertat+1],&params->objects[insertat],(params->nrofobjects-insertat)*sizeof(PTPObject));
4792	memset(&params->objects[insertat],0,sizeof(PTPObject));
4793	params->objects[insertat].oid = handle;
4794	*retob = &params->objects[insertat];
4795	params->nrofobjects++;
4796	return PTP_RC_OK;
4797}
4798
4799uint16_t
4800ptp_object_want (PTPParams *params, uint32_t handle, int want, PTPObject **retob) {
4801	uint16_t	ret;
4802	PTPObject	*ob;
4803	//Camera 		*camera = ((PTPData *)params->data)->camera;
4804
4805	*retob = NULL;
4806	if (!handle) {
4807		ptp_debug (params, "ptp_object_want: querying handle 0?\n");
4808		return PTP_RC_GeneralError;
4809	}
4810	ret = ptp_object_find_or_insert (params, handle, &ob);
4811	if (ret != PTP_RC_OK)
4812		return PTP_RC_GeneralError;
4813	*retob = ob;
4814	/* Do we have all of it already? */
4815	if ((ob->flags & want) == want)
4816		return PTP_RC_OK;
4817
4818#define X (PTPOBJECT_OBJECTINFO_LOADED|PTPOBJECT_STORAGEID_LOADED|PTPOBJECT_PARENTOBJECT_LOADED)
4819	if ((want & X) && ((ob->flags & X) != X)) {
4820		uint32_t	saveparent = 0;
4821
4822		/* One EOS issue, where getobjecthandles(root) returns obs without root flag. */
4823		if (ob->flags & PTPOBJECT_PARENTOBJECT_LOADED)
4824			saveparent = ob->oi.ParentObject;
4825
4826		ret = ptp_getobjectinfo (params, handle, &ob->oi);
4827		if (ret != PTP_RC_OK)
4828			return ret;
4829		if (!ob->oi.Filename) ob->oi.Filename=strdup("<none>");
4830		if (ob->flags & PTPOBJECT_PARENTOBJECT_LOADED)
4831			ob->oi.ParentObject = saveparent;
4832
4833		/* Second EOS issue, 0x20000000 has 0x20000000 as parent */
4834		if (ob->oi.ParentObject == handle)
4835			ob->oi.ParentObject = 0;
4836		ob->flags |= X;
4837
4838		/* EOS bug, DCIM links back to itself. */
4839	}
4840#undef X
4841	if (	(want & PTPOBJECT_MTPPROPLIST_LOADED) &&
4842		(!(ob->flags & PTPOBJECT_MTPPROPLIST_LOADED))
4843	) {
4844		int		nrofprops = 0;
4845		MTPProperties 	*props = NULL;
4846
4847		if (params->device_flags & DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST) {
4848			want &= ~PTPOBJECT_MTPPROPLIST_LOADED;
4849			goto fallback;
4850		}
4851
4852		/* Microsoft/MTP has fast directory retrieval. */
4853		if (!ptp_operation_issupported(params,PTP_OC_MTP_GetObjPropList)) {
4854			want &= ~PTPOBJECT_MTPPROPLIST_LOADED;
4855			goto fallback;
4856		}
4857
4858		ptp_debug (params, "ptp2/mtpfast: reading mtp proplist of %08x", handle);
4859		ret = ptp_mtp_getobjectproplist (params, handle, &props, &nrofprops);
4860		if (ret != PTP_RC_OK)
4861			goto fallback;
4862		ob->mtpprops = props;
4863		ob->nrofmtpprops = nrofprops;
4864
4865#if 0
4866		MTPProperties 	*xpl;
4867		int j;
4868		PTPObjectInfo	oinfo;
4869
4870		memset (&oinfo,0,sizeof(oinfo));
4871		/* hmm, not necessary ... only if we would use it */
4872		for (j=0;j<nrofprops;j++) {
4873			xpl = &props[j];
4874			switch (xpl->property) {
4875			case PTP_OPC_ParentObject:
4876				if (xpl->datatype != PTP_DTC_UINT32) {
4877					ptp_debug (params, "ptp2/mtpfast: parentobject has type 0x%x???", xpl->datatype);
4878					break;
4879				}
4880				oinfo.ParentObject = xpl->propval.u32;
4881				ptp_debug (params, "ptp2/mtpfast: parent 0x%x", xpl->propval.u32);
4882				break;
4883			case PTP_OPC_ObjectFormat:
4884				if (xpl->datatype != PTP_DTC_UINT16) {
4885					ptp_debug (params, "ptp2/mtpfast: objectformat has type 0x%x???", xpl->datatype);
4886					break;
4887				}
4888				oinfo.ObjectFormat = xpl->propval.u16;
4889				ptp_debug (params, "ptp2/mtpfast: ofc 0x%x", xpl->propval.u16);
4890				break;
4891			case PTP_OPC_ObjectSize:
4892				switch (xpl->datatype) {
4893				case PTP_DTC_UINT32:
4894					oinfo.ObjectCompressedSize = xpl->propval.u32;
4895					break;
4896				case PTP_DTC_UINT64:
4897					oinfo.ObjectCompressedSize = xpl->propval.u64;
4898					break;
4899				default:
4900					ptp_debug (params, "ptp2/mtpfast: objectsize has type 0x%x???", xpl->datatype);
4901					break;
4902				}
4903				ptp_debug (params, "ptp2/mtpfast: objectsize %u", xpl->propval.u32);
4904				break;
4905			case PTP_OPC_StorageID:
4906				if (xpl->datatype != PTP_DTC_UINT32) {
4907					ptp_debug (params, "ptp2/mtpfast: storageid has type 0x%x???", xpl->datatype);
4908					break;
4909				}
4910				oinfo.StorageID = xpl->propval.u32;
4911				ptp_debug (params, "ptp2/mtpfast: storageid 0x%x", xpl->propval.u32);
4912				break;
4913			case PTP_OPC_ProtectionStatus:/*UINT16*/
4914				if (xpl->datatype != PTP_DTC_UINT16) {
4915					ptp_debug (params, "ptp2/mtpfast: protectionstatus has type 0x%x???", xpl->datatype);
4916					break;
4917				}
4918				oinfo.ProtectionStatus = xpl->propval.u16;
4919				ptp_debug (params, "ptp2/mtpfast: protection 0x%x", xpl->propval.u16);
4920				break;
4921			case PTP_OPC_ObjectFileName:
4922				if (xpl->datatype != PTP_DTC_STR) {
4923					ptp_debug (params, "ptp2/mtpfast: filename has type 0x%x???", xpl->datatype);
4924					break;
4925				}
4926				if (xpl->propval.str) {
4927					ptp_debug (params, "ptp2/mtpfast: filename %s", xpl->propval.str);
4928					oinfo.Filename = strdup(xpl->propval.str);
4929				} else {
4930					oinfo.Filename = NULL;
4931				}
4932				break;
4933			case PTP_OPC_DateCreated:
4934				if (xpl->datatype != PTP_DTC_STR) {
4935					ptp_debug (params, "ptp2/mtpfast: datecreated has type 0x%x???", xpl->datatype);
4936					break;
4937				}
4938				ptp_debug (params, "ptp2/mtpfast: capturedate %s", xpl->propval.str);
4939				oinfo.CaptureDate = ptp_unpack_PTPTIME (xpl->propval.str);
4940				break;
4941			case PTP_OPC_DateModified:
4942				if (xpl->datatype != PTP_DTC_STR) {
4943					ptp_debug (params, "ptp2/mtpfast: datemodified has type 0x%x???", xpl->datatype);
4944					break;
4945				}
4946				ptp_debug (params, "ptp2/mtpfast: moddate %s", xpl->propval.str);
4947				oinfo.ModificationDate = ptp_unpack_PTPTIME (xpl->propval.str);
4948				break;
4949			default:
4950				if ((xpl->property & 0xfff0) == 0xdc00)
4951					ptp_debug (params, "ptp2/mtpfast:case %x type %x unhandled", xpl->property, xpl->datatype);
4952				break;
4953			}
4954		}
4955		if (!oinfo.Filename)
4956			/* i have one such file on my Creative */
4957			oinfo.Filename = strdup("<null>");
4958#endif
4959		ob->flags |= PTPOBJECT_MTPPROPLIST_LOADED;
4960fallback:	;
4961	}
4962	if ((ob->flags & want) == want)
4963		return PTP_RC_OK;
4964	ptp_debug (params, "ptp_object_want: oid 0x%08x, want flags %x, have only %x?", handle, want, ob->flags);
4965	return PTP_RC_GeneralError;
4966}
4967
4968
4969uint16_t
4970ptp_add_object_to_cache(PTPParams *params, uint32_t handle)
4971{
4972	PTPObject *ob;
4973	return ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED|PTPOBJECT_MTPPROPLIST_LOADED, &ob);
4974}
4975