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 
57 static uint16_t ptp_exit_recv_memory_handler (PTPDataHandler*,unsigned char**,unsigned long*);
58 static uint16_t ptp_init_recv_memory_handler(PTPDataHandler*);
59 static uint16_t ptp_init_send_memory_handler(PTPDataHandler*,unsigned char*,unsigned long len);
60 static uint16_t ptp_exit_send_memory_handler (PTPDataHandler *handler);
61 
62 static void
ptp_debug(PTPParams * params,const char * format,...)63 ptp_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 
79 static void
ptp_error(PTPParams * params,const char * format,...)80 ptp_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  **/
136 static uint16_t
ptp_transaction_new(PTPParams * params,PTPContainer * ptp,uint16_t flags,unsigned int sendlen,PTPDataHandler * handler)137 ptp_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 */
206 typedef struct {
207 	unsigned char	*data;
208 	unsigned long	size, curoff;
209 } PTPMemHandlerPrivate;
210 
211 static uint16_t
memory_getfunc(PTPParams * params,void * private,unsigned long wantlen,unsigned char * data,unsigned long * gotlen)212 memory_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 
227 static uint16_t
memory_putfunc(PTPParams * params,void * private,unsigned long sendlen,unsigned char * data,unsigned long * putlen)228 memory_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. */
245 static uint16_t
ptp_init_recv_memory_handler(PTPDataHandler * handler)246 ptp_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  */
261 static uint16_t
ptp_init_send_memory_handler(PTPDataHandler * handler,unsigned char * data,unsigned long len)262 ptp_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 */
279 static uint16_t
ptp_exit_send_memory_handler(PTPDataHandler * handler)280 ptp_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 */
288 static uint16_t
ptp_exit_recv_memory_handler(PTPDataHandler * handler,unsigned char ** data,unsigned long * size)289 ptp_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 */
300 typedef struct {
301 	int fd;
302 } PTPFDHandlerPrivate;
303 
304 static uint16_t
fd_getfunc(PTPParams * params,void * private,unsigned long wantlen,unsigned char * data,unsigned long * gotlen)305 fd_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 
320 static uint16_t
fd_putfunc(PTPParams * params,void * private,unsigned long sendlen,unsigned char * data,unsigned long * putlen)321 fd_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 
336 static uint16_t
ptp_init_fd_handler(PTPDataHandler * handler,int fd)337 ptp_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 
347 static uint16_t
ptp_exit_fd_handler(PTPDataHandler * handler)348 ptp_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 */
355 static uint16_t
ptp_transaction(PTPParams * params,PTPContainer * ptp,uint16_t flags,unsigned int sendlen,unsigned char ** data,unsigned int * recvlen)356 ptp_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  **/
406 uint16_t
ptp_getdeviceinfo(PTPParams * params,PTPDeviceInfo * deviceinfo)407 ptp_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 
428 uint16_t
ptp_canon_eos_getdeviceinfo(PTPParams * params,PTPCanonEOSDeviceInfo * di)429 ptp_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  **/
461 uint16_t
ptp_generic_no_data(PTPParams * params,uint16_t code,unsigned int n_param,...)462 ptp_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  **/
492 uint16_t
ptp_opensession(PTPParams * params,uint32_t session)493 ptp_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  **/
529 void
ptp_free_params(PTPParams * params)530 ptp_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  **/
549 uint16_t
ptp_getstorageids(PTPParams * params,PTPStorageIDs * storageids)550 ptp_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  **/
577 uint16_t
ptp_getstorageinfo(PTPParams * params,uint32_t storageid,PTPStorageInfo * storageinfo)578 ptp_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  **/
611 uint16_t
ptp_getobjecthandles(PTPParams * params,uint32_t storage,uint32_t objectformatcode,uint32_t associationOH,PTPObjectHandles * objecthandles)612 ptp_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  **/
662 uint16_t
ptp_getnumobjects(PTPParams * params,uint32_t storage,uint32_t objectformatcode,uint32_t associationOH,uint32_t * numobs)663 ptp_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  **/
698 uint16_t
ptp_getobjectinfo(PTPParams * params,uint32_t handle,PTPObjectInfo * objectinfo)699 ptp_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  **/
729 uint16_t
ptp_getobject(PTPParams * params,uint32_t handle,unsigned char ** object)730 ptp_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  **/
754 uint16_t
ptp_getobject_to_handler(PTPParams * params,uint32_t handle,PTPDataHandler * handler)755 ptp_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  **/
777 uint16_t
ptp_getobject_tofd(PTPParams * params,uint32_t handle,int fd)778 ptp_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  **/
807 uint16_t
ptp_getpartialobject(PTPParams * params,uint32_t handle,uint32_t offset,uint32_t maxbytes,unsigned char ** object)808 ptp_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  **/
835 uint16_t
ptp_getthumb(PTPParams * params,uint32_t handle,unsigned char ** object)836 ptp_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  **/
858 uint16_t
ptp_deleteobject(PTPParams * params,uint32_t handle,uint32_t ofc)859 ptp_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  **/
896 uint16_t
ptp_sendobjectinfo(PTPParams * params,uint32_t * store,uint32_t * parenthandle,uint32_t * handle,PTPObjectInfo * objectinfo)897 ptp_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  */
932 uint16_t
ptp_sendobject(PTPParams * params,unsigned char * object,uint32_t size)933 ptp_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  **/
955 uint16_t
ptp_sendobject_from_handler(PTPParams * params,PTPDataHandler * handler,uint32_t size)956 ptp_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  **/
978 uint16_t
ptp_sendobject_fromfd(PTPParams * params,int fd,uint32_t size)979 ptp_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 
995 uint16_t
ptp_getdevicepropdesc(PTPParams * params,uint16_t propcode,PTPDevicePropDesc * devicepropertydesc)996 ptp_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 
1016 uint16_t
ptp_getdevicepropvalue(PTPParams * params,uint16_t propcode,PTPPropertyValue * value,uint16_t datatype)1017 ptp_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 
1038 uint16_t
ptp_setdevicepropvalue(PTPParams * params,uint16_t propcode,PTPPropertyValue * value,uint16_t datatype)1039 ptp_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  **/
1075 uint16_t
ptp_ek_sendfileobjectinfo(PTPParams * params,uint32_t * store,uint32_t * parenthandle,uint32_t * handle,PTPObjectInfo * objectinfo)1076 ptp_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  */
1111 uint16_t
ptp_ek_getserial(PTPParams * params,unsigned char ** data,unsigned int * size)1112 ptp_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  */
1133 uint16_t
ptp_ek_setserial(PTPParams * params,unsigned char * data,unsigned int size)1134 ptp_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 */
1145 uint16_t
ptp_ek_9007(PTPParams * params,unsigned char ** data,unsigned int * size)1146 ptp_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 */
1157 uint16_t
ptp_ek_9009(PTPParams * params,uint32_t * p1,uint32_t * p2)1158 ptp_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 */
1173 uint16_t
ptp_ek_900c(PTPParams * params,unsigned char ** data,unsigned int * size)1174 ptp_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  */
1195 uint16_t
ptp_ek_settext(PTPParams * params,PTPEKTextParams * text)1196 ptp_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  */
1224 uint16_t
ptp_ek_sendfileobject(PTPParams * params,unsigned char * object,uint32_t size)1225 ptp_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  */
1247 uint16_t
ptp_ek_sendfileobject_from_handler(PTPParams * params,PTPDataHandler * handler,uint32_t size)1248 ptp_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  **/
1284 uint16_t
ptp_canon_getpartialobjectinfo(PTPParams * params,uint32_t handle,uint32_t p2,uint32_t * size,uint32_t * rp2)1285 ptp_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  **/
1312 uint16_t
ptp_canon_get_mac_address(PTPParams * params,unsigned char ** mac)1313 ptp_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  **/
1337 uint16_t
ptp_canon_get_directory(PTPParams * params,PTPObjectHandles * handles,PTPObjectInfo ** oinfos,uint32_t ** flags)1338 ptp_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  **/
1371 uint16_t
ptp_canon_gettreeinfo(PTPParams * params,uint32_t * out)1372 ptp_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  **/
1397 uint16_t
ptp_canon_getpairinginfo(PTPParams * params,uint32_t nr,unsigned char ** data,unsigned int * size)1398 ptp_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  **/
1427 uint16_t
ptp_canon_gettreesize(PTPParams * params,PTPCanon_directtransfer_entry ** entries,unsigned int * cnt)1428 ptp_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  **/
1475 uint16_t
ptp_canon_checkevent(PTPParams * params,PTPContainer * event,int * isevent)1476 ptp_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 
1499 uint16_t
ptp_check_event(PTPParams * params)1500 ptp_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 
1539 store_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 
1554 int
ptp_get_one_event(PTPParams * params,PTPContainer * event)1555 ptp_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  **/
1577 uint16_t
ptp_canon_eos_getevent(PTPParams * params,PTPCanon_changes_entry ** entries,int * nrofentries)1578 ptp_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 
1596 uint16_t
ptp_canon_eos_getdevicepropdesc(PTPParams * params,uint16_t propcode,PTPDevicePropDesc * dpd)1597 ptp_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 
1625 uint16_t
ptp_canon_eos_getstorageids(PTPParams * params,PTPStorageIDs * storageids)1626 ptp_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 
1642 uint16_t
ptp_canon_eos_getstorageinfo(PTPParams * params,uint32_t p1)1643 ptp_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  */
1675 uint16_t
ptp_canon_eos_getpartialobject(PTPParams * params,uint32_t oid,uint32_t offset,uint32_t xsize,unsigned char ** data)1676 ptp_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 
1691 uint16_t
ptp_canon_eos_setdevicepropvalueex(PTPParams * params,unsigned char * data,unsigned int size)1692 ptp_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 
1702 uint16_t
ptp_canon_eos_setdevicepropvalue(PTPParams * params,uint16_t propcode,PTPPropertyValue * value,uint16_t datatype)1703 ptp_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  **/
1790 uint16_t
ptp_canon_getpartialobject(PTPParams * params,uint32_t handle,uint32_t offset,uint32_t size,uint32_t pos,unsigned char ** block,uint32_t * readnum)1791 ptp_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  **/
1833 uint16_t
ptp_canon_getviewfinderimage(PTPParams * params,unsigned char ** image,uint32_t * size)1834 ptp_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  **/
1865 uint16_t
ptp_canon_getchanges(PTPParams * params,uint16_t ** props,uint32_t * propnum)1866 ptp_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  **/
1907 uint16_t
ptp_canon_getobjectinfo(PTPParams * params,uint32_t store,uint32_t p2,uint32_t parent,uint32_t handle,PTPCANONFolderEntry ** entries,uint32_t * entnum)1908 ptp_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  **/
1960 uint16_t
ptp_canon_get_objecthandle_by_name(PTPParams * params,char * name,uint32_t * objectid)1961 ptp_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  **/
1995 uint16_t
ptp_canon_get_customize_data(PTPParams * params,uint32_t themenr,unsigned char ** data,unsigned int * size)1996 ptp_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 
2011 uint16_t
ptp_nikon_curve_download(PTPParams * params,unsigned char ** data,unsigned int * size)2012 ptp_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  **/
2034 uint16_t
ptp_nikon_get_vendorpropcodes(PTPParams * params,uint16_t ** props,unsigned int * size)2035 ptp_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 
2052 uint16_t
ptp_nikon_getfileinfoinblock(PTPParams * params,uint32_t p1,uint32_t p2,uint32_t p3,unsigned char ** data,unsigned int * size)2053 ptp_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  **/
2079 uint16_t
ptp_nikon_get_liveview_image(PTPParams * params,unsigned char ** data,unsigned int * size)2080 ptp_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  **/
2100 uint16_t
ptp_nikon_get_preview_image(PTPParams * params,unsigned char ** xdata,unsigned int * xsize,uint32_t * handle)2101 ptp_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  **/
2128 uint16_t
ptp_canon_eos_get_viewfinder_image(PTPParams * params,unsigned char ** data,unsigned int * size)2129 ptp_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  **/
2152 uint16_t
ptp_nikon_check_event(PTPParams * params,PTPContainer ** event,int * evtcnt)2153 ptp_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  **/
2184 uint16_t
ptp_nikon_getptpipinfo(PTPParams * params,unsigned char ** data,unsigned int * size)2185 ptp_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  **/
2205 uint16_t
ptp_nikon_getwifiprofilelist(PTPParams * params)2206 ptp_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  **/
2305 uint16_t
ptp_nikon_writewifiprofile(PTPParams * params,PTPNIKONWifiProfile * profile)2306 ptp_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  **/
2406 uint16_t
ptp_mtp_getobjectpropssupported(PTPParams * params,uint16_t ofc,uint32_t * propnum,uint16_t ** props)2407 ptp_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  **/
2438 uint16_t
ptp_mtp_getobjectpropdesc(PTPParams * params,uint16_t opc,uint16_t ofc,PTPObjectPropDesc * opd)2439 ptp_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  **/
2471 uint16_t
ptp_mtp_getobjectpropvalue(PTPParams * params,uint32_t oid,uint16_t opc,PTPPropertyValue * value,uint16_t datatype)2472 ptp_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  **/
2506 uint16_t
ptp_mtp_setobjectpropvalue(PTPParams * params,uint32_t oid,uint16_t opc,PTPPropertyValue * value,uint16_t datatype)2507 ptp_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 
2527 uint16_t
ptp_mtp_getobjectreferences(PTPParams * params,uint32_t handle,uint32_t ** ohArray,uint32_t * arraylen)2528 ptp_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 
2554 uint16_t
ptp_mtp_setobjectreferences(PTPParams * params,uint32_t handle,uint32_t * ohArray,uint32_t arraylen)2555 ptp_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 
2572 uint16_t
ptp_mtp_getobjectproplist(PTPParams * params,uint32_t handle,MTPProperties ** props,int * nrofprops)2573 ptp_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 
2595 uint16_t
ptp_mtp_sendobjectproplist(PTPParams * params,uint32_t * store,uint32_t * parenthandle,uint32_t * handle,uint16_t objecttype,uint64_t objectsize,MTPProperties * props,int nrofprops)2596 ptp_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 
2624 uint16_t
ptp_mtp_setobjectproplist(PTPParams * params,MTPProperties * props,int nrofprops)2625 ptp_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 
2646 int
ptp_operation_issupported(PTPParams * params,uint16_t operation)2647 ptp_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 
2659 int
ptp_event_issupported(PTPParams * params,uint16_t event)2660 ptp_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 
2672 int
ptp_property_issupported(PTPParams * params,uint16_t property)2673 ptp_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 */
2684 void
ptp_free_devicepropvalue(uint16_t dt,PTPPropertyValue * dpd)2685 ptp_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 
2709 void
ptp_free_devicepropdesc(PTPDevicePropDesc * dpd)2710 ptp_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 
2731 void
ptp_free_objectpropdesc(PTPObjectPropDesc * opd)2732 ptp_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 
2765 void
ptp_free_objectinfo(PTPObjectInfo * oi)2766 ptp_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 
2773 void
ptp_free_object(PTPObject * ob)2774 ptp_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 
2785 void
ptp_perror(PTPParams * params,uint16_t error)2786 ptp_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 
2846 const char*
ptp_get_property_description(PTPParams * params,uint16_t dpc)2847 ptp_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 
3494 static int64_t
_value_to_num(PTPPropertyValue * data,uint16_t dt)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 
3538 int
ptp_render_property_value(PTPParams * params,uint16_t dpc,PTPDevicePropDesc * dpd,int length,char * out)3539 ptp_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 
4177 struct {
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 
4213 struct {
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 
4274 int
ptp_render_ofc(PTPParams * params,uint16_t ofc,int spaceleft,char * txt)4275 ptp_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 
4313 struct {
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 
4348 struct {
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 
4408 int
ptp_render_opcode(PTPParams * params,uint16_t opcode,int spaceleft,char * txt)4409 ptp_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 
4432 struct {
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 
4606 int
ptp_render_mtp_propname(uint16_t propid,int spaceleft,char * txt)4607 ptp_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  */
4618 MTPProperties *
ptp_get_new_object_prop_entry(MTPProperties ** props,int * nrofprops)4619 ptp_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 
4641 void
ptp_destroy_object_prop(MTPProperties * prop)4642 ptp_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 
4657 void
ptp_destroy_object_prop_list(MTPProperties * props,int nrofprops)4658 ptp_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  */
4672 MTPProperties *
ptp_find_object_prop_in_cache(PTPParams * params,uint32_t const handle,uint32_t const attribute_id)4673 ptp_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 
4692 void
ptp_remove_object_from_cache(PTPParams * params,uint32_t handle)4693 ptp_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 
_cmp_ob(const void * a,const void * b)4713 static 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 
4720 void
ptp_objects_sort(PTPParams * params)4721 ptp_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!  */
4726 uint16_t
ptp_object_find(PTPParams * params,uint32_t handle,PTPObject ** retob)4727 ptp_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!  */
4738 uint16_t
ptp_object_find_or_insert(PTPParams * params,uint32_t handle,PTPObject ** retob)4739 ptp_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 
4799 uint16_t
ptp_object_want(PTPParams * params,uint32_t handle,int want,PTPObject ** retob)4800 ptp_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;
4960 fallback:	;
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 
4969 uint16_t
ptp_add_object_to_cache(PTPParams * params,uint32_t handle)4970 ptp_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