Home | History | Annotate | Download | only in src
      1 /* ptp.c
      2  *
      3  * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi (at) ipartners.pl>
      4  * Copyright (C) 2003-2009 Marcus Meissner <marcus (at) jet.franken.de>
      5  * Copyright (C) 2006-2008 Linus Walleij <triad (at) df.lth.se>
      6  * Copyright (C) 2007 Tero Saarni <tero.saarni (at) 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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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*
   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
   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
   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
   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
   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
   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 *
   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
   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
   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 *
   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
   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 
   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
   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
   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
   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
   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
   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