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