"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/camlibs/ptp2/ptp.c" (14 Feb 2021, 341425 Bytes) of package /linux/privat/libgphoto2-2.5.27.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ptp.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.5.26_vs_2.5.27.

    1 /* ptp.c
    2  *
    3  * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
    4  * Copyright (C) 2003-2019 Marcus Meissner <marcus@jet.franken.de>
    5  * Copyright (C) 2006-2008 Linus Walleij <triad@df.lth.se>
    6  * Copyright (C) 2007 Tero Saarni <tero.saarni@gmail.com>
    7  * Copyright (C) 2009 Axel Waggershauser <awagger@web.de>
    8  *
    9  * This library is free software; you can redistribute it and/or
   10  * modify it under the terms of the GNU Lesser General Public
   11  * License as published by the Free Software Foundation; either
   12  * version 2 of the License, or (at your option) any later version.
   13  *
   14  * This library is distributed in the hope that it will be useful,
   15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   17  * Lesser General Public License for more details.
   18  *
   19  * You should have received a copy of the GNU Lesser General Public
   20  * License along with this library; if not, write to the
   21  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   22  * Boston, MA  02110-1301  USA
   23  */
   24 
   25 #define _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 being ignored (no
  148  * dataphase).
  149  * The memory for a pointer should be preserved by the caller, if data are
  150  * being retreived the appropriate amount of memory is being 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 = NULL;
  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 = NULL;
  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 uint16_t
  499 ptp_getstreaminfo (PTPParams *params, uint32_t streamid, PTPStreamInfo *si)
  500 {
  501     PTPContainer    ptp;
  502     unsigned char   *data = NULL;
  503     unsigned int    size;
  504     int     ret;
  505 
  506     PTP_CNT_INIT(ptp, PTP_OC_GetStreamInfo, streamid);
  507     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
  508     ret = ptp_unpack_StreamInfo(params, data, si, size);
  509     free (data);
  510     if (ret)
  511         return PTP_RC_OK;
  512     else
  513         return PTP_ERROR_IO;
  514 }
  515 
  516 uint16_t
  517 ptp_getstream (PTPParams *params, unsigned char **data, unsigned int *size)
  518 {
  519     PTPContainer    ptp;
  520 
  521     PTP_CNT_INIT(ptp, PTP_OC_GetStream);
  522     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size));
  523     return PTP_RC_OK;
  524 }
  525 
  526 uint16_t
  527 ptp_leica_getstreamdata (PTPParams *params, unsigned char **data, unsigned int *size)
  528 {
  529     PTPContainer    ptp;
  530 
  531     PTP_CNT_INIT(ptp, PTP_OC_LEICA_LEGetStreamData);
  532     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size));
  533     return PTP_RC_OK;
  534 }
  535 
  536 uint16_t
  537 ptp_canon_eos_905f (PTPParams* params, uint32_t x)
  538 {
  539     PTPContainer    ptp;
  540     unsigned char   *data = NULL;
  541     unsigned int    size;
  542 
  543     PTP_CNT_INIT(ptp, 0x905f, x);
  544     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
  545     free (data);
  546     return PTP_RC_OK;
  547 }
  548 
  549 #ifdef HAVE_LIBXML2
  550 static int
  551 traverse_tree (PTPParams *params, int depth, xmlNodePtr node)
  552 {
  553     xmlNodePtr  next;
  554     xmlChar     *xchar;
  555     int     n;
  556     char        *xx;
  557 
  558 
  559     if (!node) return 0;
  560     xx = malloc (depth * 4 + 1);
  561     memset (xx, ' ', depth*4);
  562     xx[depth*4] = 0;
  563 
  564     n = xmlChildElementCount (node);
  565 
  566     next = node;
  567     do {
  568         fprintf(stderr,"%snode %s\n", xx,next->name);
  569         fprintf(stderr,"%selements %d\n", xx,n);
  570         xchar = xmlNodeGetContent (next);
  571         fprintf(stderr,"%scontent %s\n", xx,xchar);
  572         traverse_tree (params, depth+1,xmlFirstElementChild (next));
  573     } while ((next = xmlNextElementSibling (next)));
  574     free (xx);
  575     return PTP_RC_OK;
  576 }
  577 
  578 static int
  579 parse_9301_cmd_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di)
  580 {
  581     xmlNodePtr  next;
  582     int     cnt;
  583 
  584     cnt = 0;
  585     next = xmlFirstElementChild (node);
  586     while (next) {
  587         cnt++;
  588         next = xmlNextElementSibling (next);
  589     }
  590     di->OperationsSupported_len = cnt;
  591     di->OperationsSupported = calloc (cnt,sizeof(di->OperationsSupported[0]));
  592     cnt = 0;
  593     next = xmlFirstElementChild (node);
  594     while (next) {
  595         unsigned int p;
  596 
  597         sscanf((char*)next->name, "c%04x", &p);
  598         ptp_debug( params, "cmd %s / 0x%04x", next->name, p);
  599         di->OperationsSupported[cnt++] = p;
  600         next = xmlNextElementSibling (next);
  601     }
  602     return PTP_RC_OK;
  603 }
  604 
  605 static int
  606 parse_9301_value (PTPParams *params, const char *str, uint16_t type, PTPPropertyValue *propval)
  607 {
  608     switch (type) {
  609     case 6: { /*UINT32*/
  610         unsigned int x;
  611         if (!sscanf(str,"%08x", &x)) {
  612             ptp_debug( params, "could not parse uint32 %s", str);
  613             return PTP_RC_GeneralError;
  614         }
  615         ptp_debug( params, "\t%d", x);
  616         propval->u32 = x;
  617         break;
  618     }
  619     case 5: { /*INT32*/
  620         int x;
  621         if (!sscanf(str,"%08x", &x)) {
  622             ptp_debug( params, "could not parse int32 %s", str);
  623             return PTP_RC_GeneralError;
  624         }
  625         ptp_debug( params, "\t%d", x);
  626         propval->i32 = x;
  627         break;
  628     }
  629     case 4: { /*UINT16*/
  630         unsigned int x;
  631         if (!sscanf(str,"%04x", &x)) {
  632             ptp_debug( params, "could not parse uint16 %s", str);
  633             return PTP_RC_GeneralError;
  634         }
  635         ptp_debug( params, "\t%d", x);
  636         propval->u16 = x;
  637         break;
  638     }
  639     case 3: { /*INT16*/
  640         int x;
  641         if (!sscanf(str,"%04x", &x)) {
  642             ptp_debug( params, "could not parse int16 %s", str);
  643             return PTP_RC_GeneralError;
  644         }
  645         ptp_debug( params, "\t%d", x);
  646         propval->i16 = x;
  647         break;
  648     }
  649     case 2: { /*UINT8*/
  650         unsigned int x;
  651         if (!sscanf(str,"%02x", &x)) {
  652             ptp_debug( params, "could not parse uint8 %s", str);
  653             return PTP_RC_GeneralError;
  654         }
  655         ptp_debug( params, "\t%d", x);
  656         propval->u8 = x;
  657         break;
  658     }
  659     case 1: { /*INT8*/
  660         int x;
  661         if (!sscanf(str,"%02x", &x)) {
  662             ptp_debug( params, "could not parse int8 %s", str);
  663             return PTP_RC_GeneralError;
  664         }
  665         ptp_debug( params, "\t%d", x);
  666         propval->i8 = x;
  667         break;
  668     }
  669     case 65535: { /* string */
  670         int len;
  671 
  672         /* ascii ptp string, 1 byte length, little endian 16 bit chars */
  673         if (sscanf(str,"%02x", &len)) {
  674             int i;
  675             char *xstr = malloc(len+1);
  676             for (i=0;i<len;i++) {
  677                 int xc;
  678                 if (sscanf(str+2+i*4,"%04x", &xc)) {
  679                     int cx;
  680 
  681                     cx = ((xc>>8) & 0xff) | ((xc & 0xff) << 8);
  682                     xstr[i] = cx;
  683                 }
  684                 xstr[len] = 0;
  685             }
  686             ptp_debug( params, "\t%s", xstr);
  687             propval->str = xstr;
  688             break;
  689         }
  690         ptp_debug( params, "string %s not parseable!", str);
  691         return PTP_RC_GeneralError;
  692     }
  693     case 7: /*INT64*/
  694     case 8: /*UINT64*/
  695     case 9: /*INT128*/
  696     case 10: /*UINT128*/
  697     default:
  698         ptp_debug( params, "unhandled data type %d!", type);
  699         return PTP_RC_GeneralError;
  700     }
  701     return PTP_RC_OK;
  702 }
  703 
  704 static int
  705 parse_9301_propdesc (PTPParams *params, xmlNodePtr next, PTPDevicePropDesc *dpd)
  706 {
  707     int type = -1;
  708 
  709     if (!next)
  710         return PTP_RC_GeneralError;
  711 
  712     ptp_debug (params, "parse_9301_propdesc");
  713     dpd->FormFlag   = PTP_DPFF_None;
  714     dpd->GetSet = PTP_DPGS_Get;
  715     do {
  716         if (!strcmp((char*)next->name,"type")) {    /* propdesc.DataType */
  717             if (!sscanf((char*)xmlNodeGetContent (next), "%04x", &type)) {
  718                 ptp_debug( params, "\ttype %s not parseable?",xmlNodeGetContent (next));
  719                 return 0;
  720             }
  721             ptp_debug( params, "type 0x%x", type);
  722             dpd->DataType = type;
  723             continue;
  724         }
  725         if (!strcmp((char*)next->name,"attribute")) {   /* propdesc.GetSet */
  726             int attr;
  727 
  728             if (!sscanf((char*)xmlNodeGetContent (next), "%02x", &attr)) {
  729                 ptp_debug( params, "\tattr %s not parseable",xmlNodeGetContent (next));
  730                 return 0;
  731             }
  732             ptp_debug( params, "attribute 0x%x", attr);
  733             dpd->GetSet = attr;
  734             continue;
  735         }
  736         if (!strcmp((char*)next->name,"default")) { /* propdesc.FactoryDefaultValue */
  737             ptp_debug( params, "default value");
  738             parse_9301_value (params, (char*)xmlNodeGetContent (next), type, &dpd->FactoryDefaultValue);
  739             continue;
  740         }
  741         if (!strcmp((char*)next->name,"value")) {   /* propdesc.CurrentValue */
  742             ptp_debug( params, "current value");
  743             parse_9301_value (params, (char*)xmlNodeGetContent (next), type, &dpd->CurrentValue);
  744             continue;
  745         }
  746         if (!strcmp((char*)next->name,"enum")) {    /* propdesc.FORM.Enum */
  747             int n,i;
  748             char *s;
  749 
  750             ptp_debug( params, "enum");
  751             dpd->FormFlag = PTP_DPFF_Enumeration;
  752             s = (char*)xmlNodeGetContent (next);
  753             n = 0;
  754             do {
  755                 s = strchr(s,' ');
  756                 if (s) s++;
  757                 n++;
  758             } while (s);
  759             dpd->FORM.Enum.NumberOfValues = n;
  760             dpd->FORM.Enum.SupportedValue = calloc (n , sizeof(PTPPropertyValue));
  761             s = (char*)xmlNodeGetContent (next);
  762             i = 0;
  763             do {
  764                 parse_9301_value (params, s, type, &dpd->FORM.Enum.SupportedValue[i]); /* should turn ' ' into \0? */
  765                 i++;
  766                 s = strchr(s,' ');
  767                 if (s) s++;
  768             } while (s && (i<n));
  769             continue;
  770         }
  771         if (!strcmp((char*)next->name,"range")) {   /* propdesc.FORM.Enum */
  772             char *s = (char*)xmlNodeGetContent (next);
  773             dpd->FormFlag = PTP_DPFF_Range;
  774             ptp_debug( params, "range");
  775             parse_9301_value (params, s, type, &dpd->FORM.Range.MinimumValue); /* should turn ' ' into \0? */
  776             s = strchr(s,' ');
  777             if (!s) continue;
  778             s++;
  779             parse_9301_value (params, s, type, &dpd->FORM.Range.MaximumValue); /* should turn ' ' into \0? */
  780             s = strchr(s,' ');
  781             if (!s) continue;
  782             s++;
  783             parse_9301_value (params, s, type, &dpd->FORM.Range.StepSize); /* should turn ' ' into \0? */
  784 
  785             continue;
  786         }
  787         ptp_debug (params, "\tpropdescvar: %s", next->name);
  788         traverse_tree (params, 3, next);
  789     } while ((next = xmlNextElementSibling (next)));
  790     return PTP_RC_OK;
  791 }
  792 
  793 static int
  794 parse_9301_prop_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di)
  795 {
  796     xmlNodePtr  next;
  797     int     cnt;
  798     unsigned int    i;
  799 
  800     cnt = 0;
  801     next = xmlFirstElementChild (node);
  802     while (next) {
  803         cnt++;
  804         next = xmlNextElementSibling (next);
  805     }
  806 
  807     di->DevicePropertiesSupported_len = cnt;
  808     di->DevicePropertiesSupported = calloc (cnt,sizeof(di->DevicePropertiesSupported[0]));
  809     cnt = 0;
  810     next = xmlFirstElementChild (node);
  811     while (next) {
  812         unsigned int p;
  813         PTPDevicePropDesc   dpd;
  814 
  815         sscanf((char*)next->name, "p%04x", &p);
  816         ptp_debug( params, "prop %s / 0x%04x", next->name, p);
  817         parse_9301_propdesc (params, xmlFirstElementChild (next), &dpd);
  818         dpd.DevicePropertyCode = p;
  819         di->DevicePropertiesSupported[cnt++] = p;
  820 
  821         /* add to cache of device propdesc */
  822         for (i=0;i<params->nrofdeviceproperties;i++)
  823             if (params->deviceproperties[i].desc.DevicePropertyCode == p)
  824                 break;
  825         if (i == params->nrofdeviceproperties) {
  826             params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0]));
  827             memset(&params->deviceproperties[i],0,sizeof(params->deviceproperties[0]));
  828             params->nrofdeviceproperties++;
  829         } else {
  830             ptp_free_devicepropdesc (&params->deviceproperties[i].desc);
  831         }
  832         /* FIXME: free old entry */
  833         /* we are not using dpd, so copy it directly to the cache */
  834         time( &params->deviceproperties[i].timestamp);
  835         params->deviceproperties[i].desc = dpd;
  836 
  837         next = xmlNextElementSibling (next);
  838     }
  839     return PTP_RC_OK;
  840 }
  841 
  842 static int
  843 parse_9301_event_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di)
  844 {
  845     xmlNodePtr  next;
  846     int     cnt;
  847 
  848     cnt = 0;
  849     next = xmlFirstElementChild (node);
  850     while (next) {
  851         cnt++;
  852         next = xmlNextElementSibling (next);
  853     }
  854     di->EventsSupported_len = cnt;
  855     di->EventsSupported = calloc (cnt,sizeof(di->EventsSupported[0]));
  856     cnt = 0;
  857     next = xmlFirstElementChild (node);
  858     while (next) {
  859         unsigned int p;
  860 
  861         sscanf((char*)next->name, "e%04x", &p);
  862         ptp_debug( params, "event %s / 0x%04x", next->name, p);
  863         di->EventsSupported[cnt++] = p;
  864         next = xmlNextElementSibling (next);
  865     }
  866     return PTP_RC_OK;
  867 }
  868 
  869 static int
  870 parse_9301_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di)
  871 {
  872     xmlNodePtr  next;
  873 
  874     next = xmlFirstElementChild (node);
  875     while (next) {
  876         if (!strcmp ((char*)next->name, "cmd")) {
  877             parse_9301_cmd_tree (params, next, di);
  878             next = xmlNextElementSibling (next);
  879             continue;
  880         }
  881         if (!strcmp ((char*)next->name, "prop")) {
  882             parse_9301_prop_tree (params, next, di);
  883             next = xmlNextElementSibling (next);
  884             continue;
  885         }
  886         if (!strcmp ((char*)next->name, "event")) {
  887             parse_9301_event_tree (params, next, di);
  888             next = xmlNextElementSibling (next);
  889             continue;
  890         }
  891         fprintf (stderr,"9301: unhandled type %s\n", next->name);
  892         next = xmlNextElementSibling (next);
  893     }
  894     /*traverse_tree (0, node);*/
  895     return PTP_RC_OK;
  896 }
  897 #endif
  898 
  899 uint16_t
  900 ptp_olympus_omd_capture (PTPParams* params)
  901 {
  902     PTPContainer    ptp;
  903     uint16_t    ret;
  904     unsigned int    size = 0;
  905     unsigned char   *buffer = NULL;
  906 
  907 /* these two trigger the capture ... one might be "shutter down", the other "shutter up"? */
  908     PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OMD_Capture, 0x3); // initiate capture
  909     ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
  910     PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OMD_Capture, 0x6); // initiate capture
  911     ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
  912 
  913     usleep(500);
  914 
  915 /* this only fetches changed props */
  916     PTP_CNT_INIT(ptp, 0x9486); /* query changed properties */
  917     ret =  ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &buffer, &size);
  918     free (buffer);
  919     return ret;
  920 }
  921 /**
  922  * ptp_olympus_bulbstart:
  923  * params:  PTPParams*
  924  *
  925  * Starts Olympus Bulb capture.
  926  *
  927  * Return values: Some PTP_RC_* code.
  928  **/
  929 uint16_t
  930 ptp_olympus_omd_bulbstart (PTPParams* params)
  931 {
  932     PTPContainer    ptp;
  933 
  934     PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OMD_Capture, 0x3); // initiate capture
  935     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
  936     if ((ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000))
  937         return ptp.Param1;
  938     return PTP_RC_OK;
  939 }
  940 
  941 
  942 /**
  943  * ptp_olympus_bulbend:
  944  * params:  PTPParams*
  945  *
  946  * Stops Olympus Bulb capture.
  947  *
  948  * Return values: Some PTP_RC_* code.
  949  **/
  950 uint16_t
  951 ptp_olympus_omd_bulbend (PTPParams* params)
  952 {
  953     PTPContainer    ptp;
  954 
  955     PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OMD_Capture, 0x6); // initiate capture
  956     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
  957     if ((ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000))
  958         return ptp.Param1;
  959     return PTP_RC_OK;
  960 }
  961 
  962 uint16_t
  963 ptp_panasonic_liveview_image (PTPParams* params, unsigned char **data, unsigned int *size)
  964 {
  965     PTPContainer    ptp;
  966 
  967     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_LiveviewImage);
  968         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
  969 }
  970 
  971 uint16_t
  972 ptp_olympus_init_pc_mode (PTPParams* params)
  973 {
  974     uint16_t        ret;
  975     PTPPropertyValue    propval;
  976     PTPContainer        event;
  977     int         i;
  978 
  979     ptp_debug (params,"PTP: (Olympus Init) switching to PC mode...");
  980 
  981     propval.u16 = 1;
  982     ret = ptp_setdevicepropvalue (params, 0xD052, &propval, PTP_DTC_UINT16);
  983     usleep(100000);
  984 
  985     for(i = 0; i < 2; i++) {
  986         ptp_debug (params,"PTP: (Olympus Init) checking events...");
  987         /* Just busy loop until the camera is ready again. */
  988         ptp_check_event (params);
  989         if (ptp_get_one_event(params, &event)) break;
  990         usleep(100000);
  991     }
  992 
  993 /*
  994  * 9489 code: sends a list of PTP device properties supported apparently? on E-M1.
  995  * F4 00 00 00  count
  996 02 D0 03 D0 04 D0 05 D0 06 D0 07 D0 08 D0 09 D0 0C D0 0D D0 0E D0 0F D0 10 D0 11 D0 13 D0 14 D0 18 D0 1A D0 1B D0 1C D0 1D D0 1E D0 1F D0 20 D0 21 D0 22 D0 23 D0 24 D0 25 D0 26 D0 27 D0 28 D0 29 D0 2A D0 2B D0 2C D0 2D D0 2E D0 2F D0 30 D0 31 D0 32 D0 33 D0 34 D0 35 D0 36 D0 37 D0 38 D0 39 D0 3A D0 3B D0 3C D0 3D D0 3E D0 3F D0 40 D0 41 D0 42 D0 43 D0 44 D0 45 D0 46 D0 47 D0 48 D0 49 D0 4A D0 4B D0 4C D0 4D D0 4E D0 4F D0 50 D0 51 D0 52 D0 58 D0 59 D0 5F D0 60 D0 61 D0 62 D0 64 D0 65 D0 66 D0 68 D0 69 D0 70 D0 73 D0 67 D0 5A D0 5B D0 63 D0 6A D0 6B D0 6C D0 71 D0 72 D0 7A D0 7B D0 7C D0 7D D0 7F D0 80 D0 81 D0 82 D0 86 D0 87 D0 8B D0 8C D0 8E D0 8F D0 97 D0 9F D0 C4 D0 C5 D0 A2 D0 A3 D0 A4 D0 A6 D0 A7 D0 A8 D0 A9 D0 AA D0 AB D0 AC D0 AD D0 AE D0 B2 D0 B3 D0 B4 D0 B5 D0 B6 D0 B7 D0 B8 D0 B9 D0 BA D0 BC D0 BD D0 BE D0 BF D0 C0 D0 C6 D0 C7 D0 C8 D0 C9 D0 CB D0 CC D0 CD D0 CE D0 CF D0 D0 D0 D1 D0 D2 D0 D3 D0 D4 D0 D5 D0 D6 D0 D7 D0 D8 D0 D9 D0 DA D0 DB D0 DC D0 DD D0 DE D0 E2 D0 E3 D0 E4 D0 E5 D0 E6 D0 E7 D0 E8 D0 E9 D0 EA D0 EC D0 EF D0 F0 D0 F1 D0 F2 D0 F3 D0 F4 D0 F5 D0 F6 D0 F7 D0 F8 D0 F9 D0 FA D0 FB D0 FC D0 FD D0 FE D0 FF D0 00 D1 01 D1 02 D1 03 D1 04 D1 05 D1 06 D1 07 D1 08 D1 09 D1 0A D1 0B D1 0C D1 0D D1 0E D1 0F D1 10 D1 11 D1 12 D1 13 D1 14 D1 15 D1 16 D1 17 D1 18 D1 19 D1 1A D1 1B D1 1C D1 1D D1 1E D1 1F D1 20 D1 51 D1 52 D1 5A D1 24 D1 25 D1 26 D1 27 D1 28 D1 2D D1 2E D1 2F D1 30 D1 31 D1 34 D1 35 D1 36 D1 37 D1 38 D1 39 D1 3A D1
  997  *
  998  * 9486: queries something. gets 00 00 00 00 ... or list of devicepropdesc in standard ptp propdesc format.
  999  * could be some form of "properties changed" query perhaps? (32bit count in front)
 1000  * might only monitor/return properties set by 9489?
 1001  *
 1002  * 948a: seems also be some kind of polling function, returns 32bit 0 if nothing is there. similar to above?
 1003  *       returns properties sent by 94b8.
 1004  *
 1005  * 948b: also sends a list of ptp devprops:
 1006  * 11 00 00 00 53 D0 54 D0 55 D0 56 D0 57 D0 6D D0 5C D0 5D D0 5E D0 74 D0 75 D0 83 D0 84 D0 85 D0 ED D0 79 D0 E1 D0
 1007  * Events: c008: 21 D1 00 00 0F 00 00 00 01 00 00 00
 1008  */
 1009     //ptp_debug (params,"PTP: (Olympus Init) getting response...");
 1010     //gp_port_set_timeout (camera->port, timeout);
 1011     //ret=ptp_transaction(params, &ptp, PTP_DP_RESPONSEONLY, size, &data, NULL);
 1012     //if(data) free(data);
 1013     return ret;
 1014 }
 1015 
 1016 uint16_t
 1017 ptp_olympus_liveview_image (PTPParams* params, unsigned char **data, unsigned int *size)
 1018 {
 1019     PTPContainer    ptp;
 1020     uint32_t    param1 = 1;
 1021 
 1022     PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_GetLiveViewImage, param1);
 1023     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 1024 }
 1025 
 1026 uint16_t
 1027 ptp_olympus_sdram_image (PTPParams* params, unsigned char **data, unsigned int *size)
 1028 {
 1029     PTPContainer    ptp;
 1030 
 1031     PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OMD_GetImage);
 1032     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 1033 }
 1034 
 1035 uint16_t
 1036 ptp_panasonic_9401 (PTPParams* params, uint32_t param1)
 1037 {
 1038         PTPContainer    ptp;
 1039     uint16_t    ret;
 1040     unsigned int    *size = 0;
 1041     unsigned char   *data = NULL;
 1042 
 1043     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_9401, param1);
 1044     ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, size);
 1045     free(data);
 1046     return ret;
 1047 }
 1048 
 1049 /* liveview format query
 1050  * 0d800012 - get imageformats
 1051  * 0d800011 - get current imageformat ?
 1052  */
 1053 uint16_t
 1054 ptp_panasonic_9414_0d800012 (PTPParams* params, PanasonicLiveViewSize **liveviewsizes, unsigned int *nrofliveviewsizes)
 1055 {
 1056         PTPContainer    ptp;
 1057     unsigned int    i;
 1058     unsigned int    size = 0;
 1059     unsigned char   *data = NULL;
 1060     uint32_t    blobsize;
 1061     uint16_t    count;
 1062     uint16_t    structsize;
 1063 
 1064     *nrofliveviewsizes = 0;
 1065     *liveviewsizes = NULL;
 1066 
 1067     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_GetLiveViewParameters, 0x0d800012);
 1068     CHECK_PTP_RC (ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1069 /* return data with the GC9 is:
 1070 
 1071 12 00 80 0d
 1072 1c 00 00 00
 1073 03 00           count
 1074 08 00           structsize
 1075 e0 01 80 02 20 00 1e 00
 1076 d0 02 c0 03 5e 01 1e 00
 1077 c0 03 00 05 bc 02 1e 00
 1078 
 1079  */
 1080     if (size < 8) return PTP_RC_GeneralError;
 1081 
 1082     blobsize = dtoh32a(data+4);
 1083     if (size - 8 < blobsize) {
 1084         ptp_debug (params, "blobsize expected %d, but size is only %d", blobsize, size - 8);
 1085         return PTP_RC_GeneralError;
 1086     }
 1087     if (blobsize < 4) {
 1088         ptp_debug (params, "blobsize expected at least 4, but is only %d", blobsize);
 1089         return PTP_RC_GeneralError;
 1090     }
 1091     count       = dtoh16a (data+8);
 1092     structsize  = dtoh16a (data+10);
 1093     if (structsize != 8) {
 1094         ptp_debug (params, "structsize expected 8, but is %d", structsize);
 1095         return PTP_RC_GeneralError;
 1096     }
 1097     if (count * structsize > blobsize) {
 1098         ptp_debug (params, "%d * %d = %d is larger than %d", count, structsize, count * structsize, blobsize);
 1099         return PTP_RC_GeneralError;
 1100     }
 1101 
 1102     *liveviewsizes = calloc (sizeof(PanasonicLiveViewSize),count);
 1103     for (i = 0;i < count; i++) {
 1104         (*liveviewsizes)[i].height  = dtoh16a (data + 12 + i*structsize);
 1105         (*liveviewsizes)[i].width   = dtoh16a (data + 12 + 2 + i*structsize);
 1106         (*liveviewsizes)[i].x       = dtoh16a (data + 12 + 4 + i*structsize);
 1107         (*liveviewsizes)[i].freq    = dtoh16a (data + 12 + 6 + i*structsize);
 1108     }
 1109     *nrofliveviewsizes = count;
 1110     free(data);
 1111     return PTP_RC_OK;
 1112 }
 1113 
 1114 uint16_t
 1115 ptp_panasonic_9414_0d800011 (PTPParams* params, PanasonicLiveViewSize *liveviewsize)
 1116 {
 1117         PTPContainer    ptp;
 1118     unsigned int    size = 0;
 1119     unsigned char   *data = NULL;
 1120     uint32_t    blobsize;
 1121 
 1122     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_GetLiveViewParameters, 0x0d800011);
 1123     CHECK_PTP_RC (ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1124 /* data is:
 1125 
 1126 11 00 80 0d
 1127 08 00 00 00
 1128 
 1129 e0 01 80 02
 1130 00 00
 1131 1e 00
 1132 
 1133  */
 1134     if (size < 8) return PTP_RC_GeneralError;
 1135 
 1136     blobsize = dtoh32a(data+4);
 1137     if (size - 8 < blobsize) {
 1138         ptp_debug (params, "blobsize expected %d, but size is only %d", blobsize, size - 8);
 1139         return PTP_RC_GeneralError;
 1140     }
 1141     if (blobsize < 8) {
 1142         ptp_debug (params, "blobsize expected at least 8, but is only %d", blobsize);
 1143         return PTP_RC_GeneralError;
 1144     }
 1145     liveviewsize->height    = dtoh16a (data + 8 + 0);
 1146     liveviewsize->width = dtoh16a (data + 8 + 2);
 1147     liveviewsize->x     = dtoh16a (data + 8 + 4);
 1148     liveviewsize->freq  = dtoh16a (data + 8 + 6);
 1149     free(data);
 1150     return PTP_RC_OK;
 1151 }
 1152 
 1153 uint16_t
 1154 ptp_panasonic_9415 (PTPParams* params, PanasonicLiveViewSize *liveviewsize)
 1155 {
 1156         PTPContainer    ptp;
 1157     unsigned char   *data;
 1158     uint16_t    ret;
 1159 
 1160     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_SetLiveViewParameters, 0x0d800011);
 1161 
 1162     data = malloc(16);
 1163     htod32a(data+0 , 0x0d800011);
 1164     htod32a(data+4 , 8);
 1165     htod16a(data+8 , liveviewsize->height);
 1166     htod16a(data+10, liveviewsize->width);
 1167     htod16a(data+12, liveviewsize->x);
 1168     htod16a(data+14, liveviewsize->freq);
 1169 
 1170     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, 16, (unsigned char**)&data, 0);
 1171     free (data);
 1172     return ret;
 1173 }
 1174 
 1175 uint16_t
 1176 ptp_panasonic_setdeviceproperty (PTPParams* params, uint32_t propcode,
 1177             unsigned char *value, uint16_t valuesize)
 1178 {
 1179     PTPContainer    ptp;
 1180     uint16_t    ret;
 1181     unsigned char   *data;
 1182     uint32_t    size = 4 + 4 + valuesize;
 1183 
 1184     data = calloc(size, sizeof(unsigned char));
 1185 
 1186     htod32a(data, propcode); /* memcpy(data, &propcode, 4); */
 1187     htod16a(&data[4], valuesize); /* memcpy(&data[4], &valuesize, 2); */
 1188 
 1189     memcpy(&data[8], value, valuesize); /* perhaps check if one of the DPV packagers work? */
 1190 
 1191     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_SetProperty, propcode);
 1192     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 1193     free(data);
 1194     return ret;
 1195 }
 1196 
 1197 uint16_t
 1198 ptp_panasonic_getdevicepropertysize (PTPParams *params, uint32_t propcode)
 1199 {
 1200     PTPContainer    ptp;
 1201     unsigned char   *data = NULL;
 1202     unsigned int    size = 0;
 1203 
 1204     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_9107, propcode, 0, 0);
 1205     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1206     if (!data) return PTP_RC_GeneralError;
 1207 
 1208     if (size < 4) return PTP_RC_GeneralError;
 1209     uint32_t headerLength       = dtoh32a( (data) + 4 );
 1210     if (size < 4 + 6 * 4) return PTP_RC_GeneralError;
 1211     uint32_t propertyCode       = dtoh32a( (data) + 4 + 6 * 4 );
 1212     if (size < headerLength * 4 + 2 * 4) return PTP_RC_GeneralError;
 1213 
 1214     ptp_debug(params, "header: %lu, code: %lu\n", headerLength, propertyCode);
 1215 
 1216     return PTP_RC_OK;
 1217 }
 1218 
 1219 uint16_t
 1220 ptp_panasonic_manualfocusdrive (PTPParams* params, uint16_t mode)
 1221 {
 1222     PTPContainer    ptp;
 1223     unsigned char   data[10];
 1224     unsigned char   *xdata = data;
 1225     uint32_t    propcode = 0x03010011;
 1226     uint32_t    type = 2;
 1227 
 1228     htod32a(data, propcode);    /* memcpy(data, &propcode, 4); */
 1229     htod32a(&data[4], type);    /* memcpy(&data[4], &type, 4); */
 1230     htod16a(&data[8], mode);    /* memcpy(&data[8], &mode, 2); */
 1231 
 1232     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_ManualFocusDrive, propcode);
 1233     return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, sizeof(data), &xdata, NULL);
 1234 }
 1235 
 1236 uint16_t
 1237 ptp_panasonic_getcapturetarget (PTPParams* params, uint16_t *target)
 1238 {
 1239     PTPContainer    ptp;
 1240     unsigned char   *data;
 1241     unsigned int    size;
 1242 
 1243     *target = 0;
 1244 
 1245     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_GetCaptureTarget, 0x08000090);
 1246     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1247     if (!data) return PTP_RC_GeneralError;
 1248     if (size < 10) return PTP_RC_GeneralError;
 1249     if (dtoh32a(data) != 0x08000091) return PTP_RC_GeneralError;
 1250     if (dtoh32a(data+4) != 2) return PTP_RC_GeneralError;
 1251     *target = dtoh16a(data+8);
 1252     free (data);
 1253     return PTP_RC_OK;
 1254 }
 1255 
 1256 uint16_t
 1257 ptp_panasonic_setcapturetarget (PTPParams* params, uint16_t mode) // mode == 1 == RAM, mode == 0 == SD, 2 = BOTH
 1258 {
 1259     PTPContainer    ptp;
 1260     unsigned char   data[10];
 1261     unsigned char   *xdata = (unsigned char*)data;
 1262 
 1263     htod32a(data,     0x08000091);  /* capturetarget */
 1264     htod32a(&data[4], 2);       /* size */
 1265     htod16a(&data[8], mode);
 1266 
 1267     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_SetCaptureTarget, 0);
 1268     return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, sizeof(data), &xdata, NULL);
 1269 }
 1270 
 1271 uint16_t
 1272 ptp_panasonic_getdevicepropertydesc (PTPParams *params, uint32_t propcode, uint16_t valuesize, uint32_t *currentValue, uint32_t **propertyValueList, uint32_t *propertyValueListLength)
 1273 {
 1274     PTPContainer    ptp;
 1275     unsigned char   *data = NULL;
 1276     unsigned int    size = 0;
 1277     uint16_t    ret = PTP_RC_OK;
 1278     uint32_t    headerLength;
 1279     uint32_t    propertyCode;
 1280     unsigned int    off = 0;
 1281 
 1282     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_ListProperty, propcode, 0, 0);
 1283     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1284     if (!data) return PTP_RC_GeneralError;
 1285     if (size < 8)
 1286         return PTP_RC_GeneralError;
 1287 
 1288     ptp_debug (params, "ptp_panasonic_getdevicepropertydesc 0x%08x", propcode);
 1289     while (off < size) {
 1290         if (off >= size-8) break;
 1291         ptp_debug (params, "propcode 0x%08lx, size %d", dtoh32a(data+off), dtoh32a(data+off+4));
 1292         off += dtoh32a(data+off+4)+8;
 1293     }
 1294 
 1295     headerLength = dtoh32a( (data) + 4 );
 1296     if (size < 4 + 6 * 4)
 1297         return PTP_RC_GeneralError;
 1298 
 1299     propertyCode = dtoh32a( (data) + 4 + 6 * 4 );
 1300     if (size < headerLength * 4 + 2 * 4)
 1301         return PTP_RC_GeneralError;
 1302 
 1303     if(valuesize == 2) {
 1304         *currentValue       = (uint32_t) dtoh16a( (data) + headerLength * 4 + 2 * 4 );
 1305     } else if(valuesize == 4) {
 1306         *currentValue       = dtoh32a( (data) + headerLength * 4 + 2 * 4 );
 1307     } else {
 1308         ptp_debug (params, "unexpected valuesize %d", valuesize);
 1309         return PTP_RC_GeneralError;
 1310     }
 1311     /* Marcus: where is 4*headerLenght coming from ? */
 1312     if (size < headerLength * 4 + 2 * 4 + valuesize) return PTP_RC_GeneralError;
 1313     *propertyValueListLength        = dtoh32a( (data) + headerLength * 4 + 2 * 4 + valuesize);
 1314 
 1315     ptp_debug(params, "header: %lu, code: 0x%lx, value: %lu, count: %lu", headerLength, propertyCode, *currentValue, *propertyValueListLength);
 1316 
 1317     if (size < headerLength * 4 + 3 * 4 + valuesize + (*propertyValueListLength) * valuesize) {
 1318         ptp_debug (params, "size %d vs expected size %d", size, headerLength * 4 + 3 * 4 + valuesize + (*propertyValueListLength) * valuesize);
 1319         return PTP_RC_GeneralError;
 1320     }
 1321 
 1322     *propertyValueList = calloc(*propertyValueListLength, sizeof(uint32_t));
 1323 
 1324     uint16_t i;
 1325     for(i = 0; i < *propertyValueListLength; i++) {
 1326         if(valuesize == 2) {
 1327             (*propertyValueList)[i] = (uint32_t) dtoh16a( (data) + headerLength * 4 + 3 * 4 + valuesize + i * valuesize);
 1328         } else if(valuesize == 4) {
 1329             (*propertyValueList)[i] = dtoh32a( (data) + headerLength * 4 + 3 * 4 + valuesize + i * valuesize);
 1330         }
 1331         //printf("Property: %lu\n", (*propertyValueList)[i]);
 1332     }
 1333 
 1334     free (data);
 1335     return ret;
 1336 }
 1337 
 1338 
 1339 uint16_t
 1340 ptp_panasonic_getdeviceproperty (PTPParams *params, uint32_t propcode, uint16_t *valuesize, uint32_t *currentValue)
 1341 {
 1342     PTPContainer    ptp;
 1343     unsigned char   *data = NULL;
 1344     unsigned int    size = 0;
 1345     uint16_t    ret = PTP_RC_OK;
 1346 
 1347     PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_GetProperty, propcode);
 1348     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1349     if (!data) return PTP_RC_GeneralError;
 1350 
 1351     if(size < 8) return PTP_RC_GeneralError;
 1352     *valuesize = dtoh32a( (data + 4) );
 1353 
 1354     if(size < 8u + (*valuesize)) return PTP_RC_GeneralError;
 1355     if(*valuesize == 4) {
 1356         *currentValue = dtoh32a( (data + 8) );
 1357     } else if(*valuesize == 2) {
 1358         *currentValue = (uint32_t) dtoh16a( (data + 8) );
 1359     } else {
 1360         return PTP_RC_GeneralError;
 1361     }
 1362     //printf("ptp_panasonic_getdeviceproperty: size: %lu, valuesize: %d, currentValue: %lu\n", size, *valuesize, *currentValue);
 1363 
 1364     free (data);
 1365     return ret;
 1366 }
 1367 
 1368 #ifdef HAVE_LIBXML2
 1369 static uint16_t
 1370 ptp_olympus_parse_output_xml(PTPParams* params, char*data, int len, xmlNodePtr *code)
 1371 {
 1372         xmlDocPtr       docin;
 1373         xmlNodePtr      docroot, output, next;
 1374     int         result, xcode;
 1375 
 1376     *code = NULL;
 1377 
 1378         docin = xmlReadMemory ((char*)data, len, "http://gphoto.org/", "utf-8", 0);
 1379         if (!docin) return PTP_RC_GeneralError;
 1380         docroot = xmlDocGetRootElement (docin);
 1381         if (!docroot) {
 1382         xmlFreeDoc (docin);
 1383         return PTP_RC_GeneralError;
 1384     }
 1385 
 1386         if (strcmp((char*)docroot->name,"x3c")) {
 1387                 ptp_debug (params, "olympus: docroot is not x3c, but %s", docroot->name);
 1388         xmlFreeDoc (docin);
 1389                 return PTP_RC_GeneralError;
 1390         }
 1391         if (xmlChildElementCount(docroot) != 1) {
 1392                 ptp_debug (params, "olympus: x3c: expected 1 child, got %ld", xmlChildElementCount(docroot));
 1393         xmlFreeDoc (docin);
 1394                 return PTP_RC_GeneralError;
 1395         }
 1396         output = xmlFirstElementChild (docroot);
 1397         if (strcmp((char*)output->name, "output") != 0) {
 1398                 ptp_debug (params, "olympus: x3c node: expected child 'output', but got %s", (char*)output->name);
 1399         xmlFreeDoc (docin);
 1400                 return PTP_RC_GeneralError;
 1401     }
 1402         next = xmlFirstElementChild (output);
 1403 
 1404     result = PTP_RC_GeneralError;
 1405 
 1406     while (next) {
 1407         if (!strcmp((char*)next->name,"result")) {
 1408             xmlChar  *xchar;
 1409 
 1410             xchar = xmlNodeGetContent (next);
 1411             if (!sscanf((char*)xchar,"%04x",&result))
 1412                 ptp_debug (params, "failed scanning result from %s", xchar);
 1413             ptp_debug (params,  "ptp result is 0x%04x", result);
 1414             next = xmlNextElementSibling (next);
 1415             continue;
 1416         }
 1417         if (sscanf((char*)next->name,"c%x", &xcode)) {
 1418             ptp_debug (params,  "ptp code node found %s", (char*)next->name);
 1419             *code = next;
 1420             next = xmlNextElementSibling (next);
 1421             continue;
 1422         }
 1423         ptp_debug (params, "unhandled node %s", (char*)next->name);
 1424         next = xmlNextElementSibling (next);
 1425     }
 1426 
 1427     if (result != PTP_RC_OK) {
 1428         *code = NULL;
 1429         xmlFreeDoc (docin);
 1430     }
 1431     return result;
 1432 }
 1433 #endif
 1434 
 1435 uint16_t
 1436 ptp_olympus_getdeviceinfo (PTPParams* params, PTPDeviceInfo *di)
 1437 {
 1438 #ifdef HAVE_LIBXML2
 1439     PTPContainer    ptp;
 1440     uint16_t    ret;
 1441     unsigned char   *data = NULL;
 1442     unsigned int    size;
 1443     xmlNodePtr  code;
 1444 
 1445     memset (di, 0, sizeof(PTPDeviceInfo));
 1446 
 1447     PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_GetDeviceInfo);
 1448     ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
 1449     /* TODO: check for error, only parse_output_xml if ret == PTP_RC_OK?
 1450      * where is 'data' going to be deallocated? */
 1451     ret = ptp_olympus_parse_output_xml(params,(char*)data,size,&code);
 1452     if (ret != PTP_RC_OK)
 1453         return ret;
 1454 
 1455     ret = parse_9301_tree (params, code, di);
 1456 
 1457     xmlFreeDoc(code->doc);
 1458     return ret;
 1459 #else
 1460     return PTP_RC_GeneralError;
 1461 #endif
 1462 }
 1463 
 1464 uint16_t
 1465 ptp_olympus_opensession (PTPParams* params, unsigned char**data, unsigned int *len)
 1466 {
 1467     PTPContainer    ptp;
 1468 
 1469     PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OpenSession);
 1470     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, len);
 1471 }
 1472 
 1473 uint16_t
 1474 ptp_olympus_getcameraid (PTPParams* params, unsigned char**data, unsigned int *len)
 1475 {
 1476     PTPContainer    ptp;
 1477 
 1478     PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_GetCameraID);
 1479     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, len);
 1480 }
 1481 
 1482 /**
 1483  * ptp_generic_no_data:
 1484  * params:  PTPParams*
 1485  *      code    PTP OP Code
 1486  *      n_param count of parameters
 1487  *      ... variable argument list ...
 1488  *
 1489  * Emits a generic PTP command without any data transfer.
 1490  *
 1491  * Return values: Some PTP_RC_* code.
 1492  **/
 1493 uint16_t
 1494 ptp_generic_no_data (PTPParams* params, uint16_t code, unsigned int n_param, ...)
 1495 {
 1496     PTPContainer    ptp;
 1497     va_list     args;
 1498     unsigned int    i;
 1499 
 1500     if( n_param > 5 )
 1501         return PTP_ERROR_BADPARAM;
 1502 
 1503     memset(&ptp, 0, sizeof(ptp));
 1504     ptp.Code=code;
 1505     ptp.Nparam=n_param;
 1506 
 1507     va_start(args, n_param);
 1508     for( i=0; i<n_param; ++i )
 1509         (&ptp.Param1)[i] = va_arg(args, uint32_t);
 1510     va_end(args);
 1511 
 1512     return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
 1513 }
 1514 
 1515 /**
 1516  * ptp_opensession:
 1517  * params:  PTPParams*
 1518  *      session         - session number
 1519  *
 1520  * Establishes a new session.
 1521  *
 1522  * Return values: Some PTP_RC_* code.
 1523  **/
 1524 uint16_t
 1525 ptp_opensession (PTPParams* params, uint32_t session)
 1526 {
 1527     PTPContainer    ptp;
 1528     uint16_t    ret;
 1529 
 1530     ptp_debug(params,"PTP: Opening session");
 1531 
 1532     /* SessonID field of the operation dataset should always
 1533        be set to 0 for OpenSession request! */
 1534     params->session_id=0x00000000;
 1535     /* TransactionID should be set to 0 also! */
 1536     params->transaction_id=0x0000000;
 1537     /* zero out response packet buffer */
 1538     params->response_packet = NULL;
 1539     params->response_packet_size = 0;
 1540     /* no split headers */
 1541     params->split_header_data = 0;
 1542 
 1543     PTP_CNT_INIT(ptp, PTP_OC_OpenSession, session);
 1544     ret=ptp_transaction_new(params, &ptp, PTP_DP_NODATA, 0, NULL);
 1545     /* TODO: check for error */
 1546     /* now set the global session id to current session number */
 1547     params->session_id=session;
 1548     return ret;
 1549 }
 1550 
 1551 void
 1552 ptp_free_devicepropvalue(uint16_t dt, PTPPropertyValue* dpd)
 1553 {
 1554     switch (dt) {
 1555     case PTP_DTC_INT8:  case PTP_DTC_UINT8:
 1556     case PTP_DTC_UINT16:    case PTP_DTC_INT16:
 1557     case PTP_DTC_UINT32:    case PTP_DTC_INT32:
 1558     case PTP_DTC_UINT64:    case PTP_DTC_INT64:
 1559     case PTP_DTC_UINT128:   case PTP_DTC_INT128:
 1560         /* Nothing to free */
 1561         break;
 1562     case PTP_DTC_AINT8: case PTP_DTC_AUINT8:
 1563     case PTP_DTC_AUINT16:   case PTP_DTC_AINT16:
 1564     case PTP_DTC_AUINT32:   case PTP_DTC_AINT32:
 1565     case PTP_DTC_AUINT64:   case PTP_DTC_AINT64:
 1566     case PTP_DTC_AUINT128:  case PTP_DTC_AINT128:
 1567         free(dpd->a.v);
 1568         break;
 1569     case PTP_DTC_STR:
 1570         free(dpd->str);
 1571         break;
 1572     }
 1573 }
 1574 
 1575 void
 1576 ptp_free_devicepropdesc(PTPDevicePropDesc* dpd)
 1577 {
 1578     uint16_t i;
 1579 
 1580     ptp_free_devicepropvalue (dpd->DataType, &dpd->FactoryDefaultValue);
 1581     ptp_free_devicepropvalue (dpd->DataType, &dpd->CurrentValue);
 1582     switch (dpd->FormFlag) {
 1583     case PTP_DPFF_Range:
 1584         ptp_free_devicepropvalue (dpd->DataType, &dpd->FORM.Range.MinimumValue);
 1585         ptp_free_devicepropvalue (dpd->DataType, &dpd->FORM.Range.MaximumValue);
 1586         ptp_free_devicepropvalue (dpd->DataType, &dpd->FORM.Range.StepSize);
 1587         break;
 1588     case PTP_DPFF_Enumeration:
 1589         if (dpd->FORM.Enum.SupportedValue) {
 1590             for (i=0;i<dpd->FORM.Enum.NumberOfValues;i++)
 1591                 ptp_free_devicepropvalue (dpd->DataType, dpd->FORM.Enum.SupportedValue+i);
 1592             free (dpd->FORM.Enum.SupportedValue);
 1593         }
 1594     }
 1595     dpd->DataType = PTP_DTC_UNDEF;
 1596     dpd->FormFlag = PTP_DPFF_None;
 1597 }
 1598 
 1599 
 1600 void
 1601 ptp_free_objectpropdesc(PTPObjectPropDesc* opd)
 1602 {
 1603     uint16_t i;
 1604 
 1605     ptp_free_devicepropvalue (opd->DataType, &opd->FactoryDefaultValue);
 1606     switch (opd->FormFlag) {
 1607     case PTP_OPFF_None:
 1608         break;
 1609     case PTP_OPFF_Range:
 1610         ptp_free_devicepropvalue (opd->DataType, &opd->FORM.Range.MinimumValue);
 1611         ptp_free_devicepropvalue (opd->DataType, &opd->FORM.Range.MaximumValue);
 1612         ptp_free_devicepropvalue (opd->DataType, &opd->FORM.Range.StepSize);
 1613         break;
 1614     case PTP_OPFF_Enumeration:
 1615         if (opd->FORM.Enum.SupportedValue) {
 1616             for (i=0;i<opd->FORM.Enum.NumberOfValues;i++)
 1617                 ptp_free_devicepropvalue (opd->DataType, opd->FORM.Enum.SupportedValue+i);
 1618             free (opd->FORM.Enum.SupportedValue);
 1619         }
 1620         break;
 1621     case PTP_OPFF_DateTime:
 1622         free(opd->FORM.DateTime.String);
 1623         break;
 1624     case PTP_OPFF_RegularExpression:
 1625         free(opd->FORM.RegularExpression.String);
 1626         break;
 1627     case PTP_OPFF_FixedLengthArray: /* nothing to free */ /* fallthrough */
 1628     case PTP_OPFF_ByteArray:    /* nothing to free */ /* fallthrough */
 1629     case PTP_OPFF_LongString:
 1630         /* Ignore these presently, we cannot unpack them, so there is nothing to be freed. */
 1631         break;
 1632     default:
 1633         fprintf (stderr, "Unknown OPFF type %d\n", opd->FormFlag);
 1634         break;
 1635     }
 1636 }
 1637 
 1638 
 1639 /**
 1640  * ptp_free_params:
 1641  * params:  PTPParams*
 1642  *
 1643  * Frees all data within the PTPParams struct.
 1644  *
 1645  * Return values: Some PTP_RC_* code.
 1646  **/
 1647 void
 1648 ptp_free_params (PTPParams *params)
 1649 {
 1650     unsigned int i;
 1651 
 1652     free (params->cameraname);
 1653     free (params->wifi_profiles);
 1654     for (i=0;i<params->nrofobjects;i++)
 1655         ptp_free_object (&params->objects[i]);
 1656     free (params->objects);
 1657     free (params->storageids.Storage);
 1658     free (params->events);
 1659     for (i=0;i<params->nrofcanon_props;i++) {
 1660         free (params->canon_props[i].data);
 1661         ptp_free_devicepropdesc (&params->canon_props[i].dpd);
 1662     }
 1663     free (params->canon_props);
 1664     free (params->backlogentries);
 1665 
 1666     for (i=0;i<params->nrofdeviceproperties;i++)
 1667         ptp_free_devicepropdesc (&params->deviceproperties[i].desc);
 1668     free (params->deviceproperties);
 1669 
 1670     ptp_free_DI (&params->deviceinfo);
 1671 }
 1672 
 1673 /**
 1674  * ptp_getststorageids:
 1675  * params:  PTPParams*
 1676  *
 1677  * Gets array of StorageIDs and fills the storageids structure.
 1678  *
 1679  * Return values: Some PTP_RC_* code.
 1680  **/
 1681 uint16_t
 1682 ptp_getstorageids (PTPParams* params, PTPStorageIDs* storageids)
 1683 {
 1684     PTPContainer    ptp;
 1685     unsigned char   *data = NULL;
 1686     unsigned int    size;
 1687 
 1688     PTP_CNT_INIT(ptp, PTP_OC_GetStorageIDs);
 1689     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1690     ptp_unpack_SIDs(params, data, storageids, size);
 1691     free(data);
 1692     return PTP_RC_OK;
 1693 }
 1694 
 1695 /**
 1696  * ptp_getststorageinfo:
 1697  * params:  PTPParams*
 1698  *      storageid       - StorageID
 1699  *
 1700  * Gets StorageInfo dataset of desired storage and fills storageinfo
 1701  * structure.
 1702  *
 1703  * Return values: Some PTP_RC_* code.
 1704  **/
 1705 uint16_t
 1706 ptp_getstorageinfo (PTPParams* params, uint32_t storageid,
 1707             PTPStorageInfo* storageinfo)
 1708 {
 1709     PTPContainer    ptp;
 1710     unsigned char   *data = NULL;
 1711     unsigned int    size;
 1712 
 1713     PTP_CNT_INIT(ptp, PTP_OC_GetStorageInfo, storageid);
 1714     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1715     if (!data || !size)
 1716         return PTP_RC_GeneralError;
 1717     memset(storageinfo, 0, sizeof(*storageinfo));
 1718     if (!ptp_unpack_SI(params, data, storageinfo, size)) {
 1719         free(data);
 1720         return PTP_RC_GeneralError;
 1721     }
 1722     free(data);
 1723     return PTP_RC_OK;
 1724 }
 1725 
 1726 /**
 1727  * ptp_getobjecthandles:
 1728  * params:  PTPParams*
 1729  *      storage         - StorageID
 1730  *      objectformatcode    - ObjectFormatCode (optional)
 1731  *      associationOH       - ObjectHandle of Association for
 1732  *                    which a list of children is desired
 1733  *                    (optional)
 1734  *      objecthandles       - pointer to structute
 1735  *
 1736  * Fills objecthandles with structure returned by device.
 1737  *
 1738  * Return values: Some PTP_RC_* code.
 1739  **/
 1740 uint16_t
 1741 ptp_getobjecthandles (PTPParams* params, uint32_t storage,
 1742             uint32_t objectformatcode, uint32_t associationOH,
 1743             PTPObjectHandles* objecthandles)
 1744 {
 1745     PTPContainer    ptp;
 1746     uint16_t    ret;
 1747     unsigned char   *data = NULL;
 1748     unsigned int    size;
 1749 
 1750     objecthandles->Handler = NULL;
 1751     objecthandles->n = 0;
 1752 
 1753     PTP_CNT_INIT(ptp, PTP_OC_GetObjectHandles, storage, objectformatcode, associationOH);
 1754     ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
 1755     if (ret == PTP_RC_OK) {
 1756         ptp_unpack_OH(params, data, objecthandles, size);
 1757     } else {
 1758         if (    (storage == 0xffffffff) &&
 1759             (objectformatcode == 0) &&
 1760             (associationOH == 0)
 1761         ) {
 1762             /* When we query all object handles on all stores and
 1763              * get an error -> just handle it as "0 handles".
 1764              */
 1765             objecthandles->Handler = NULL;
 1766             objecthandles->n = 0;
 1767             ret = PTP_RC_OK;
 1768         }
 1769     }
 1770     free(data);
 1771     return ret;
 1772 }
 1773 
 1774 uint16_t
 1775 ptp_getfilesystemmanifest (PTPParams* params, uint32_t storage,
 1776     uint32_t objectformatcode, uint32_t associationOH,
 1777         uint64_t *numoifs, PTPObjectFilesystemInfo **oifs
 1778 ) {
 1779     PTPContainer    ptp;
 1780     unsigned int    size = 0;
 1781     unsigned char   *data = NULL;
 1782 
 1783     *oifs = NULL;
 1784     *numoifs = 0;
 1785     PTP_CNT_INIT(ptp, PTP_OC_GetFilesystemManifest, storage, objectformatcode, associationOH);
 1786     CHECK_PTP_RC (ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1787     ptp_unpack_ptp11_manifest (params, data, size, numoifs, oifs);
 1788     return PTP_RC_OK;
 1789 }
 1790 
 1791 /**
 1792  * ptp_getnumobjects:
 1793  * params:  PTPParams*
 1794  *      storage         - StorageID
 1795  *      objectformatcode    - ObjectFormatCode (optional)
 1796  *      associationOH       - ObjectHandle of Association for
 1797  *                    which a list of children is desired
 1798  *                    (optional)
 1799  *      numobs          - pointer to uint32_t that takes number of objects
 1800  *
 1801  * Fills numobs with number of objects on device.
 1802  *
 1803  * Return values: Some PTP_RC_* code.
 1804  **/
 1805 uint16_t
 1806 ptp_getnumobjects (PTPParams* params, uint32_t storage,
 1807             uint32_t objectformatcode, uint32_t associationOH,
 1808             uint32_t* numobs)
 1809 {
 1810     PTPContainer    ptp;
 1811 
 1812     PTP_CNT_INIT(ptp, PTP_OC_GetNumObjects, storage, objectformatcode, associationOH);
 1813     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 1814     if (ptp.Nparam >= 1)
 1815         *numobs = ptp.Param1;
 1816     else
 1817         return PTP_RC_GeneralError;
 1818     return PTP_RC_OK;
 1819 }
 1820 
 1821 /**
 1822  * ptp_eos_bulbstart:
 1823  * params:  PTPParams*
 1824  *
 1825  * Starts EOS Bulb capture.
 1826  *
 1827  * Return values: Some PTP_RC_* code.
 1828  **/
 1829 uint16_t
 1830 ptp_canon_eos_bulbstart (PTPParams* params)
 1831 {
 1832     PTPContainer    ptp;
 1833 
 1834     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_BulbStart);
 1835     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 1836     if ((ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000))
 1837         return ptp.Param1;
 1838     return PTP_RC_OK;
 1839 }
 1840 
 1841 /**
 1842  * ptp_eos_capture:
 1843  * params:  PTPParams*
 1844  *              uint32_t*   result
 1845  *
 1846  * This starts a EOS400D style capture. You have to use the
 1847  * get_eos_events to find out what resulted.
 1848  * The return value is "0" for all OK, and "1" for capture failed. (not fully confirmed)
 1849  *
 1850  * Return values: Some PTP_RC_* code.
 1851  **/
 1852 uint16_t
 1853 ptp_canon_eos_capture (PTPParams* params, uint32_t *result)
 1854 {
 1855     PTPContainer    ptp;
 1856 
 1857     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_RemoteRelease);
 1858     *result = 0;
 1859     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 1860     if (ptp.Nparam >= 1)
 1861         *result = ptp.Param1;
 1862     return PTP_RC_OK;
 1863 }
 1864 
 1865 /**
 1866  * ptp_canon_eos_bulbend:
 1867  * params:  PTPParams*
 1868  *
 1869  * Starts EOS Bulb capture.
 1870  *
 1871  * Return values: Some PTP_RC_* code.
 1872  **/
 1873 uint16_t
 1874 ptp_canon_eos_bulbend (PTPParams* params)
 1875 {
 1876     PTPContainer    ptp;
 1877 
 1878     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_BulbEnd);
 1879     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 1880     if ((ptp.Nparam >= 1) && ((ptp.Param1 & 0x7000) == 0x2000))
 1881         return ptp.Param1;
 1882     return PTP_RC_OK;
 1883 }
 1884 
 1885 /**
 1886  * ptp_getobjectinfo:
 1887  * params:  PTPParams*
 1888  *      handle          - Object handle
 1889  *      objectinfo      - pointer to objectinfo that is returned
 1890  *
 1891  * Get objectinfo structure for handle from device.
 1892  *
 1893  * Return values: Some PTP_RC_* code.
 1894  **/
 1895 uint16_t
 1896 ptp_getobjectinfo (PTPParams* params, uint32_t handle,
 1897             PTPObjectInfo* objectinfo)
 1898 {
 1899     PTPContainer    ptp;
 1900     unsigned char   *data = NULL;
 1901     unsigned int    size;
 1902 
 1903     PTP_CNT_INIT(ptp, PTP_OC_GetObjectInfo, handle);
 1904     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 1905     ptp_unpack_OI(params, data, objectinfo, size);
 1906     free(data);
 1907     return PTP_RC_OK;
 1908 }
 1909 
 1910 /**
 1911  * ptp_getobject:
 1912  * params:  PTPParams*
 1913  *      handle          - Object handle
 1914  *      object          - pointer to data area
 1915  *
 1916  * Get object 'handle' from device and store the data in newly
 1917  * allocated 'object'.
 1918  *
 1919  * Return values: Some PTP_RC_* code.
 1920  **/
 1921 uint16_t
 1922 ptp_getobject (PTPParams* params, uint32_t handle, unsigned char** object)
 1923 {
 1924     PTPContainer ptp;
 1925 
 1926     PTP_CNT_INIT(ptp, PTP_OC_GetObject, handle);
 1927     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, NULL);
 1928 }
 1929 
 1930 /**
 1931  * ptp_getobject_with_size:
 1932  * params:  PTPParams*
 1933  *      handle          - Object handle
 1934  *      object          - pointer to data area
 1935  *      size            - pointer to uint, returns size of object
 1936  *
 1937  * Get object 'handle' from device and store the data in newly
 1938  * allocated 'object'.
 1939  *
 1940  * Return values: Some PTP_RC_* code.
 1941  **/
 1942 uint16_t
 1943 ptp_getobject_with_size (PTPParams* params, uint32_t handle, unsigned char** object, unsigned int *size)
 1944 {
 1945     PTPContainer ptp;
 1946 
 1947     PTP_CNT_INIT(ptp, PTP_OC_GetObject, handle);
 1948     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, size);
 1949 }
 1950 
 1951 /**
 1952  * ptp_getobject_to_handler:
 1953  * params:  PTPParams*
 1954  *      handle          - Object handle
 1955  *      PTPDataHandler*     - pointer datahandler
 1956  *
 1957  * Get object 'handle' from device and store the data in newly
 1958  * allocated 'object'.
 1959  *
 1960  * Return values: Some PTP_RC_* code.
 1961  **/
 1962 uint16_t
 1963 ptp_getobject_to_handler (PTPParams* params, uint32_t handle, PTPDataHandler *handler)
 1964 {
 1965     PTPContainer ptp;
 1966 
 1967     PTP_CNT_INIT(ptp, PTP_OC_GetObject, handle);
 1968     return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler);
 1969 }
 1970 
 1971 /**
 1972  * ptp_getobject_tofd:
 1973  * params:  PTPParams*
 1974  *      handle          - Object handle
 1975  *      fd                      - File descriptor to write() to
 1976  *
 1977  * Get object 'handle' from device and write the data to the
 1978  * given file descriptor.
 1979  *
 1980  * Return values: Some PTP_RC_* code.
 1981  **/
 1982 uint16_t
 1983 ptp_getobject_tofd (PTPParams* params, uint32_t handle, int fd)
 1984 {
 1985     PTPContainer    ptp;
 1986     PTPDataHandler  handler;
 1987     uint16_t    ret;
 1988 
 1989     PTP_CNT_INIT(ptp, PTP_OC_GetObject, handle);
 1990     ptp_init_fd_handler (&handler, fd);
 1991     ret = ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, &handler);
 1992     ptp_exit_fd_handler (&handler);
 1993     return ret;
 1994 }
 1995 
 1996 /**
 1997  * ptp_getpartialobject:
 1998  * params:  PTPParams*
 1999  *      handle          - Object handle
 2000  *      offset          - Offset into object
 2001  *      maxbytes        - Maximum of bytes to read
 2002  *      object          - pointer to data area
 2003  *      len         - pointer to returned length
 2004  *
 2005  * Get object 'handle' from device and store the data in newly
 2006  * allocated 'object'. Start from offset and read at most maxbytes.
 2007  *
 2008  * Return values: Some PTP_RC_* code.
 2009  **/
 2010 uint16_t
 2011 ptp_getpartialobject (PTPParams* params, uint32_t handle, uint32_t offset,
 2012             uint32_t maxbytes, unsigned char** object,
 2013             uint32_t *len)
 2014 {
 2015     PTPContainer ptp;
 2016 
 2017     PTP_CNT_INIT(ptp, PTP_OC_GetPartialObject, handle, offset, maxbytes);
 2018     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len);
 2019 }
 2020 
 2021 /**
 2022  * ptp_getpartialobject_to_handler:
 2023  * params:  PTPParams*
 2024  *      handle          - Object handle
 2025  *      offset          - Offset into object
 2026  *      maxbytes        - Maximum of bytes to read
 2027  *      handler         - a ptp data handler
 2028  *
 2029  * Get object 'handle' from device and send the data to the
 2030  * data handler. Start from offset and read at most maxbytes.
 2031  *
 2032  * Return values: Some PTP_RC_* code.
 2033  **/
 2034 uint16_t
 2035 ptp_getpartialobject_to_handler (PTPParams* params, uint32_t handle, uint32_t offset,
 2036             uint32_t maxbytes, PTPDataHandler *handler)
 2037 {
 2038     PTPContainer ptp;
 2039 
 2040     PTP_CNT_INIT(ptp, PTP_OC_GetPartialObject, handle, offset, maxbytes);
 2041     return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler);
 2042 }
 2043 
 2044 /**
 2045  * ptp_nikon_getpartialobjectex:
 2046  * params:  PTPParams*
 2047  *      handle          - Object handle
 2048  *      offset          - 64bit offset into object
 2049  *      maxbytes        - 64bit maximum of bytes to read
 2050  *      handler         - a ptp pata handler
 2051  *
 2052  * Get object 'handle' from device and send the data to the
 2053  * data handler. Start from offset and read at most maxbytes.
 2054  *
 2055  * Return values: Some PTP_RC_* code.
 2056  **/
 2057 uint16_t
 2058 ptp_nikon_getpartialobjectex (PTPParams* params, uint32_t handle, uint64_t offset,
 2059                 uint64_t maxbytes, unsigned char** object,
 2060                 uint32_t *len)
 2061 {
 2062     PTPContainer ptp;
 2063 
 2064     /* casts due to varargs otherwise pushing 64bit values on the stack */
 2065     PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetPartialObjectEx, handle, ((uint32_t)offset & 0xFFFFFFFF), (uint32_t)(offset >> 32), ((uint32_t)maxbytes & 0xFFFFFFFF), (uint32_t)(maxbytes >> 32));
 2066     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len);
 2067 }
 2068 
 2069 
 2070 /**
 2071  * ptp_getthumb:
 2072  * params:  PTPParams*
 2073  *      handle          - Object handle
 2074  *      object          - pointer to data area
 2075  *
 2076  * Get thumb for object 'handle' from device and store the data in newly
 2077  * allocated 'object'.
 2078  *
 2079  * Return values: Some PTP_RC_* code.
 2080  **/
 2081 uint16_t
 2082 ptp_getthumb (PTPParams* params, uint32_t handle, unsigned char** object, unsigned int *len)
 2083 {
 2084     PTPContainer ptp;
 2085 
 2086     PTP_CNT_INIT(ptp, PTP_OC_GetThumb, handle);
 2087     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len);
 2088 }
 2089 
 2090 /**
 2091  * ptp_nikon_getlargethumb:
 2092  * params:  PTPParams*
 2093  *      handle          - Object handle
 2094  *      object          - pointer to data area
 2095  *
 2096  * Get a large thumb for object 'handle' from device and store the data in newly
 2097  * allocated 'object'. This function is Nikon specific.
 2098  *
 2099  * Return values: Some PTP_RC_* code.
 2100  **/
 2101 uint16_t
 2102 ptp_nikon_getlargethumb (PTPParams* params, uint32_t handle, unsigned char** object, unsigned int *len)
 2103 {
 2104     PTPContainer ptp;
 2105 
 2106     PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetLargeThumb, handle);
 2107     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object, len);
 2108 }
 2109 
 2110 /**
 2111  * ptp_nikon_getobjectsize:
 2112  * params:  PTPParams*
 2113  *      handle          - Object handle
 2114  *      objectsize      - size of object
 2115  *
 2116  * Get the 64bit objectsize for object 'handle' from device and store the size in objectsize
 2117  * allocated 'object'. This function is Nikon specific.
 2118  *
 2119  * Return values: Some PTP_RC_* code.
 2120  **/
 2121 uint16_t
 2122 ptp_nikon_getobjectsize (PTPParams* params, uint32_t handle, uint64_t *objectsize)
 2123 {
 2124     PTPContainer    ptp;
 2125     unsigned char   *data = NULL;
 2126     unsigned int    size = 0;
 2127 
 2128     *objectsize = 0;
 2129 
 2130     PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetObjectSize, handle);
 2131     CHECK_PTP_RC (ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 2132 
 2133     if (size < 8) {
 2134         free (data);
 2135         return PTP_RC_GeneralError;
 2136     }
 2137 
 2138     *objectsize = dtoh64ap(params, data);
 2139     free (data);
 2140     return PTP_RC_OK;
 2141 }
 2142 
 2143 /**
 2144  * ptp_deleteobject:
 2145  * params:  PTPParams*
 2146  *      handle          - object handle
 2147  *      ofc         - object format code (optional)
 2148  *
 2149  * Deletes desired objects.
 2150  *
 2151  * Return values: Some PTP_RC_* code.
 2152  **/
 2153 uint16_t
 2154 ptp_deleteobject (PTPParams* params, uint32_t handle, uint32_t ofc)
 2155 {
 2156     PTPContainer ptp;
 2157 
 2158     PTP_CNT_INIT(ptp, PTP_OC_DeleteObject, handle, ofc);
 2159     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 2160     /* If the object is cached and could be removed, cleanse cache. */
 2161     ptp_remove_object_from_cache(params, handle);
 2162     return PTP_RC_OK;
 2163 }
 2164 
 2165 /**
 2166  * ptp_moveobject:
 2167  * params:  PTPParams*
 2168  *      handle          - source ObjectHandle
 2169  *      storage         - destination StorageID
 2170  *      parent          - destination parent ObjectHandle
 2171  *
 2172  * Move an object to a new location under the specified parent.
 2173  * Note that unlike most calls, 0 must be passed for the parent if the destination
 2174  * is the Storage root.
 2175  *
 2176  * Return values: Some PTP_RC_* code.
 2177  **/
 2178 uint16_t
 2179 ptp_moveobject (PTPParams* params, uint32_t handle, uint32_t storage, uint32_t parent)
 2180 {
 2181     PTPContainer ptp;
 2182 
 2183     PTP_CNT_INIT(ptp, PTP_OC_MoveObject, handle, storage, parent);
 2184     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 2185     /* If the object is cached and could be removed, cleanse cache. */
 2186     ptp_remove_object_from_cache(params, handle);
 2187     return PTP_RC_OK;
 2188 }
 2189 
 2190 /**
 2191  * ptp_copyobject:
 2192  * params:  PTPParams*
 2193  *      handle          - source ObjectHandle
 2194  *      storage         - destination StorageID
 2195  *      parent          - destination parent ObjectHandle
 2196  *
 2197  * Copy an object to a new location under the specified parent.
 2198  * Note that unlike most calls, 0 must be passed for the parent if the destination
 2199  * is the Storage root.
 2200  *
 2201  * Return values: Some PTP_RC_* code.
 2202  **/
 2203 uint16_t
 2204 ptp_copyobject (PTPParams* params, uint32_t handle, uint32_t storage, uint32_t parent)
 2205 {
 2206     PTPContainer ptp;
 2207 
 2208     PTP_CNT_INIT(ptp, PTP_OC_CopyObject, handle, storage, parent);
 2209     return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL);
 2210 }
 2211 
 2212 /**
 2213  * ptp_sendobjectinfo:
 2214  * params:  PTPParams*
 2215  *      uint32_t* store     - destination StorageID on Responder
 2216  *      uint32_t* parenthandle  - Parent ObjectHandle on responder
 2217  *      uint32_t* handle    - see Return values
 2218  *      PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
 2219  *
 2220  * Sends ObjectInfo of file that is to be sent via SendFileObject.
 2221  *
 2222  * Return values: Some PTP_RC_* code.
 2223  * Upon success : uint32_t* store   - Responder StorageID in which
 2224  *                    object will be stored
 2225  *        uint32_t* parenthandle- Responder Parent ObjectHandle
 2226  *                    in which the object will be stored
 2227  *        uint32_t* handle  - Responder's reserved ObjectHandle
 2228  *                    for the incoming object
 2229  **/
 2230 uint16_t
 2231 ptp_sendobjectinfo (PTPParams* params, uint32_t* store,
 2232             uint32_t* parenthandle, uint32_t* handle,
 2233             PTPObjectInfo* objectinfo)
 2234 {
 2235     PTPContainer    ptp;
 2236     uint16_t    ret;
 2237     unsigned char   *data = NULL;
 2238     uint32_t    size;
 2239 
 2240     PTP_CNT_INIT(ptp, PTP_OC_SendObjectInfo, *store, *parenthandle);
 2241     size = ptp_pack_OI(params, objectinfo, &data);
 2242     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 2243     free(data);
 2244     *store=ptp.Param1;
 2245     *parenthandle=ptp.Param2;
 2246     *handle=ptp.Param3;
 2247     return ret;
 2248 }
 2249 
 2250 /**
 2251  * ptp_sendobject:
 2252  * params:  PTPParams*
 2253  *      char*   object      - contains the object that is to be sent
 2254  *      uint64_t size       - object size
 2255  *
 2256  * Sends object to Responder.
 2257  *
 2258  * Return values: Some PTP_RC_* code.
 2259  *
 2260  */
 2261 uint16_t
 2262 ptp_sendobject (PTPParams* params, unsigned char* object, uint64_t size)
 2263 {
 2264     PTPContainer ptp;
 2265 
 2266     PTP_CNT_INIT(ptp, PTP_OC_SendObject);
 2267     return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object, NULL);
 2268 }
 2269 
 2270 /**
 2271  * ptp_sendobject_from_handler:
 2272  * params:  PTPParams*
 2273  *      PTPDataHandler*         - File descriptor to read() object from
 2274  *              uint64_t size           - File/object size
 2275  *
 2276  * Sends object from file descriptor by consecutive reads from this
 2277  * descriptor.
 2278  *
 2279  * Return values: Some PTP_RC_* code.
 2280  **/
 2281 uint16_t
 2282 ptp_sendobject_from_handler (PTPParams* params, PTPDataHandler *handler, uint64_t size)
 2283 {
 2284     PTPContainer ptp;
 2285 
 2286     PTP_CNT_INIT(ptp, PTP_OC_SendObject);
 2287     return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler);
 2288 }
 2289 
 2290 
 2291 /**
 2292  * ptp_sendobject_fromfd:
 2293  * params:  PTPParams*
 2294  *      fd                      - File descriptor to read() object from
 2295  *              uint64_t size           - File/object size
 2296  *
 2297  * Sends object from file descriptor by consecutive reads from this
 2298  * descriptor.
 2299  *
 2300  * Return values: Some PTP_RC_* code.
 2301  **/
 2302 uint16_t
 2303 ptp_sendobject_fromfd (PTPParams* params, int fd, uint64_t size)
 2304 {
 2305     PTPContainer    ptp;
 2306     PTPDataHandler  handler;
 2307     uint16_t    ret;
 2308 
 2309     PTP_CNT_INIT(ptp, PTP_OC_SendObject);
 2310     ptp_init_fd_handler (&handler, fd);
 2311     ret = ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, &handler);
 2312     ptp_exit_fd_handler (&handler);
 2313     return ret;
 2314 }
 2315 
 2316 #define PROPCACHE_TIMEOUT 5 /* seconds */
 2317 
 2318 uint16_t
 2319 ptp_getdevicepropdesc (PTPParams* params, uint16_t propcode,
 2320             PTPDevicePropDesc* devicepropertydesc)
 2321 {
 2322     PTPContainer    ptp;
 2323     uint16_t    ret = PTP_RC_OK;
 2324     unsigned char   *data = NULL;
 2325     unsigned int    size, newoffset;
 2326 
 2327     PTP_CNT_INIT(ptp, PTP_OC_GetDevicePropDesc, propcode);
 2328     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 2329 
 2330     if (!data) {
 2331         ptp_debug (params, "no data received for getdevicepropdesc");
 2332         return PTP_RC_InvalidDevicePropFormat;
 2333     }
 2334 
 2335     if (params->device_flags & DEVICE_FLAG_OLYMPUS_XML_WRAPPED) {
 2336 #ifdef HAVE_LIBXML2
 2337         xmlNodePtr  code;
 2338 
 2339         ret = ptp_olympus_parse_output_xml (params,(char*)data,size,&code);
 2340         if (ret == PTP_RC_OK) {
 2341             int x;
 2342 
 2343             if (    (xmlChildElementCount(code) == 1) &&
 2344                     (!strcmp((char*)code->name,"c1014"))
 2345                     ) {
 2346                 code = xmlFirstElementChild (code);
 2347 
 2348                 if (    (sscanf((char*)code->name,"p%x", &x)) &&
 2349                         (x == propcode)
 2350                         ) {
 2351                     ret = parse_9301_propdesc (params, xmlFirstElementChild (code), devicepropertydesc);
 2352                     xmlFreeDoc(code->doc);
 2353                 }
 2354             }
 2355         } else {
 2356             ptp_debug(params,"failed to parse output xml, ret %x?", ret);
 2357         }
 2358 #endif
 2359     } else {
 2360         if (!ptp_unpack_DPD(params, data, devicepropertydesc, size, &newoffset)) {
 2361             ptp_debug(params,"failed to unpack DPD of propcode 0x%04x, likely corrupted?", propcode);
 2362             free (data);
 2363             return PTP_RC_InvalidDevicePropFormat;
 2364         }
 2365     }
 2366     free(data);
 2367     return ret;
 2368 }
 2369 
 2370 
 2371 uint16_t
 2372 ptp_getdevicepropvalue (PTPParams* params, uint16_t propcode,
 2373             PTPPropertyValue* value, uint16_t datatype)
 2374 {
 2375     PTPContainer    ptp;
 2376     unsigned char   *data = NULL;
 2377     unsigned int    size, offset = 0;
 2378     uint16_t    ret;
 2379 
 2380     PTP_CNT_INIT(ptp, PTP_OC_GetDevicePropValue, propcode);
 2381     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 2382     ret = ptp_unpack_DPV(params, data, &offset, size, value, datatype) ? PTP_RC_OK : PTP_RC_GeneralError;
 2383     if (ret != PTP_RC_OK)
 2384         ptp_debug (params, "ptp_getdevicepropvalue: unpacking DPV failed");
 2385     free(data);
 2386     return ret;
 2387 }
 2388 
 2389 uint16_t
 2390 ptp_setdevicepropvalue (PTPParams* params, uint16_t propcode,
 2391             PTPPropertyValue *value, uint16_t datatype)
 2392 {
 2393     PTPContainer    ptp;
 2394     uint16_t    ret;
 2395     unsigned char   *data = NULL;
 2396     uint32_t    size;
 2397 
 2398     PTP_CNT_INIT(ptp, PTP_OC_SetDevicePropValue, propcode);
 2399     size=ptp_pack_DPV(params, value, &data, datatype);
 2400     ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 2401     free(data);
 2402     return ret;
 2403 }
 2404 
 2405 /**
 2406  * ptp_ek_sendfileobjectinfo:
 2407  * params:  PTPParams*
 2408  *      uint32_t* store     - destination StorageID on Responder
 2409  *      uint32_t* parenthandle  - Parent ObjectHandle on responder
 2410  *      uint32_t* handle    - see Return values
 2411  *      PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
 2412  *
 2413  * Sends ObjectInfo of file that is to be sent via SendFileObject.
 2414  *
 2415  * Return values: Some PTP_RC_* code.
 2416  * Upon success : uint32_t* store   - Responder StorageID in which
 2417  *                    object will be stored
 2418  *        uint32_t* parenthandle- Responder Parent ObjectHandle
 2419  *                    in which the object will be stored
 2420  *        uint32_t* handle  - Responder's reserved ObjectHandle
 2421  *                    for the incoming object
 2422  **/
 2423 uint16_t
 2424 ptp_ek_sendfileobjectinfo (PTPParams* params, uint32_t* store,
 2425             uint32_t* parenthandle, uint32_t* handle,
 2426             PTPObjectInfo* objectinfo)
 2427 {
 2428     PTPContainer    ptp;
 2429     uint16_t    ret;
 2430     unsigned char   *data = NULL;
 2431     uint32_t    size;
 2432 
 2433     PTP_CNT_INIT(ptp, PTP_OC_EK_SendFileObjectInfo, *store, *parenthandle);
 2434     size=ptp_pack_OI(params, objectinfo, &data);
 2435     ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 2436     free(data);
 2437     *store=ptp.Param1;
 2438     *parenthandle=ptp.Param2;
 2439     *handle=ptp.Param3;
 2440     return ret;
 2441 }
 2442 
 2443 /**
 2444  * ptp_ek_getserial:
 2445  * params:  PTPParams*
 2446  *      char**  serial      - contains the serial number of the camera
 2447  *      uint32_t* size      - contains the string length
 2448  *
 2449  * Gets the serial number from the device. (ptp serial)
 2450  *
 2451  * Return values: Some PTP_RC_* code.
 2452  *
 2453  */
 2454 uint16_t
 2455 ptp_ek_getserial (PTPParams* params, unsigned char **data, unsigned int *size)
 2456 {
 2457     PTPContainer ptp;
 2458 
 2459     PTP_CNT_INIT(ptp, PTP_OC_EK_GetSerial);
 2460     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 2461 }
 2462 
 2463 /**
 2464  * ptp_ek_setserial:
 2465  * params:  PTPParams*
 2466  *      char*   serial      - contains the new serial number
 2467  *      uint32_t size       - string length
 2468  *
 2469  * Sets the serial number of the device. (ptp serial)
 2470  *
 2471  * Return values: Some PTP_RC_* code.
 2472  *
 2473  */
 2474 uint16_t
 2475 ptp_ek_setserial (PTPParams* params, unsigned char *data, unsigned int size)
 2476 {
 2477     PTPContainer ptp;
 2478 
 2479     PTP_CNT_INIT(ptp, PTP_OC_EK_SetSerial);
 2480     return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 2481 }
 2482 
 2483 /* unclear what it does yet */
 2484 uint16_t
 2485 ptp_ek_9007 (PTPParams* params, unsigned char **data, unsigned int *size)
 2486 {
 2487     PTPContainer ptp;
 2488 
 2489     PTP_CNT_INIT(ptp, 0x9007);
 2490     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 2491 }
 2492 
 2493 /* unclear what it does yet */
 2494 uint16_t
 2495 ptp_ek_9009 (PTPParams* params, uint32_t *p1, uint32_t *p2)
 2496 {
 2497     PTPContainer    ptp;
 2498 
 2499     PTP_CNT_INIT(ptp, 0x9009);
 2500     *p1 = *p2 = 0;
 2501     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 2502     *p1 = ptp.Param1;
 2503     *p2 = ptp.Param2;
 2504     return PTP_RC_OK;
 2505 }
 2506 
 2507 /* unclear yet, but I guess it returns the info from 9008 */
 2508 uint16_t
 2509 ptp_ek_900c (PTPParams* params, unsigned char **data, unsigned int *size)
 2510 {
 2511     PTPContainer ptp;
 2512 
 2513     PTP_CNT_INIT(ptp, 0x900c);
 2514     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 2515     /* returned data is 16bit,16bit,32bit,32bit */
 2516 }
 2517 
 2518 /**
 2519  * ptp_ek_settext:
 2520  * params:  PTPParams*
 2521  *      PTPEKTextParams*    - contains the texts to display.
 2522  *
 2523  * Displays the specified texts on the TFT of the camera.
 2524  *
 2525  * Return values: Some PTP_RC_* code.
 2526  *
 2527  */
 2528 uint16_t
 2529 ptp_ek_settext (PTPParams* params, PTPEKTextParams *text)
 2530 {
 2531     PTPContainer    ptp;
 2532     uint16_t    ret;
 2533     unsigned char   *data = 0;
 2534     uint32_t    size;
 2535 
 2536     PTP_CNT_INIT(ptp, PTP_OC_EK_SetText);
 2537     if (0 == (size = ptp_pack_EK_text(params, text, &data)))
 2538         return PTP_ERROR_BADPARAM;
 2539     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 2540     free(data);
 2541     return ret;
 2542 }
 2543 
 2544 /**
 2545  * ptp_ek_sendfileobject:
 2546  * params:  PTPParams*
 2547  *      char*   object      - contains the object that is to be sent
 2548  *      uint32_t size       - object size
 2549  *
 2550  * Sends object to Responder.
 2551  *
 2552  * Return values: Some PTP_RC_* code.
 2553  *
 2554  */
 2555 uint16_t
 2556 ptp_ek_sendfileobject (PTPParams* params, unsigned char* object, uint32_t size)
 2557 {
 2558     PTPContainer ptp;
 2559 
 2560     PTP_CNT_INIT(ptp, PTP_OC_EK_SendFileObject);
 2561     return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object, NULL);
 2562 }
 2563 
 2564 /**
 2565  * ptp_ek_sendfileobject_from_handler:
 2566  * params:  PTPParams*
 2567  *      PTPDataHandler* handler - contains the handler of the object that is to be sent
 2568  *      uint32_t size       - object size
 2569  *
 2570  * Sends object to Responder.
 2571  *
 2572  * Return values: Some PTP_RC_* code.
 2573  *
 2574  */
 2575 uint16_t
 2576 ptp_ek_sendfileobject_from_handler (PTPParams* params, PTPDataHandler*handler, uint32_t size)
 2577 {
 2578     PTPContainer ptp;
 2579 
 2580     PTP_CNT_INIT(ptp, PTP_OC_EK_SendFileObject);
 2581     return ptp_transaction_new(params, &ptp, PTP_DP_SENDDATA, size, handler);
 2582 }
 2583 
 2584 /*************************************************************************
 2585  *
 2586  * Canon PTP extensions support
 2587  *
 2588  * (C) Nikolai Kopanygin 2003
 2589  *
 2590  *************************************************************************/
 2591 
 2592 
 2593 /**
 2594  * ptp_canon_getpartialobjectinfo:
 2595  * params:  PTPParams*
 2596  *      uint32_t handle     - ObjectHandle
 2597  *      uint32_t p2         - Not fully understood parameter
 2598  *                    0 - returns full size
 2599  *                    1 - returns thumbnail size (or EXIF?)
 2600  *
 2601  * Gets form the responder the size of the specified object.
 2602  *
 2603  * Return values: Some PTP_RC_* code.
 2604  * Upon success : uint32_t* size    - The object size
 2605  *        uint32_t* rp2     - Still unknown return parameter
 2606  *                                        (perhaps upper 32bit of size)
 2607  *
 2608  *
 2609  **/
 2610 uint16_t
 2611 ptp_canon_getpartialobjectinfo (PTPParams* params, uint32_t handle, uint32_t p2,
 2612             uint32_t* size, uint32_t* rp2)
 2613 {
 2614     PTPContainer    ptp;
 2615 
 2616     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetPartialObjectInfo, handle, p2);
 2617     *size = *rp2 = 0;
 2618     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 2619     *size=ptp.Param1;
 2620     *rp2=ptp.Param2;
 2621     return PTP_RC_OK;
 2622 }
 2623 
 2624 /**
 2625  * ptp_canon_get_mac_address:
 2626  * params:  PTPParams*
 2627  *                    value 0 works.
 2628  * Gets the MAC address of the wireless transmitter.
 2629  *
 2630  * Return values: Some PTP_RC_* code.
 2631  * Upon success : unsigned char* mac    - The MAC address
 2632  *
 2633  **/
 2634 uint16_t
 2635 ptp_canon_get_mac_address (PTPParams* params, unsigned char **mac)
 2636 {
 2637     PTPContainer ptp;
 2638 
 2639         PTP_CNT_INIT(ptp, PTP_OC_CANON_GetMACAddress);
 2640     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, mac, NULL);
 2641 }
 2642 
 2643 /**
 2644  * ptp_canon_get_directory:
 2645  * params:  PTPParams*
 2646 
 2647  * Gets the full directory of the camera.
 2648  *
 2649  * Return values: Some PTP_RC_* code.
 2650  * Upon success : PTPObjectHandles        *handles  - filled out with handles
 2651  *        PTPObjectInfo           **oinfos  - allocated array of PTP Object Infos
 2652  *        uint32_t                **flags   - allocated array of CANON Flags
 2653  *
 2654  **/
 2655 uint16_t
 2656 ptp_canon_get_directory (PTPParams* params,
 2657     PTPObjectHandles    *handles,
 2658     PTPObjectInfo       **oinfos,   /* size(handles->n) */
 2659     uint32_t        **flags     /* size(handles->n) */
 2660 ) {
 2661     PTPContainer    ptp;
 2662     unsigned char   *data = NULL;
 2663     uint16_t    ret;
 2664 
 2665     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetDirectory);
 2666     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL));
 2667     ret = ptp_unpack_canon_directory(params, data, ptp.Param1, handles, oinfos, flags);
 2668     free (data);
 2669     return ret;
 2670 }
 2671 
 2672 /**
 2673  * ptp_canon_gettreeinfo:
 2674  * params:  PTPParams*
 2675  *              uint32_t *out
 2676  *
 2677  * Switches the camera display to on and lets the user
 2678  * select what to transfer. Sends a 0xc011 event when started
 2679  * and 0xc013 if direct transfer aborted.
 2680  *
 2681  * Return values: Some PTP_RC_* code.
 2682  *
 2683  **/
 2684 uint16_t
 2685 ptp_canon_gettreeinfo (PTPParams* params, uint32_t *out)
 2686 {
 2687     PTPContainer    ptp;
 2688 
 2689     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetTreeInfo, 0xf);
 2690     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 2691     if (ptp.Nparam > 0)
 2692         *out = ptp.Param1;
 2693     return PTP_RC_OK;
 2694 }
 2695 
 2696 /**
 2697  * ptp_canon_getpairinginfo:
 2698  * params:  PTPParams*
 2699  *              int nr
 2700  *
 2701  * Get the pairing information.
 2702  *
 2703  * Return values: Some PTP_RC_* code.
 2704  *
 2705  **/
 2706 uint16_t
 2707 ptp_canon_getpairinginfo (PTPParams* params, uint32_t nr, unsigned char **data, unsigned int *size)
 2708 {
 2709     PTPContainer ptp;
 2710 
 2711     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetPairingInfo, nr);
 2712     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 2713 }
 2714 
 2715 /**
 2716  * ptp_canon_get_target_handles:
 2717  * params:  PTPParams*
 2718  *              PTPCanon_directtransfer_entry **out
 2719  *              unsigned int *outsize
 2720  *
 2721  * Retrieves direct transfer entries specifying the images to transfer
 2722  * from the camera (to be retrieved after 0xc011 event).
 2723  *
 2724  * Return values: Some PTP_RC_* code.
 2725  *
 2726  **/
 2727 uint16_t
 2728 ptp_canon_gettreesize (PTPParams* params,
 2729     PTPCanon_directtransfer_entry **entries, unsigned int *cnt)
 2730 {
 2731     PTPContainer    ptp;
 2732     uint16_t    ret = PTP_RC_OK;
 2733     unsigned char   *data = NULL, *cur;
 2734     unsigned int    size, i;
 2735 
 2736     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetTreeSize);
 2737     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 2738     *cnt = dtoh32a(data);
 2739     *entries = calloc(sizeof(PTPCanon_directtransfer_entry),(*cnt));
 2740     if (!*entries) {
 2741         ret = PTP_RC_GeneralError;
 2742         goto exit;
 2743     }
 2744     cur = data+4;
 2745     for (i=0;i<*cnt;i++) {
 2746         unsigned char len;
 2747         (*entries)[i].oid = dtoh32a(cur);
 2748         if (!ptp_unpack_string(params, cur, 4, size-(cur-data-4), &len, &(*entries)[i].str))
 2749             break;
 2750         cur += 4+(cur[4]*2+1);
 2751     }
 2752 exit:
 2753     free (data);
 2754     return ret;
 2755 }
 2756 
 2757 /**
 2758  * ptp_canon_checkevent:
 2759  * params:  PTPParams*
 2760  *
 2761  * The camera has a FIFO stack, in which it accumulates events.
 2762  * Partially these events are communicated also via the USB interrupt pipe
 2763  * according to the PTP USB specification, partially not.
 2764  * This operation returns from the device a block of data, empty,
 2765  * if the event stack is empty, or filled with an event's data otherwise.
 2766  * The event is removed from the stack in the latter case.
 2767  * The Remote Capture app sends this command to the camera all the time
 2768  * of connection, filling with it the gaps between other operations.
 2769  *
 2770  * Return values: Some PTP_RC_* code.
 2771  * Upon success : PTPUSBEventContainer* event   - is filled with the event data
 2772  *                        if any
 2773  *                int *isevent          - returns 1 in case of event
 2774  *                        or 0 otherwise
 2775  **/
 2776 uint16_t
 2777 ptp_canon_checkevent (PTPParams* params, PTPContainer* event, int* isevent)
 2778 {
 2779     PTPContainer    ptp;
 2780     unsigned char   *data = NULL;
 2781     unsigned int    size;
 2782 
 2783     PTP_CNT_INIT(ptp, PTP_OC_CANON_CheckEvent);
 2784     *isevent=0;
 2785     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 2786     if (data && size) { /* check if we had a successful call with data */
 2787         ptp_unpack_EC(params, data, event, size);
 2788         *isevent=1;
 2789         free(data);
 2790     }
 2791     return PTP_RC_OK;
 2792 }
 2793 
 2794 uint16_t
 2795 ptp_add_event (PTPParams *params, PTPContainer *evt)
 2796 {
 2797     params->events = realloc(params->events, sizeof(PTPContainer)*(params->nrofevents+1));
 2798     memcpy (&params->events[params->nrofevents],evt,1*sizeof(PTPContainer));
 2799     params->nrofevents += 1;
 2800     return PTP_RC_OK;
 2801 }
 2802 
 2803 /* CANON EOS fast directory mode */
 2804 /* FIXME: incomplete ... needs storage mode retrieval support too (storage == 0xffffffff) */
 2805 static uint16_t
 2806 ptp_list_folder_eos (PTPParams *params, uint32_t storage, uint32_t handle) {
 2807     unsigned int    k, i, j, last, changed;
 2808     PTPCANONFolderEntry *tmp = NULL;
 2809     unsigned int    nroftmp = 0;
 2810     uint16_t    ret;
 2811     PTPStorageIDs   storageids;
 2812     PTPObject   *ob;
 2813 
 2814     if ((handle != 0xffffffff) && (handle != 0)) {
 2815         ret = ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED, &ob);
 2816         if ((ret == PTP_RC_OK) && (ob->flags & PTPOBJECT_DIRECTORY_LOADED))
 2817             return PTP_RC_OK;
 2818     }
 2819 
 2820     if (storage == 0xffffffff) {
 2821         if (handle != 0xffffffff)
 2822             handle = 0xffffffff;
 2823         ret = ptp_getstorageids(params, &storageids);
 2824         if (ret != PTP_RC_OK)
 2825             return ret;
 2826     } else {
 2827         storageids.n = 1;
 2828         storageids.Storage = malloc(sizeof(storageids.Storage[0]));
 2829         storageids.Storage[0] = storage;
 2830     }
 2831     last = changed = 0;
 2832 
 2833     for (k=0;k<storageids.n;k++) {
 2834         if ((storageids.Storage[k] & 0xffff) == 0) {
 2835             ptp_debug (params, "reading directory, storage 0x%08x skipped (invalid)", storageids.Storage[k]);
 2836             continue;
 2837         }
 2838         ptp_debug (params, "reading handle %08x directory of 0x%08x", storageids.Storage[k], handle);
 2839         tmp = NULL;
 2840         ret = ptp_canon_eos_getobjectinfoex (
 2841               params, storageids.Storage[k], handle ? handle : 0xffffffff, 0x100000, &tmp, &nroftmp);
 2842         if (ret != PTP_RC_OK) {
 2843             ptp_error (params, "error 0x%04x", ret);
 2844             free (storageids.Storage);
 2845             return ret;
 2846         }
 2847         /* convert read entries into objectinfos */
 2848         for (i=0;i<nroftmp;i++) {
 2849             PTPObject   *newobs;
 2850 
 2851             ob = NULL;
 2852             for (j=0;j<params->nrofobjects;j++) {
 2853                 if (params->objects[(last+j)%params->nrofobjects].oid == tmp[i].ObjectHandle)  {
 2854                     ob = &params->objects[(last+j)%params->nrofobjects];
 2855                     break;
 2856                 }
 2857             }
 2858             if (j == params->nrofobjects) {
 2859                 ptp_debug (params, "adding new objectid 0x%08x (nrofobs=%d,j=%d)", tmp[i].ObjectHandle, params->nrofobjects,j);
 2860                 newobs = realloc (params->objects,sizeof(PTPObject)*(params->nrofobjects+1));
 2861                 if (!newobs) {
 2862                     free (tmp);
 2863                     free (storageids.Storage);
 2864                     return PTP_RC_GeneralError;
 2865                 }
 2866                 params->objects = newobs;
 2867                 memset (&params->objects[params->nrofobjects],0,sizeof(params->objects[params->nrofobjects]));
 2868                 params->objects[params->nrofobjects].oid   = tmp[i].ObjectHandle;
 2869                 params->objects[params->nrofobjects].flags = 0;
 2870 
 2871                 params->objects[params->nrofobjects].oi.StorageID = storageids.Storage[k];
 2872                 params->objects[params->nrofobjects].flags |= PTPOBJECT_STORAGEID_LOADED;
 2873                 if (handle == 0xffffffff)
 2874                     params->objects[params->nrofobjects].oi.ParentObject = 0;
 2875                 else
 2876                     params->objects[params->nrofobjects].oi.ParentObject = handle;
 2877                 params->objects[params->nrofobjects].flags |= PTPOBJECT_PARENTOBJECT_LOADED;
 2878                 params->objects[params->nrofobjects].oi.Filename = strdup(tmp[i].Filename);
 2879                 params->objects[params->nrofobjects].oi.ObjectFormat = tmp[i].ObjectFormatCode;
 2880 
 2881                 ptp_debug (params, "   flags %x", tmp[i].Flags);
 2882                 if (tmp[i].Flags & 0x1)
 2883                     params->objects[params->nrofobjects].oi.ProtectionStatus = PTP_PS_ReadOnly;
 2884                 else
 2885                     params->objects[params->nrofobjects].oi.ProtectionStatus = PTP_PS_NoProtection;
 2886                 params->objects[params->nrofobjects].canon_flags = tmp[i].Flags;
 2887                 params->objects[params->nrofobjects].oi.ObjectCompressedSize = tmp[i].ObjectSize;
 2888                 params->objects[params->nrofobjects].oi.CaptureDate = tmp[i].Time;
 2889                 params->objects[params->nrofobjects].oi.ModificationDate = tmp[i].Time;
 2890                 params->objects[params->nrofobjects].flags |= PTPOBJECT_OBJECTINFO_LOADED;
 2891 
 2892                 /*debug_objectinfo(params, tmp[i].ObjectHandle, &params->objects[params->nrofobjects].oi);*/
 2893                 last = params->nrofobjects;
 2894                 params->nrofobjects++;
 2895                 changed = 1;
 2896             } else {
 2897                 ptp_debug (params, "adding old objectid 0x%08x (nrofobs=%d,j=%d)", tmp[i].ObjectHandle, params->nrofobjects,j);
 2898                 ob = &params->objects[(last+j)%params->nrofobjects];
 2899                 /* for speeding up search */
 2900                 last = (last+j)%params->nrofobjects;
 2901                 if (handle != PTP_HANDLER_SPECIAL) {
 2902                     ob->oi.ParentObject = handle;
 2903                     ob->flags |= PTPOBJECT_PARENTOBJECT_LOADED;
 2904                 }
 2905                 if (storageids.Storage[k] != PTP_HANDLER_SPECIAL) {
 2906                     ob->oi.StorageID = storageids.Storage[k];
 2907                     ob->flags |= PTPOBJECT_STORAGEID_LOADED;
 2908                 }
 2909             }
 2910         }
 2911         free (tmp);
 2912     }
 2913     if (changed) ptp_objects_sort (params);
 2914 
 2915     /* Do not cache ob, it might be reallocated and have a new address */
 2916     if (handle != 0xffffffff) {
 2917         ret = ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED, &ob);
 2918         if (ret == PTP_RC_OK)
 2919             ob->flags |= PTPOBJECT_DIRECTORY_LOADED;
 2920     }
 2921     free (storageids.Storage);
 2922     return PTP_RC_OK;
 2923 }
 2924 
 2925 uint16_t
 2926 ptp_list_folder (PTPParams *params, uint32_t storage, uint32_t handle) {
 2927     unsigned int        i, changed, last;
 2928     uint16_t        ret;
 2929     uint32_t        xhandle = handle;
 2930     PTPObject       *newobs;
 2931     PTPObjectHandles    handles;
 2932 
 2933     ptp_debug (params, "(storage=0x%08x, handle=0x%08x)", storage, handle);
 2934     /* handle=0 is only not read when there is no object in the list yet
 2935      * and we do the initial read. */
 2936     if (!handle && params->nrofobjects)
 2937         return PTP_RC_OK;
 2938     /* but we can override this to read 0 object of storages */
 2939     if (handle == PTP_HANDLER_SPECIAL)
 2940         handle = 0;
 2941 
 2942     /* Canon EOS Fast directory strategy */
 2943     if ((params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) &&
 2944         ptp_operation_issupported(params, PTP_OC_CANON_EOS_GetObjectInfoEx)) {
 2945         ret = ptp_list_folder_eos (params, storage, handle);
 2946         if (ret == PTP_RC_OK)
 2947             return ret;
 2948     }
 2949 
 2950     if (handle) { /* 0 is the virtual root */
 2951         PTPObject       *ob;
 2952         /* first check if object itself is loaded, and get its objectinfo. */
 2953         ret = ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED, &ob);
 2954         if (ret != PTP_RC_OK)
 2955             return ret;
 2956         if (ob->oi.ObjectFormat != PTP_OFC_Association)
 2957             return PTP_RC_GeneralError;
 2958         if (ob->flags & PTPOBJECT_DIRECTORY_LOADED) return PTP_RC_OK;
 2959         ob->flags |= PTPOBJECT_DIRECTORY_LOADED;
 2960         /*debug_objectinfo(params, handle, &ob->oi);*/
 2961     }
 2962 
 2963 #if 0 /* apple devices report it, but the conrtent they have does not match the standard somehow. Neesd further debugging */
 2964     if (ptp_operation_issupported(params, PTP_OC_GetFilesystemManifest)) {
 2965         uint64_t        numoifs = 0;
 2966         PTPObjectFilesystemInfo *oifs = NULL;
 2967 
 2968         if (storage == PTP_HANDLER_SPECIAL) storage = 0;
 2969         ret = ptp_getfilesystemmanifest (params, storage, 0, handle, &numoifs, &oifs);
 2970         if (ret != PTP_RC_OK || !numoifs)
 2971             goto fallback;
 2972 
 2973         last = changed = 0;
 2974         for (i=0;i<numoifs;i++) {
 2975             PTPObject   *ob;
 2976             unsigned int    j;
 2977 
 2978             ob = NULL;
 2979             for (j=0;j<params->nrofobjects;j++) {
 2980                 if (params->objects[(last+j)%params->nrofobjects].oid == oifs[i].ObjectHandle)  {
 2981                     ob = &params->objects[(last+j)%params->nrofobjects];
 2982                     break;
 2983                 }
 2984             }
 2985             if (j == params->nrofobjects) {
 2986                 ptp_debug (params, "adding new objectid 0x%08x (nrofobs=%d,j=%d)", oifs[i].ObjectHandle, params->nrofobjects,j);
 2987                 newobs = realloc (params->objects,sizeof(PTPObject)*(params->nrofobjects+1));
 2988                 if (!newobs) {
 2989                     free (oifs);
 2990                     return PTP_RC_GeneralError;
 2991                 }
 2992                 params->objects = newobs;
 2993                 memset (&params->objects[params->nrofobjects],0,sizeof(params->objects[params->nrofobjects]));
 2994                 params->objects[params->nrofobjects].oid = oifs[i].ObjectHandle;
 2995                 params->objects[params->nrofobjects].flags = 0;
 2996                 ob = &params->objects[params->nrofobjects];
 2997                 params->nrofobjects++;
 2998                 changed = 1;
 2999             } else {
 3000                 ptp_debug (params, "adding old objectid 0x%08x (nrofobs=%d,j=%d)", oifs[i].ObjectHandle, params->nrofobjects,j);
 3001                 ob = &params->objects[(last+j)%params->nrofobjects];
 3002                 /* for speeding up search */
 3003                 last = (last+j)%params->nrofobjects;
 3004             }
 3005 
 3006             ob->oi.StorageID        = oifs[i].StorageID;
 3007             ob->oi.ObjectFormat         = oifs[i].ObjectFormat;
 3008             ob->oi.ProtectionStatus     = oifs[i].ProtectionStatus;
 3009             ob->oi.ObjectCompressedSize = oifs[i].ObjectCompressedSize64;
 3010             ob->oi.ParentObject     = oifs[i].ParentObject;
 3011 
 3012             /* bad iOS, returns StorageID instead of 0x0 */
 3013             if (ob->oi.ParentObject == oifs[i].StorageID) {
 3014                 ptp_debug (params, "objectid 0x%08x aka %s has parent %08x, rewriting to 0", oifs[i].ObjectHandle, oifs[i].Filename, oifs[i].ParentObject);
 3015                 ob->oi.ParentObject = 0;
 3016             }
 3017 
 3018             ob->oi.AssociationType      = oifs[i].AssociationType;
 3019             ob->oi.AssociationDesc      = oifs[i].AssociationDesc;
 3020             ob->oi.SequenceNumber       = oifs[i].SequenceNumber;
 3021             ob->oi.Filename         = oifs[i].Filename; /* hand over memory ownership */
 3022             ob->oi.ModificationDate     = oifs[i].ModificationDate;
 3023             /* FIXME: most of it ... but not the image sizes */
 3024             ob->flags           |= PTPOBJECT_OBJECTINFO_LOADED|PTPOBJECT_STORAGEID_LOADED|PTPOBJECT_PARENTOBJECT_LOADED;
 3025         }
 3026         free (oifs);
 3027         if (changed) ptp_objects_sort (params);
 3028         return PTP_RC_OK;
 3029     }
 3030 fallback:
 3031 #endif
 3032 
 3033     ptp_debug (params, "Listing ... ");
 3034     if (handle == 0) xhandle = PTP_HANDLER_SPECIAL; /* 0 would mean all */
 3035     ret = ptp_getobjecthandles (params, storage, 0, xhandle, &handles);
 3036     if (ret == PTP_RC_ParameterNotSupported) {/* try without storage */
 3037         storage = PTP_HANDLER_SPECIAL;
 3038         ret = ptp_getobjecthandles (params, PTP_HANDLER_SPECIAL, 0, xhandle, &handles);
 3039     }
 3040     if (ret == PTP_RC_ParameterNotSupported) { /* fall back to always supported method */
 3041         xhandle = PTP_HANDLER_SPECIAL;
 3042         handle = PTP_HANDLER_SPECIAL;
 3043         ret = ptp_getobjecthandles (params, PTP_HANDLER_SPECIAL, 0, 0, &handles);
 3044     }
 3045     if (ret != PTP_RC_OK)
 3046         return ret;
 3047     last = changed = 0;
 3048     for (i=0;i<handles.n;i++) {
 3049         PTPObject   *ob;
 3050         unsigned int    j;
 3051 
 3052         ob = NULL;
 3053         for (j=0;j<params->nrofobjects;j++) {
 3054             if (params->objects[(last+j)%params->nrofobjects].oid == handles.Handler[i])  {
 3055                 ob = &params->objects[(last+j)%params->nrofobjects];
 3056                 break;
 3057             }
 3058         }
 3059         if (j == params->nrofobjects) {
 3060             ptp_debug (params, "adding new objectid 0x%08x (nrofobs=%d,j=%d)", handles.Handler[i], params->nrofobjects,j);
 3061             newobs = realloc (params->objects,sizeof(PTPObject)*(params->nrofobjects+1));
 3062             if (!newobs) return PTP_RC_GeneralError;
 3063             params->objects = newobs;
 3064             memset (&params->objects[params->nrofobjects],0,sizeof(params->objects[params->nrofobjects]));
 3065             params->objects[params->nrofobjects].oid = handles.Handler[i];
 3066             params->objects[params->nrofobjects].flags = 0;
 3067             /* root directory list files might return all files, so avoid tagging it */
 3068             if (handle != PTP_HANDLER_SPECIAL && handle) {
 3069                 ptp_debug (params, "  parenthandle 0x%08x", handle);
 3070                 if (handles.Handler[i] == handle) { /* EOS bug where oid == parent(oid) */
 3071                     params->objects[params->nrofobjects].oi.ParentObject = 0;
 3072                 } else {
 3073                     params->objects[params->nrofobjects].oi.ParentObject = handle;
 3074                 }
 3075                 params->objects[params->nrofobjects].flags |= PTPOBJECT_PARENTOBJECT_LOADED;
 3076             }
 3077             if (storage != PTP_HANDLER_SPECIAL) {
 3078                 ptp_debug (params, "  storage 0x%08x", storage);
 3079                 params->objects[params->nrofobjects].oi.StorageID = storage;
 3080                 params->objects[params->nrofobjects].flags |= PTPOBJECT_STORAGEID_LOADED;
 3081             }
 3082             params->nrofobjects++;
 3083             changed = 1;
 3084         } else {
 3085             ptp_debug (params, "adding old objectid 0x%08x (nrofobs=%d,j=%d)", handles.Handler[i], params->nrofobjects,j);
 3086             ob = &params->objects[(last+j)%params->nrofobjects];
 3087             /* for speeding up search */
 3088             last = (last+j)%params->nrofobjects;
 3089             if (handle != PTP_HANDLER_SPECIAL) {
 3090                 ob->oi.ParentObject = handle;
 3091                 ob->flags |= PTPOBJECT_PARENTOBJECT_LOADED;
 3092             }
 3093             if (storage != PTP_HANDLER_SPECIAL) {
 3094                 ob->oi.StorageID = storage;
 3095                 ob->flags |= PTPOBJECT_STORAGEID_LOADED;
 3096             }
 3097         }
 3098     }
 3099     free (handles.Handler);
 3100     if (changed) ptp_objects_sort (params);
 3101     return PTP_RC_OK;
 3102 }
 3103 
 3104 
 3105 static void
 3106 handle_event_internal (PTPParams *params, PTPContainer *event)
 3107 {
 3108     /* handle some PTP stack internal events */
 3109     switch (event->Code) {
 3110     case PTP_EC_DevicePropChanged: {
 3111         unsigned int i;
 3112 
 3113         /* mark the property for a forced refresh on the next query */
 3114         for (i=0;i<params->nrofdeviceproperties;i++)
 3115             if (params->deviceproperties[i].desc.DevicePropertyCode == event->Param1) {
 3116                 params->deviceproperties[i].timestamp = 0;
 3117                 break;
 3118             }
 3119         break;
 3120     }
 3121     case PTP_EC_StoreAdded:
 3122     case PTP_EC_StoreRemoved: {
 3123         unsigned int i;
 3124 
 3125         /* FIXME: if we just remove 1 out of many storages, we do not need to invalidate/reload the entire tree? */
 3126 
 3127         /* refetch storage IDs and also invalidate whole object tree */
 3128         free (params->storageids.Storage);
 3129         params->storageids.Storage  = NULL;
 3130         params->storageids.n        = 0;
 3131         ptp_getstorageids (params, &params->storageids);
 3132 
 3133         /* free object storage as it might be associated with the storage ids */
 3134         /* FIXME: enhance and just delete the ones from the storage */
 3135         for (i=0;i<params->nrofobjects;i++)
 3136             ptp_free_object (&params->objects[i]);
 3137         free (params->objects);
 3138         params->objects         = NULL;
 3139         params->nrofobjects         = 0;
 3140 
 3141         params->storagechanged      = 1;
 3142         /* mirror what we do in camera_init, fetch root directory entries. */
 3143         if (params->deviceinfo.VendorExtensionID != PTP_VENDOR_SONY)
 3144             ptp_list_folder (params, PTP_HANDLER_SPECIAL, PTP_HANDLER_SPECIAL);
 3145 
 3146         {
 3147             unsigned int k;
 3148 
 3149             for (k=0;k<params->storageids.n;k++) {
 3150                 if (!(params->storageids.Storage[k] & 0xffff)) continue;
 3151                 if (params->storageids.Storage[k] == 0x80000001) continue;
 3152                 ptp_list_folder (params, params->storageids.Storage[k], PTP_HANDLER_SPECIAL);
 3153             }
 3154         }
 3155 
 3156         break;
 3157     }
 3158     default: /* check if we should handle it internally too */
 3159         break;
 3160     }
 3161 }
 3162 
 3163 uint16_t
 3164 ptp_check_event_queue (PTPParams *params)
 3165 {
 3166     PTPContainer    event;
 3167     uint16_t    ret;
 3168 
 3169     /* We try to do a event check without I/O */
 3170     /* Basically this means just looking at the meanwhile queued events */
 3171 
 3172     ret = params->event_check_queue(params,&event);
 3173 
 3174     if (ret == PTP_RC_OK) {
 3175         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);
 3176         ptp_add_event (params, &event);
 3177         handle_event_internal (params, &event);
 3178     }
 3179     if (ret == PTP_ERROR_TIMEOUT) /* ok, just new events */
 3180         ret = PTP_RC_OK;
 3181     return ret;
 3182 }
 3183 
 3184 uint16_t
 3185 ptp_check_event (PTPParams *params)
 3186 {
 3187     PTPContainer    event;
 3188     uint16_t    ret;
 3189 
 3190     if (params->deviceinfo.VendorExtensionID == PTP_VENDOR_NIKON) {
 3191         if (ptp_operation_issupported(params, PTP_OC_NIKON_GetEventEx)) {
 3192             unsigned int evtcnt = 0, i;
 3193             PTPContainer *xevent = NULL;
 3194 
 3195             ret = ptp_nikon_check_eventex(params, &xevent, &evtcnt);
 3196             if (ret != PTP_RC_OperationNotSupported)
 3197                 CHECK_PTP_RC(ret);
 3198 
 3199             if (evtcnt) {
 3200                 for (i = 0; i < evtcnt; i++)
 3201                     handle_event_internal (params, &xevent[i]);
 3202                 params->events = realloc(params->events, sizeof(PTPContainer)*(evtcnt+params->nrofevents));
 3203                 memcpy (&params->events[params->nrofevents],xevent,evtcnt*sizeof(PTPContainer));
 3204                 params->nrofevents += evtcnt;
 3205                 params->event90c7works = 1;
 3206             }
 3207             free (xevent);
 3208             if (params->event90c7works)
 3209                 return PTP_RC_OK;
 3210             /* fall through to generic event handling */
 3211         } else {
 3212             /* Method offered by Nikon DSLR, Nikon 1, and some older Nikon Coolpix P*
 3213              * The Nikon Coolpix P2 however does not return anything. So if we never get
 3214              * events from here, use the ptp "interrupt" method */
 3215             if (ptp_operation_issupported(params, PTP_OC_NIKON_GetEvent)) {
 3216                 unsigned int evtcnt = 0, i;
 3217                 PTPContainer *xevent = NULL;
 3218 
 3219                 ret = ptp_nikon_check_event(params, &xevent, &evtcnt);
 3220                 if (ret != PTP_RC_OperationNotSupported)
 3221                     CHECK_PTP_RC(ret);
 3222 
 3223                 if (evtcnt) {
 3224                     for (i = 0; i < evtcnt; i++)
 3225                         handle_event_internal (params, &xevent[i]);
 3226                     params->events = realloc(params->events, sizeof(PTPContainer)*(evtcnt+params->nrofevents));
 3227                     memcpy (&params->events[params->nrofevents],xevent,evtcnt*sizeof(PTPContainer));
 3228                     params->nrofevents += evtcnt;
 3229                     params->event90c7works = 1;
 3230                 }
 3231                 free (xevent);
 3232                 if (params->event90c7works)
 3233                     return PTP_RC_OK;
 3234                 /* fall through to generic event handling */
 3235             }
 3236         }
 3237     }
 3238     /* should not get here ... EOS has no normal PTP events and another queue handling. */
 3239     if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) &&
 3240         ptp_operation_issupported(params, PTP_OC_CANON_EOS_GetEvent)
 3241     ) {
 3242         return PTP_RC_OK;
 3243     }
 3244 
 3245     if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) &&
 3246         ptp_operation_issupported(params, PTP_OC_CANON_CheckEvent)
 3247     ) {
 3248         int isevent;
 3249 
 3250         CHECK_PTP_RC(ptp_canon_checkevent (params,&event,&isevent));
 3251 
 3252         if (isevent) {
 3253             ret = PTP_RC_OK;
 3254             goto store_event;
 3255         }
 3256         /* Event Emulate Mode 0 (unset) and 1-5 get interrupt events. 6-7 does not. */
 3257         if (params->canon_event_mode > 5)
 3258             return PTP_RC_OK;
 3259 
 3260         /* FIXME: fallthrough or return? */
 3261 #ifdef __APPLE__
 3262         /* the libusb 1 on darwin currently does not like polling
 3263          * for interrupts, they have no timeout for it. 2010/08/23
 3264          * Check back in 2011 or so. -Marcus
 3265          */
 3266         return PTP_RC_OK;
 3267 #endif
 3268     }
 3269     ret = params->event_check(params,&event);
 3270 
 3271 store_event:
 3272     if (ret == PTP_RC_OK) {
 3273         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);
 3274         ptp_add_event (params, &event);
 3275 
 3276         handle_event_internal (params, &event);
 3277 
 3278 
 3279     }
 3280     if (ret == PTP_ERROR_TIMEOUT) /* ok, just new events */
 3281         ret = PTP_RC_OK;
 3282     return ret;
 3283 }
 3284 
 3285 uint16_t
 3286 ptp_wait_event (PTPParams *params)
 3287 {
 3288     PTPContainer    event;
 3289     uint16_t    ret;
 3290 
 3291     ret = params->event_wait(params,&event);
 3292     if (ret == PTP_RC_OK) {
 3293         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);
 3294         ptp_add_event (params, &event);
 3295 
 3296         handle_event_internal (params, &event);
 3297     }
 3298     if (ret == PTP_ERROR_TIMEOUT) /* ok, just new events */
 3299         ret = PTP_RC_OK;
 3300     return ret;
 3301 }
 3302 
 3303 int
 3304 ptp_get_one_event(PTPParams *params, PTPContainer *event)
 3305 {
 3306     if (!params->nrofevents)
 3307         return 0;
 3308     memcpy (event, params->events, sizeof(PTPContainer));
 3309     memmove (params->events, params->events+1, sizeof(PTPContainer)*(params->nrofevents-1));
 3310     /* do not realloc on shrink. */
 3311     params->nrofevents--;
 3312     if (!params->nrofevents) {
 3313         free (params->events);
 3314         params->events = NULL;
 3315     }
 3316     return 1;
 3317 }
 3318 
 3319 /**
 3320  * ptp_get_one_event_by_type:
 3321  *
 3322  * Check if one specific event has appeared in the queue, and return it back to us, and remove it from the queue.
 3323 
 3324  * params:  PTPParams*  in: params
 3325  *      code        in: event code
 3326  *      event       out: event container
 3327  *
 3328  * Return values: 1 if removed, 0 if not.
 3329  */
 3330 int
 3331 ptp_get_one_event_by_type(PTPParams *params, uint16_t code, PTPContainer *event)
 3332 {
 3333     unsigned int i;
 3334 
 3335     if (!params->nrofevents)
 3336         return 0;
 3337     for (i=0;i<params->nrofevents;i++) {
 3338         if (params->events[i].Code == code) {
 3339             memcpy (event, params->events+i, sizeof(PTPContainer));
 3340             memmove (params->events+i, params->events+i+1, sizeof(PTPContainer)*(params->nrofevents-i-1));
 3341             /* do not realloc on shrink. */
 3342             params->nrofevents--;
 3343             if (!params->nrofevents) {
 3344                 free (params->events);
 3345                 params->events = NULL;
 3346             }
 3347             return 1;
 3348         }
 3349     }
 3350     return 0;
 3351 }
 3352 
 3353 /**
 3354  * ptp_have_event:
 3355  *
 3356  * Check if one specific event has appeared in the queue, without draining it.
 3357  *
 3358  * params:  PTPParams*  in: params
 3359  *      code        in: event code
 3360  *
 3361  * Return values: 1 if removed, 0 if not.
 3362  */
 3363 int
 3364 ptp_have_event(PTPParams *params, uint16_t code)
 3365 {
 3366     unsigned int i;
 3367 
 3368     if (!params->nrofevents)
 3369         return 0;
 3370     for (i=0;i<params->nrofevents;i++)
 3371         if (params->events[i].Code == code)
 3372             return 1;
 3373     return 0;
 3374 }
 3375 
 3376 /**
 3377  * ptp_canon_eos_getevent:
 3378  *
 3379  * This retrieves configuration status/updates/changes
 3380  * on EOS cameras. It reads a datablock which has a list of variable
 3381  * sized structures.
 3382  *
 3383  * params:  PTPParams*
 3384  *
 3385  * Return values: Some PTP_RC_* code.
 3386  *
 3387  **/
 3388 uint16_t
 3389 ptp_canon_eos_getevent (PTPParams* params, PTPCanon_changes_entry **entries, int *nrofentries)
 3390 {
 3391     PTPContainer    ptp;
 3392     unsigned char   *data = NULL;
 3393     unsigned int    size;
 3394 
 3395     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetEvent);
 3396     *nrofentries = 0;
 3397     *entries = NULL;
 3398     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 3399     *nrofentries = ptp_unpack_CANON_changes(params,data,size,entries);
 3400     free (data);
 3401     return PTP_RC_OK;
 3402 }
 3403 
 3404 uint16_t
 3405 ptp_check_eos_events (PTPParams *params)
 3406 {
 3407     PTPCanon_changes_entry  *entries = NULL, *nentries;
 3408     int         nrofentries = 0;
 3409 
 3410     while (1) { /* call it repeatedly until the camera does not report any */
 3411         CHECK_PTP_RC(ptp_canon_eos_getevent (params, &entries, &nrofentries));
 3412         if (!nrofentries)
 3413             return PTP_RC_OK;
 3414 
 3415         if (params->nrofbacklogentries) {
 3416             nentries = realloc(params->backlogentries,sizeof(entries[0])*(params->nrofbacklogentries+nrofentries));
 3417             if (!nentries)
 3418                 return PTP_RC_GeneralError;
 3419             params->backlogentries = nentries;
 3420             memcpy (nentries+params->nrofbacklogentries, entries, nrofentries*sizeof(entries[0]));
 3421             params->nrofbacklogentries += nrofentries;
 3422             free (entries);
 3423         } else {
 3424             params->backlogentries = entries;
 3425             params->nrofbacklogentries = nrofentries;
 3426         }
 3427     }
 3428     return PTP_RC_OK;
 3429 }
 3430 
 3431 int
 3432 ptp_get_one_eos_event (PTPParams *params, PTPCanon_changes_entry *entry)
 3433 {
 3434     if (!params->nrofbacklogentries)
 3435         return 0;
 3436     memcpy (entry, params->backlogentries, sizeof(*entry));
 3437     if (params->nrofbacklogentries > 1) {
 3438         memmove (params->backlogentries,params->backlogentries+1,sizeof(*entry)*(params->nrofbacklogentries-1));
 3439         params->nrofbacklogentries--;
 3440     } else {
 3441         free (params->backlogentries);
 3442         params->backlogentries = NULL;
 3443         params->nrofbacklogentries = 0;
 3444     }
 3445     return 1;
 3446 }
 3447 
 3448 
 3449 uint16_t
 3450 ptp_canon_eos_getdevicepropdesc (PTPParams* params, uint16_t propcode,
 3451     PTPDevicePropDesc *dpd)
 3452 {
 3453     unsigned int i;
 3454 
 3455     for (i=0;i<params->nrofcanon_props;i++)
 3456         if (params->canon_props[i].proptype == propcode)
 3457             break;
 3458     if (params->nrofcanon_props == i)
 3459         return PTP_RC_Undefined;
 3460     memcpy (dpd, &params->canon_props[i].dpd, sizeof (*dpd));
 3461     if (dpd->FormFlag == PTP_DPFF_Enumeration) {
 3462         /* need to duplicate the Enumeration alloc */
 3463         dpd->FORM.Enum.SupportedValue = calloc (sizeof (PTPPropertyValue),dpd->FORM.Enum.NumberOfValues);
 3464         memcpy (dpd->FORM.Enum.SupportedValue,
 3465             params->canon_props[i].dpd.FORM.Enum.SupportedValue,
 3466             sizeof (PTPPropertyValue)*dpd->FORM.Enum.NumberOfValues
 3467         );
 3468     }
 3469     if (dpd->DataType == PTP_DTC_STR) {
 3470         dpd->FactoryDefaultValue.str = strdup( params->canon_props[i].dpd.FactoryDefaultValue.str );
 3471         dpd->CurrentValue.str = strdup( params->canon_props[i].dpd.CurrentValue.str );
 3472     }
 3473 
 3474     return PTP_RC_OK;
 3475 }
 3476 
 3477 
 3478 uint16_t
 3479 ptp_canon_eos_getstorageids (PTPParams* params, PTPStorageIDs* storageids)
 3480 {
 3481     PTPContainer    ptp;
 3482     unsigned char   *data = NULL;
 3483     unsigned int    size;
 3484 
 3485     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetStorageIDs);
 3486     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 3487     ptp_unpack_SIDs(params, data, storageids, size);
 3488     free(data);
 3489     return PTP_RC_OK;
 3490 }
 3491 
 3492 uint16_t
 3493 ptp_canon_eos_getstorageinfo (PTPParams* params, uint32_t p1, unsigned char **data, unsigned int *size)
 3494 {
 3495     PTPContainer    ptp;
 3496 
 3497     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetStorageInfo, p1);
 3498     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 3499     /* FIXME: do stuff with data */
 3500 }
 3501 
 3502 uint16_t
 3503 ptp_canon_eos_getobjectinfoex (
 3504     PTPParams* params, uint32_t storageid, uint32_t oid, uint32_t unk,
 3505     PTPCANONFolderEntry **entries, unsigned int *nrofentries
 3506 ) {
 3507     PTPContainer    ptp;
 3508     uint16_t    ret = PTP_RC_OK;
 3509     unsigned char   *data = NULL, *xdata;
 3510     unsigned int    size, i;
 3511 
 3512     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetObjectInfoEx, storageid, oid, unk);
 3513     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 3514     if (!data) {
 3515         *nrofentries = 0;
 3516         return PTP_RC_OK;
 3517     }
 3518 
 3519     if (size < 4) {
 3520         ret = PTP_RC_GeneralError;
 3521         goto exit;
 3522     }
 3523     /* check for integer overflow */
 3524     if (dtoh32a(data) >= INT_MAX/sizeof(PTPCANONFolderEntry))  {
 3525         ret = PTP_RC_GeneralError;
 3526         goto exit;
 3527     }
 3528 
 3529     *nrofentries = dtoh32a(data);
 3530     *entries = calloc(*nrofentries , sizeof(PTPCANONFolderEntry));
 3531     if (!*entries) {
 3532         ret = PTP_RC_GeneralError;
 3533         goto exit;
 3534     }
 3535 
 3536     xdata = data+sizeof(uint32_t);
 3537     for (i=0;i<*nrofentries;i++) {
 3538         unsigned int entrysize;
 3539 
 3540         if (4 + (xdata - data) > size) {
 3541             ptp_debug (params, "reading canon FEs run over read data size? (1)\n");
 3542             free (*entries);
 3543             *entries = NULL;
 3544             *nrofentries = 0;
 3545             ret = PTP_RC_GeneralError;
 3546             goto exit;
 3547         }
 3548         entrysize = dtoh32a(xdata);
 3549         if ((entrysize + (xdata-data)) > size) {
 3550             ptp_debug (params, "reading canon FEs run over read data size? (2)\n");
 3551             free (*entries);
 3552             *entries = NULL;
 3553             *nrofentries = 0;
 3554             ret = PTP_RC_GeneralError;
 3555             goto exit;
 3556         }
 3557         if (entrysize < 4 + 48 + 4)  {
 3558             ptp_debug (params, "%d entry size %d does not match expected 56\n", i, entrysize);
 3559             free (*entries);
 3560             *entries = NULL;
 3561             *nrofentries = 0;
 3562             ret = PTP_RC_GeneralError;
 3563             goto exit;
 3564         }
 3565         ptp_unpack_Canon_EOS_FE (params, &xdata[4], entrysize - 4, &((*entries)[i]));
 3566         xdata += entrysize;
 3567     }
 3568 exit:
 3569     free (data);
 3570     return ret;
 3571 }
 3572 
 3573 /**
 3574  * ptp_canon_eos_getpartialobject:
 3575  *
 3576  * This retrieves a part of an PTP object which you specify as object id.
 3577  * The id originates from 0x9116 call.
 3578  * After finishing it, we seem to need to call ptp_canon_eos_enddirecttransfer.
 3579  *
 3580  * params:  PTPParams*
 3581  *      oid     Object ID
 3582  *      offset      The offset where to start the data transfer
 3583  *      xsize       Size in bytes of the transfer to do
 3584  *      data        Pointer that receives the malloc()ed memory of the transfer.
 3585  *
 3586  * Return values: Some PTP_RC_* code.
 3587  *
 3588  */
 3589 uint16_t
 3590 ptp_canon_eos_getpartialobject (PTPParams* params, uint32_t oid, uint32_t offset, uint32_t xsize, unsigned char**data)
 3591 {
 3592     PTPContainer    ptp;
 3593 
 3594     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetPartialObject, oid, offset, xsize);
 3595     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, NULL);
 3596 }
 3597 
 3598 /**
 3599  * ptp_canon_eos_getpartialobjectex:
 3600  *
 3601  * This retrieves a part of an PTP object which you specify as object id.
 3602  * The id originates from 0x9116 call.
 3603  * After finishing it, we seem to need to call ptp_canon_eos_enddirecttransfer.
 3604  *
 3605  * params:  PTPParams*
 3606  *      oid     Object ID
 3607  *      offset      The offset where to start the data transfer
 3608  *      xsize       Size in bytes of the transfer to do
 3609  *      data        Pointer that receives the malloc()ed memory of the transfer.
 3610  *
 3611  * Return values: Some PTP_RC_* code.
 3612  *
 3613  */
 3614 uint16_t
 3615 ptp_canon_eos_getpartialobjectex (PTPParams* params, uint32_t oid, uint32_t offset, uint32_t xsize, unsigned char**data)
 3616 {
 3617     PTPContainer    ptp;
 3618 
 3619 /* 5bf19091  00008001  00001000  00000000  */
 3620 /* objectid  offset    size      ? 64bit part ? */
 3621     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetPartialObjectEx, oid, offset, xsize, 0);
 3622     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, NULL);
 3623 }
 3624 
 3625 uint16_t
 3626 ptp_canon_eos_setdevicepropvalueex (PTPParams* params, unsigned char* data, unsigned int size)
 3627 {
 3628     PTPContainer    ptp;
 3629 
 3630     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_SetDevicePropValueEx);
 3631     return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 3632 }
 3633 
 3634 uint16_t
 3635 ptp_canon_eos_setdevicepropvalue (PTPParams* params,
 3636     uint16_t propcode, PTPPropertyValue *value, uint16_t datatype
 3637 ) {
 3638     PTPContainer    ptp;
 3639     uint16_t    ret;
 3640     unsigned char   *data = NULL;
 3641     unsigned int    i, size;
 3642 
 3643     PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_SetDevicePropValueEx);
 3644 
 3645     for (i=0;i<params->nrofcanon_props;i++)
 3646         if (params->canon_props[i].proptype == propcode)
 3647             break;
 3648     if (params->nrofcanon_props == i)
 3649         return PTP_RC_Undefined;
 3650 
 3651     switch (propcode) {
 3652     case PTP_DPC_CANON_EOS_ImageFormat:
 3653     case PTP_DPC_CANON_EOS_ImageFormatCF:
 3654     case PTP_DPC_CANON_EOS_ImageFormatSD:
 3655     case PTP_DPC_CANON_EOS_ImageFormatExtHD:
 3656         /* special handling of ImageFormat properties */
 3657         size = 8 + ptp_pack_EOS_ImageFormat( params, NULL, value->u16 );
 3658         data = malloc( size );
 3659         if (!data) return PTP_RC_GeneralError;
 3660         ptp_pack_EOS_ImageFormat( params, data + 8, value->u16 );
 3661         break;
 3662     case PTP_DPC_CANON_EOS_CustomFuncEx:
 3663         /* special handling of CustomFuncEx properties */
 3664         ptp_debug (params, "ptp2/ptp_canon_eos_setdevicepropvalue: setting EOS prop %x to %s",propcode,value->str);
 3665         size = 8 + ptp_pack_EOS_CustomFuncEx( params, NULL, value->str );
 3666         data = malloc( size );
 3667         if (!data) return PTP_RC_GeneralError;
 3668         ptp_pack_EOS_CustomFuncEx( params, data + 8, value->str );
 3669         break;
 3670     default:
 3671         if (datatype != PTP_DTC_STR) {
 3672             data = calloc(3,sizeof(uint32_t));
 3673             if (!data) return PTP_RC_GeneralError;
 3674             size = sizeof(uint32_t)*3;
 3675         } else {
 3676             size = strlen(value->str) + 1 + 8;
 3677             data = calloc(size,sizeof(char));
 3678             if (!data) return PTP_RC_GeneralError;
 3679         }
 3680         switch (datatype) {
 3681         case PTP_DTC_INT8:
 3682         case PTP_DTC_UINT8:
 3683             /*fprintf (stderr, "%x -> %d\n", propcode, value->u8);*/
 3684             htod8a(&data[8], value->u8);
 3685             break;
 3686         case PTP_DTC_UINT16:
 3687         case PTP_DTC_INT16:
 3688             /*fprintf (stderr, "%x -> %d\n", propcode, value->u16);*/
 3689             htod16a(&data[8], value->u16);
 3690             break;
 3691         case PTP_DTC_INT32:
 3692         case PTP_DTC_UINT32:
 3693             /*fprintf (stderr, "%x -> %d\n", propcode, value->u32);*/
 3694             htod32a(&data[8], value->u32);
 3695             break;
 3696         case PTP_DTC_STR:
 3697             strcpy((char*)data + 8, value->str);
 3698             break;
 3699         }
 3700     }
 3701 
 3702     htod32a(&data[0], size);
 3703     htod32a(&data[4], propcode);
 3704 
 3705     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 3706     free (data);
 3707     if (ret == PTP_RC_OK) {
 3708         /* commit to cache only after successful setting */
 3709         switch (propcode) {
 3710         case PTP_DPC_CANON_EOS_ImageFormat:
 3711         case PTP_DPC_CANON_EOS_ImageFormatCF:
 3712         case PTP_DPC_CANON_EOS_ImageFormatSD:
 3713         case PTP_DPC_CANON_EOS_ImageFormatExtHD:
 3714             /* special handling of ImageFormat properties */
 3715             params->canon_props[i].dpd.CurrentValue.u16 = value->u16;
 3716             break;
 3717         case PTP_DPC_CANON_EOS_CustomFuncEx:
 3718             /* special handling of CustomFuncEx properties */
 3719             params->canon_props[i].dpd.CurrentValue.str = strdup( value->str );
 3720             break;
 3721         default:
 3722             switch (datatype) {
 3723             case PTP_DTC_INT8:
 3724             case PTP_DTC_UINT8:
 3725                 params->canon_props[i].dpd.CurrentValue.u8 = value->u8;
 3726                 break;
 3727             case PTP_DTC_UINT16:
 3728             case PTP_DTC_INT16:
 3729                 params->canon_props[i].dpd.CurrentValue.u16 = value->u16;
 3730                 break;
 3731             case PTP_DTC_INT32:
 3732             case PTP_DTC_UINT32:
 3733                 params->canon_props[i].dpd.CurrentValue.u32 = value->u32;
 3734                 break;
 3735             case PTP_DTC_STR:
 3736                 free (params->canon_props[i].dpd.CurrentValue.str);
 3737                 params->canon_props[i].dpd.CurrentValue.str = strdup(value->str);
 3738                 break;
 3739             }
 3740         }
 3741     }
 3742     return ret;
 3743 }
 3744 
 3745 /**
 3746  * ptp_canon_getpartialobject:
 3747  *
 3748  * This operation is used to read from the device a data
 3749  * block of an object from a specified offset.
 3750  *
 3751  * params:  PTPParams*
 3752  *      uint32_t handle - the handle of the requested object
 3753  *      uint32_t offset - the offset in bytes from the beginning of the object
 3754  *      uint32_t size - the requested size of data block to read
 3755  *      uint32_t pos - 1 for the first block, 2 - for a block in the middle,
 3756  *                  3 - for the last block
 3757  *
 3758  * Return values: Some PTP_RC_* code.
 3759  *      char **block - the pointer to the block of data read
 3760  *      uint32_t* readnum - the number of bytes read
 3761  *
 3762  **/
 3763 uint16_t
 3764 ptp_canon_getpartialobject (PTPParams* params, uint32_t handle,
 3765                 uint32_t offset, uint32_t size,
 3766                 uint32_t pos, unsigned char** block,
 3767                 uint32_t* readnum)
 3768 {
 3769     PTPContainer    ptp;
 3770     uint16_t    ret;
 3771     unsigned char   *data = NULL;
 3772 
 3773     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetPartialObjectEx, handle, offset, size, pos);
 3774     ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL);
 3775     if (ret==PTP_RC_OK) {
 3776         *block=data;
 3777         *readnum=ptp.Param1;
 3778     }
 3779     free (data);
 3780     return ret;
 3781 }
 3782 
 3783 /**
 3784  * ptp_canon_getviewfinderimage:
 3785  *
 3786  * This operation can be used to read the image which is currently
 3787  * in the camera's viewfinder. The image size is 320x240, format is JPEG.
 3788  * Of course, prior to calling this operation, one must turn the viewfinder
 3789  * on with the CANON_ViewfinderOn command.
 3790  * Invoking this operation many times, one can get live video from the camera!
 3791  *
 3792  * params:  PTPParams*
 3793  *
 3794  * Return values: Some PTP_RC_* code.
 3795  *      char **image - the pointer to the read image
 3796  *      unit32_t *size - the size of the image in bytes
 3797  *
 3798  **/
 3799 uint16_t
 3800 ptp_canon_getviewfinderimage (PTPParams* params, unsigned char** image, uint32_t* size)
 3801 {
 3802     PTPContainer    ptp;
 3803     uint16_t    ret;
 3804 
 3805     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetViewfinderImage);
 3806     ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, image, NULL);
 3807     if (ret==PTP_RC_OK)
 3808         *size=ptp.Param1;
 3809     return ret;
 3810 }
 3811 
 3812 /**
 3813  * ptp_canon_getchanges:
 3814  *
 3815  * This is an interesting operation, about the effect of which I am not sure.
 3816  * This command is called every time when a device property has been changed
 3817  * with the SetDevicePropValue operation, and after some other operations.
 3818  * This operation reads the array of Device Properties which have been changed
 3819  * by the previous operation.
 3820  * Probably, this operation is even required to make those changes work.
 3821  *
 3822  * params:  PTPParams*
 3823  *
 3824  * Return values: Some PTP_RC_* code.
 3825  *      uint16_t** props - the pointer to the array of changed properties
 3826  *      uint32_t* propnum - the number of elements in the *props array
 3827  *
 3828  **/
 3829 uint16_t
 3830 ptp_canon_getchanges (PTPParams* params, uint16_t** props, uint32_t* propnum)
 3831 {
 3832     PTPContainer    ptp;
 3833     unsigned char   *data = NULL;
 3834     unsigned int    size;
 3835 
 3836     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetChanges);
 3837     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 3838     *propnum=ptp_unpack_uint16_t_array(params,data,0,size,props);
 3839     free(data);
 3840     return PTP_RC_OK;
 3841 }
 3842 
 3843 /**
 3844  * ptp_canon_getobjectinfo:
 3845  *
 3846  * This command reads a specified object's record in a device's filesystem,
 3847  * or the records of all objects belonging to a specified folder (association).
 3848  *
 3849  * params:  PTPParams*
 3850  *      uint32_t store - StorageID,
 3851  *      uint32_t p2 - Yet unknown (0 value works OK)
 3852  *      uint32_t parent - Parent Object Handle
 3853  *                      # If Parent Object Handle is 0xffffffff,
 3854  *                      # the Parent Object is the top level folder.
 3855  *      uint32_t handle - Object Handle
 3856  *                      # If Object Handle is 0, the records of all objects
 3857  *                      # belonging to the Parent Object are read.
 3858  *                      # If Object Handle is not 0, only the record of this
 3859  *                      # Object is read.
 3860  *
 3861  * Return values: Some PTP_RC_* code.
 3862  *      PTPCANONFolderEntry** entries - the pointer to the folder entry array
 3863  *      uint32_t* entnum - the number of elements of the array
 3864  *
 3865  **/
 3866 uint16_t
 3867 ptp_canon_getobjectinfo (PTPParams* params, uint32_t store, uint32_t p2,
 3868                 uint32_t parent, uint32_t handle,
 3869                 PTPCANONFolderEntry** entries, uint32_t* entnum)
 3870 {
 3871     PTPContainer    ptp;
 3872     uint16_t    ret;
 3873     unsigned char   *data = NULL;
 3874     unsigned int    i, size;
 3875 
 3876     *entnum = 0;
 3877     *entries = NULL;
 3878     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetObjectInfoEx, store, p2, parent, handle);
 3879     data = NULL;
 3880     size = 0;
 3881     ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size);
 3882     if (ret != PTP_RC_OK)
 3883         goto exit;
 3884     if (!data)
 3885         return ret;
 3886     if (ptp.Param1 > size/PTP_CANON_FolderEntryLen) {
 3887         ptp_debug (params, "param1 is %d, size is only %d", ptp.Param1, size);
 3888         ret = PTP_RC_GeneralError;
 3889         goto exit;
 3890     }
 3891 
 3892     *entnum = ptp.Param1;
 3893     *entries= calloc(*entnum, sizeof(PTPCANONFolderEntry));
 3894     if (*entries == NULL) {
 3895         ret = PTP_RC_GeneralError;
 3896         goto exit;
 3897     }
 3898     for(i=0; i<(*entnum); i++) {
 3899         if (size < i*PTP_CANON_FolderEntryLen) break;
 3900         ptp_unpack_Canon_FE(params,
 3901                     data+i*PTP_CANON_FolderEntryLen,
 3902                     &((*entries)[i]) );
 3903     }
 3904 
 3905 exit:
 3906     free (data);
 3907     return ret;
 3908 }
 3909 
 3910 /**
 3911  * ptp_canon_get_objecthandle_by_name:
 3912  *
 3913  * This command looks up the specified object on the camera.
 3914  *
 3915  * Format is "A:\\PATH".
 3916  *
 3917  * The 'A' is the VolumeLabel from GetStorageInfo,
 3918  * my IXUS has "A" for the card and "V" for internal memory.
 3919  *
 3920  * params:  PTPParams*
 3921  *      char* name - path name
 3922  *
 3923  * Return values: Some PTP_RC_* code.
 3924  *      uint32_t *oid - PTP object id.
 3925  *
 3926  **/
 3927 uint16_t
 3928 ptp_canon_get_objecthandle_by_name (PTPParams* params, char* name, uint32_t* objectid)
 3929 {
 3930     PTPContainer    ptp;
 3931     uint16_t    ret;
 3932     unsigned char   *data;
 3933     uint8_t     len = 0;
 3934 
 3935     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetObjectHandleByName);
 3936     data = calloc (2,(strlen(name)+2));
 3937     if (!data) return PTP_RC_GeneralError;
 3938     ptp_pack_string (params, name, data, 0, &len);
 3939     ret=ptp_transaction (params, &ptp, PTP_DP_SENDDATA, (len+1)*2+1, &data, NULL);
 3940     free (data);
 3941     *objectid = ptp.Param1;
 3942     return ret;
 3943 }
 3944 
 3945 /**
 3946  * ptp_canon_get_customize_data:
 3947  *
 3948  * This command downloads the specified theme slot, including jpegs
 3949  * and wav files.
 3950  *
 3951  * params:  PTPParams*
 3952  *      uint32_t themenr - nr of theme
 3953  *
 3954  * Return values: Some PTP_RC_* code.
 3955  *      unsigned char **data - pointer to data pointer
 3956  *      unsigned int  *size - size of data returned
 3957  *
 3958  **/
 3959 uint16_t
 3960 ptp_canon_get_customize_data (PTPParams* params, uint32_t themenr,
 3961         unsigned char **data, unsigned int *size)
 3962 {
 3963     PTPContainer ptp;
 3964 
 3965     PTP_CNT_INIT(ptp, PTP_OC_CANON_GetCustomizeData, themenr);
 3966     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 3967 }
 3968 
 3969 
 3970 uint16_t
 3971 ptp_nikon_curve_download (PTPParams* params, unsigned char **data, unsigned int *size)
 3972 {
 3973     PTPContainer ptp;
 3974 
 3975     PTP_CNT_INIT(ptp, PTP_OC_NIKON_CurveDownload);
 3976     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 3977 }
 3978 
 3979 /**
 3980  * ptp_sony_sdioconnect:
 3981  *
 3982  * This changes modes of the camera
 3983  *
 3984  * params:  PTPParams*
 3985  *
 3986  * Return values: Some PTP_RC_* code.
 3987  *
 3988  **/
 3989 uint16_t
 3990 ptp_sony_sdioconnect (PTPParams* params, uint32_t p1, uint32_t p2, uint32_t p3)
 3991 {
 3992     PTPContainer    ptp;
 3993     unsigned char   *data = NULL;
 3994 
 3995     PTP_CNT_INIT(ptp, PTP_OC_SONY_SDIOConnect, p1, p2, p3);
 3996     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL));
 3997     free (data);
 3998     return PTP_RC_OK;
 3999 }
 4000 
 4001 /**
 4002  * ptp_sony_qx_connect:
 4003  *
 4004  * This changes modes of the camera
 4005  *
 4006  * params:  PTPParams*
 4007  *
 4008  * Return values: Some PTP_RC_* code.
 4009  *
 4010  **/
 4011 uint16_t
 4012 ptp_sony_qx_connect (PTPParams* params, uint32_t p1, uint32_t p2, uint32_t p3)
 4013 {
 4014     PTPContainer    ptp;
 4015     unsigned char   *data = NULL;
 4016 
 4017     PTP_CNT_INIT(ptp, PTP_OC_SONY_QX_Connect, p1, p2, p3);
 4018     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL));
 4019     free (data);
 4020     return PTP_RC_OK;
 4021 }
 4022 
 4023 /**
 4024  * ptp_sony_get_vendorpropcodes:
 4025  *
 4026  * This command downloads the vendor specific property codes.
 4027  *
 4028  * params:  PTPParams*
 4029  *
 4030  * Return values: Some PTP_RC_* code.
 4031  *      unsigned char **data - pointer to data pointer
 4032  *      unsigned int  *size - size of data returned
 4033  *
 4034  **/
 4035 uint16_t
 4036 ptp_sony_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size)
 4037 {
 4038     PTPContainer    ptp;
 4039     unsigned char   *xdata = NULL;
 4040     unsigned int    xsize, psize1 = 0, psize2 = 0;
 4041     uint16_t    *props1 = NULL,*props2 = NULL;
 4042 
 4043     *props = NULL;
 4044     *size = 0;
 4045     PTP_CNT_INIT(ptp, PTP_OC_SONY_GetSDIOGetExtDeviceInfo, 0xc8 /* unclear */);
 4046     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize));
 4047     if (xsize == 0) {
 4048         ptp_debug (params, "No special operations sent?");
 4049         return PTP_RC_OK;
 4050     }
 4051 
 4052     psize1 = ptp_unpack_uint16_t_array (params, xdata+2, 0, xsize, &props1);
 4053     ptp_debug (params, "xsize %d, got size %d\n", xsize, psize1*2 + 2 + 4);
 4054     if (psize1*2 + 2 + 4 < xsize) {
 4055         psize2 = ptp_unpack_uint16_t_array(params,xdata+2+psize1*2+4, 0, xsize, &props2);
 4056     }
 4057     *props = calloc(psize1+psize2, sizeof(uint16_t));
 4058     if (!*props) {
 4059         ptp_debug (params, "oom during malloc?");
 4060         free (props1);
 4061         free (props2);
 4062         free (xdata);
 4063         return PTP_RC_OK;
 4064     }
 4065     *size = psize1+psize2;
 4066     memcpy (*props, props1, psize1*sizeof(uint16_t));
 4067     memcpy ((*props)+psize1, props2, psize2*sizeof(uint16_t));
 4068     free (props1);
 4069     free (props2);
 4070     free (xdata);
 4071     return PTP_RC_OK;
 4072 }
 4073 
 4074 uint16_t
 4075 ptp_sony_qx_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size)
 4076 {
 4077     PTPContainer    ptp;
 4078     unsigned char   *xdata = NULL;
 4079     unsigned int    xsize, psize1 = 0, psize2 = 0;
 4080     uint16_t    *props1 = NULL,*props2 = NULL;
 4081 
 4082     *props = NULL;
 4083     *size = 0;
 4084     PTP_CNT_INIT(ptp, PTP_OC_SONY_QX_GetSDIOGetExtDeviceInfo, 0xc8 /* unclear */);
 4085     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &xdata, &xsize));
 4086     if (xsize == 0) {
 4087         ptp_debug (params, "No special operations sent?");
 4088         return PTP_RC_OK;
 4089     }
 4090 
 4091     psize1 = ptp_unpack_uint16_t_array (params, xdata+2, 0, xsize, &props1);
 4092     ptp_debug (params, "xsize %d, got size %d\n", xsize, psize1*2 + 2 + 4);
 4093     if (psize1*2 + 2 + 4 < xsize) {
 4094         psize2 = ptp_unpack_uint16_t_array(params,xdata+2+psize1*2+4, 0, xsize, &props2);
 4095     }
 4096     *props = calloc(psize1+psize2, sizeof(uint16_t));
 4097     if (!*props) {
 4098         ptp_debug (params, "oom during malloc?");
 4099         free (props1);
 4100         free (props2);
 4101         free (xdata);
 4102         return PTP_RC_OK;
 4103     }
 4104     *size = psize1+psize2;
 4105     memcpy (*props, props1, psize1*sizeof(uint16_t));
 4106     memcpy ((*props)+psize1, props2, psize2*sizeof(uint16_t));
 4107     free (props1);
 4108     free (props2);
 4109     free (xdata);
 4110     return PTP_RC_OK;
 4111 }
 4112 
 4113 
 4114 uint16_t
 4115 ptp_sony_getdevicepropdesc (PTPParams* params, uint16_t propcode, PTPDevicePropDesc *dpd)
 4116 {
 4117     PTPContainer    ptp;
 4118     unsigned char   *data = NULL;
 4119     unsigned int    size, len = 0;
 4120     uint16_t    ret;
 4121 
 4122     PTP_CNT_INIT(ptp, PTP_OC_SONY_GetDevicePropdesc, propcode);
 4123     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 4124     if (!data) return PTP_RC_GeneralError;
 4125     /* first 16 bit is 0xc8 0x00, then an array of 16 bit PTP ids */
 4126     ret = ptp_unpack_Sony_DPD(params,data,dpd,size,&len) ? PTP_RC_OK : PTP_RC_GeneralError;
 4127     free (data);
 4128     return ret;
 4129 }
 4130 
 4131 static uint16_t
 4132 _ptp_sony_getalldevicepropdesc (PTPParams* params, uint16_t opcode)
 4133 {
 4134     PTPContainer        ptp;
 4135     unsigned char       *data = NULL, *dpddata;
 4136     unsigned int        size, readlen;
 4137     PTPDevicePropDesc   dpd;
 4138     time_t          now;
 4139 
 4140     ptp_debug (params, "_ptp_sony_getalldevicepropdesc: opcode %04x", opcode);
 4141     /* for old A900 / A700 who does not have this, but has capture */
 4142     if (!ptp_operation_issupported(params, opcode))
 4143         return PTP_RC_OK;
 4144 
 4145     PTP_CNT_INIT(ptp, opcode);
 4146     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 4147     if (!data)
 4148         return PTP_RC_GeneralError;
 4149     if (size <= 8) {
 4150         free (data);
 4151         return PTP_RC_GeneralError;
 4152     }
 4153     dpddata = data+8; /* nr of entries 32bit, 0 32bit */
 4154     size -= 8;
 4155     time(&now);
 4156     while (size>0) {
 4157         unsigned int    i;
 4158         uint16_t    propcode;
 4159 
 4160         if (!ptp_unpack_Sony_DPD (params, dpddata, &dpd, size, &readlen))
 4161             break;
 4162 
 4163         propcode = dpd.DevicePropertyCode;
 4164 
 4165         for (i=0;i<params->nrofdeviceproperties;i++)
 4166             if (params->deviceproperties[i].desc.DevicePropertyCode == propcode)
 4167                 break;
 4168 
 4169         /* debug output to see what changes */
 4170         if (i != params->nrofdeviceproperties) {
 4171             switch (dpd.DataType) {
 4172             case PTP_DTC_INT8:
 4173 #define CHECK_CHANGED(type) \
 4174                 if (params->deviceproperties[i].desc.CurrentValue.type != dpd.CurrentValue.type) \
 4175                     ptp_debug (params, "ptp_sony_getalldevicepropdesc: %s(%04x): value %d -> %d", ptp_get_property_description (params, propcode), propcode, params->deviceproperties[i].desc.CurrentValue.type, dpd.CurrentValue.type);
 4176                 CHECK_CHANGED(i8);
 4177                 break;
 4178             case PTP_DTC_UINT8:
 4179                 CHECK_CHANGED(u8);
 4180                 break;
 4181             case PTP_DTC_UINT16:
 4182                 CHECK_CHANGED(u16);
 4183                 break;
 4184             case PTP_DTC_INT16:
 4185                 CHECK_CHANGED(i16);
 4186                 break;
 4187             case PTP_DTC_INT32:
 4188                 CHECK_CHANGED(i32);
 4189                 break;
 4190             case PTP_DTC_UINT32:
 4191                 CHECK_CHANGED(u32);
 4192                 break;
 4193             default:
 4194                 break;
 4195             }
 4196         }
 4197 
 4198         if (i == params->nrofdeviceproperties) {
 4199             params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0]));
 4200             memset(&params->deviceproperties[i],0,sizeof(params->deviceproperties[0]));
 4201             params->nrofdeviceproperties++;
 4202         } else {
 4203             ptp_free_devicepropdesc (&params->deviceproperties[i].desc);
 4204         }
 4205         params->deviceproperties[i].desc = dpd;
 4206         params->deviceproperties[i].timestamp = now;
 4207 #if 0
 4208         ptp_debug (params, "dpd.DevicePropertyCode %04x, readlen %d, getset %d", dpd.DevicePropertyCode, readlen, dpd.GetSet);
 4209         switch (dpd.DataType) {
 4210         case PTP_DTC_INT8:
 4211             ptp_debug (params, "value %d/%x", dpd.CurrentValue.i8, dpd.CurrentValue.i8);
 4212             break;
 4213         case PTP_DTC_UINT8:
 4214             ptp_debug (params, "value %d/%x", dpd.CurrentValue.u8, dpd.CurrentValue.u8);
 4215             break;
 4216         case PTP_DTC_UINT16:
 4217             ptp_debug (params, "value %d/%x", dpd.CurrentValue.u16, dpd.CurrentValue.u16);
 4218             break;
 4219         case PTP_DTC_INT16:
 4220             ptp_debug (params, "value %d/%x", dpd.CurrentValue.i16, dpd.CurrentValue.i16);
 4221             break;
 4222         case PTP_DTC_INT32:
 4223             ptp_debug (params, "value %d/%x", dpd.CurrentValue.i32, dpd.CurrentValue.i32);
 4224             break;
 4225         case PTP_DTC_UINT32:
 4226             ptp_debug (params, "value %d/%x", dpd.CurrentValue.u32, dpd.CurrentValue.u32);
 4227             break;
 4228         default:
 4229             ptp_debug (params, "unknown type %x", dpd.DataType);
 4230             break;
 4231         }
 4232 #endif
 4233         dpddata += readlen;
 4234         size -= readlen;
 4235     }
 4236     free(data);
 4237     return PTP_RC_OK;
 4238 }
 4239 
 4240 uint16_t
 4241 ptp_sony_getalldevicepropdesc (PTPParams* params) {
 4242     return _ptp_sony_getalldevicepropdesc (params, PTP_OC_SONY_GetAllDevicePropData);
 4243 }
 4244 
 4245 uint16_t
 4246 ptp_sony_qx_getalldevicepropdesc (PTPParams* params) {
 4247     return _ptp_sony_getalldevicepropdesc (params, PTP_OC_SONY_QX_GetAllDevicePropData);
 4248 }
 4249 
 4250 uint16_t
 4251 ptp_sony_setdevicecontrolvaluea (PTPParams* params, uint16_t propcode,
 4252             PTPPropertyValue *value, uint16_t datatype)
 4253 {
 4254     PTPContainer    ptp;
 4255     uint16_t    ret;
 4256     unsigned char   *data;
 4257     uint32_t    size;
 4258 
 4259     PTP_CNT_INIT(ptp, PTP_OC_SONY_SetControlDeviceA, propcode);
 4260     size = ptp_pack_DPV(params, value, &data, datatype);
 4261     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 4262     free(data);
 4263     return ret;
 4264 }
 4265 
 4266 uint16_t
 4267 ptp_sony_qx_setdevicecontrolvaluea (PTPParams* params, uint16_t propcode,
 4268             PTPPropertyValue *value, uint16_t datatype)
 4269 {
 4270     PTPContainer    ptp;
 4271     uint16_t    ret;
 4272     unsigned char   *data;
 4273     uint32_t    size;
 4274 
 4275     PTP_CNT_INIT(ptp, PTP_OC_SONY_QX_SetControlDeviceA, propcode);
 4276     size = ptp_pack_DPV(params, value, &data, datatype);
 4277     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 4278     free(data);
 4279     return ret;
 4280 }
 4281 
 4282 uint16_t
 4283 ptp_sony_setdevicecontrolvalueb (PTPParams* params, uint16_t propcode,
 4284             PTPPropertyValue *value, uint16_t datatype)
 4285 {
 4286     PTPContainer    ptp;
 4287     uint16_t    ret;
 4288     unsigned char   *data;
 4289     uint32_t    size;
 4290 
 4291     PTP_CNT_INIT(ptp, PTP_OC_SONY_SetControlDeviceB, propcode);
 4292     size = ptp_pack_DPV(params, value, &data , datatype);
 4293     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 4294     free(data);
 4295     return ret;
 4296 }
 4297 
 4298 uint16_t
 4299 ptp_sony_qx_setdevicecontrolvalueb (PTPParams* params, uint16_t propcode,
 4300             PTPPropertyValue *value, uint16_t datatype)
 4301 {
 4302     PTPContainer    ptp;
 4303     uint16_t    ret;
 4304     unsigned char   *data;
 4305     uint32_t    size;
 4306 
 4307     PTP_CNT_INIT(ptp, PTP_OC_SONY_QX_SetControlDeviceB, propcode);
 4308     size = ptp_pack_DPV(params, value, &data , datatype);
 4309     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 4310     free(data);
 4311     return ret;
 4312 }
 4313 
 4314 
 4315 uint16_t
 4316 ptp_sony_9280 (PTPParams* params, uint32_t param1,
 4317     uint32_t additional, uint32_t data2, uint32_t data3, uint32_t data4, uint8_t x, uint8_t y)
 4318 {
 4319     PTPContainer    ptp;
 4320     unsigned char   buf[18];
 4321     unsigned char   *buffer;
 4322 
 4323     PTP_CNT_INIT(ptp, 0x9280, param1);
 4324 
 4325     if ((additional != 0) && (additional != 2))
 4326         return PTP_RC_GeneralError;
 4327 
 4328     htod32a(&buf[0], additional);
 4329     htod32a(&buf[4], data2);
 4330     htod32a(&buf[8], data3);
 4331     htod32a(&buf[12], data4);
 4332 
 4333     /* only sent in the case where additional is 2 */
 4334     buf[16]= x; buf[17]= y;
 4335 
 4336     buffer=buf;
 4337     return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, 16+additional, &buffer, NULL);
 4338 }
 4339 
 4340 uint16_t
 4341 ptp_sony_9281 (PTPParams* params, uint32_t param1) {
 4342     PTPContainer    ptp;
 4343     unsigned int    size = 0;
 4344     unsigned char   *buffer = NULL;
 4345     uint16_t    ret;
 4346 
 4347     PTP_CNT_INIT(ptp, 0x9281, param1);
 4348     ret =  ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &buffer, &size);
 4349     free (buffer);
 4350     return ret;
 4351 }
 4352 
 4353 /**
 4354  * ptp_generic_getdevicepropdesc:
 4355  *
 4356  * This command gets a propertydesc.
 4357  * If a vendor specific property desc query is available, it uses that.
 4358  * If not, it falls back to the generic PTP getdevicepropdesc.
 4359  *
 4360  * params:  PTPParams*
 4361  *      uint16_t propcode
 4362  *      PTPDevicePropDesc *dpd
 4363  *
 4364  * Return values: Some PTP_RC_* code.
 4365  *
 4366  **/
 4367 /* Cache time in seconds. Should perhaps be more granular... */
 4368 
 4369 uint16_t
 4370 ptp_generic_getdevicepropdesc (PTPParams *params, uint16_t propcode, PTPDevicePropDesc *dpd)
 4371 {
 4372     unsigned int    i;
 4373     time_t      now;
 4374 
 4375     for (i=0;i<params->nrofdeviceproperties;i++)
 4376         if (params->deviceproperties[i].desc.DevicePropertyCode == propcode)
 4377             break;
 4378     if (i == params->nrofdeviceproperties) {
 4379         params->deviceproperties = realloc(params->deviceproperties,(i+1)*sizeof(params->deviceproperties[0]));
 4380         memset(&params->deviceproperties[i],0,sizeof(params->deviceproperties[0]));
 4381         params->nrofdeviceproperties++;
 4382     }
 4383 
 4384     if (params->deviceproperties[i].desc.DataType != PTP_DTC_UNDEF) {
 4385         time(&now);
 4386         if (params->deviceproperties[i].timestamp + params->cachetime > now) {
 4387             duplicate_DevicePropDesc(&params->deviceproperties[i].desc, dpd);
 4388             return PTP_RC_OK;
 4389         }
 4390         /* free cached entry as we will refetch it. */
 4391         ptp_free_devicepropdesc (&params->deviceproperties[i].desc);
 4392     }
 4393 
 4394     if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) &&
 4395         ptp_operation_issupported(params, PTP_OC_SONY_GetAllDevicePropData)
 4396     ) {
 4397         CHECK_PTP_RC(ptp_sony_getalldevicepropdesc (params));
 4398 
 4399         for (i=0;i<params->nrofdeviceproperties;i++)
 4400             if (params->deviceproperties[i].desc.DevicePropertyCode == propcode)
 4401                 break;
 4402         if (i == params->nrofdeviceproperties) {
 4403             ptp_debug (params, "alpha property 0x%04x not found?\n", propcode);
 4404             return PTP_RC_GeneralError;
 4405         }
 4406         time(&now);
 4407         params->deviceproperties[i].timestamp = now;
 4408         duplicate_DevicePropDesc(&params->deviceproperties[i].desc, dpd);
 4409         return PTP_RC_OK;
 4410     }
 4411     if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) &&
 4412         ptp_operation_issupported(params, PTP_OC_SONY_QX_GetAllDevicePropData)
 4413     ) {
 4414         CHECK_PTP_RC(ptp_sony_qx_getalldevicepropdesc (params));
 4415 
 4416         for (i=0;i<params->nrofdeviceproperties;i++)
 4417             if (params->deviceproperties[i].desc.DevicePropertyCode == propcode)
 4418                 break;
 4419         if (i == params->nrofdeviceproperties) {
 4420             ptp_debug (params, "qx property 0x%04x not found?\n", propcode);
 4421             return PTP_RC_GeneralError;
 4422         }
 4423         time(&now);
 4424         params->deviceproperties[i].timestamp = now;
 4425         duplicate_DevicePropDesc(&params->deviceproperties[i].desc, dpd);
 4426         return PTP_RC_OK;
 4427     }
 4428     if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) &&
 4429         ptp_operation_issupported(params, PTP_OC_SONY_GetDevicePropdesc)
 4430     ) {
 4431         CHECK_PTP_RC(ptp_sony_getdevicepropdesc (params, propcode, &params->deviceproperties[i].desc));
 4432 
 4433         time(&now);
 4434         params->deviceproperties[i].timestamp = now;
 4435         duplicate_DevicePropDesc(&params->deviceproperties[i].desc, dpd);
 4436         return PTP_RC_OK;
 4437     }
 4438 
 4439 
 4440     if (ptp_operation_issupported(params, PTP_OC_GetDevicePropDesc)) {
 4441         CHECK_PTP_RC(ptp_getdevicepropdesc (params, propcode, &params->deviceproperties[i].desc));
 4442 
 4443         time(&now);
 4444         params->deviceproperties[i].timestamp = now;
 4445         duplicate_DevicePropDesc(&params->deviceproperties[i].desc, dpd);
 4446         return PTP_RC_OK;
 4447     }
 4448 
 4449     return PTP_RC_OperationNotSupported;
 4450 }
 4451 
 4452 /**
 4453  * ptp_generic_setdevicepropvalue:
 4454  *
 4455  * This command sets a property value, device specific.
 4456  *
 4457  * params:  PTPParams*
 4458  *      uint16_t propcode
 4459  *      PTPDevicePropertyValue *value
 4460  *      uint16_t datatype
 4461  *
 4462  * Return values: Some PTP_RC_* code.
 4463  *
 4464  **/
 4465 uint16_t
 4466 ptp_generic_setdevicepropvalue (PTPParams* params, uint16_t propcode,
 4467     PTPPropertyValue *value, uint16_t datatype)
 4468 {
 4469     unsigned int i;
 4470 
 4471     /* reset the cache entry */
 4472     for (i=0;i<params->nrofdeviceproperties;i++)
 4473         if (params->deviceproperties[i].desc.DevicePropertyCode == propcode)
 4474             break;
 4475     if (i != params->nrofdeviceproperties)
 4476         params->deviceproperties[i].timestamp = 0;
 4477 
 4478     /* FIXME: change the cache? hmm */
 4479     /* this works for some methods, but not for all */
 4480     if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) &&
 4481         ptp_operation_issupported(params, PTP_OC_SONY_SetControlDeviceA)
 4482     )
 4483         return ptp_sony_setdevicecontrolvaluea (params, propcode, value, datatype);
 4484     /* Sony QX method */
 4485     if (    (params->deviceinfo.VendorExtensionID == PTP_VENDOR_SONY) &&
 4486         ptp_operation_issupported(params, PTP_OC_SONY_QX_SetControlDeviceA)
 4487     )
 4488         return ptp_sony_qx_setdevicecontrolvaluea (params, propcode, value, datatype);
 4489     return ptp_setdevicepropvalue (params, propcode, value, datatype);
 4490 }
 4491 
 4492 /**
 4493  * ptp_nikon_get_vendorpropcodes:
 4494  *
 4495  * This command downloads the vendor specific property codes.
 4496  *
 4497  * params:  PTPParams*
 4498  *
 4499  * Return values: Some PTP_RC_* code.
 4500  *      unsigned char **data - pointer to data pointer
 4501  *      unsigned int  *size - size of data returned
 4502  *
 4503  **/
 4504 uint16_t
 4505 ptp_nikon_get_vendorpropcodes (PTPParams* params, uint16_t **props, unsigned int *size)
 4506 {
 4507     PTPContainer    ptp;
 4508     unsigned char   *data = NULL;
 4509     unsigned int    xsize = 0;
 4510 
 4511     *props = NULL;
 4512     *size = 0;
 4513     PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetVendorPropCodes);
 4514     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &xsize));
 4515     *size = ptp_unpack_uint16_t_array(params,data,0,xsize,props);
 4516     free (data);
 4517     return PTP_RC_OK;
 4518 }
 4519 
 4520 uint16_t
 4521 ptp_nikon_getfileinfoinblock ( PTPParams* params,
 4522     uint32_t p1, uint32_t p2, uint32_t p3,
 4523     unsigned char **data, unsigned int *size
 4524 ) {
 4525     PTPContainer ptp;
 4526 
 4527     PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetFileInfoInBlock, p1, p2, p3);
 4528     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 4529 }
 4530 
 4531 /**
 4532  * ptp_nikon_get_liveview_image:
 4533  *
 4534  * This command gets a LiveView image from newer Nikons DSLRs.
 4535  *
 4536  * params:  PTPParams*
 4537  *
 4538  * Return values: Some PTP_RC_* code.
 4539  *
 4540  **/
 4541 uint16_t
 4542 ptp_nikon_get_liveview_image (PTPParams* params, unsigned char **data, unsigned int *size)
 4543 {
 4544         PTPContainer ptp;
 4545 
 4546         PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetLiveViewImg);
 4547         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 4548 }
 4549 
 4550 /**
 4551  * ptp_nikon_get_preview_image:
 4552  *
 4553  * This command gets a Preview image from newer Nikons DSLRs.
 4554  *
 4555  * params:  PTPParams*
 4556  *
 4557  * Return values: Some PTP_RC_* code.
 4558  *
 4559  **/
 4560 uint16_t
 4561 ptp_nikon_get_preview_image (PTPParams* params, unsigned char **xdata, unsigned int *xsize,
 4562     uint32_t *handle)
 4563 {
 4564     PTPContainer    ptp;
 4565 
 4566         PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetPreviewImg);
 4567 
 4568     /* FIXME:
 4569      * pdslrdashboard passes 3 parameters:
 4570      * objectid, minimum size, maximum size
 4571      */
 4572     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, xdata, xsize));
 4573     if (ptp.Nparam > 0)
 4574         *handle = ptp.Param1;
 4575     return PTP_RC_OK;
 4576 }
 4577 
 4578 /**
 4579  * ptp_canon_eos_get_remotemode:
 4580  *
 4581  * This command gets the EOS remote mode.
 4582  *
 4583  * params:  PTPParams*
 4584  *
 4585  * Return values: Some PTP_RC_* code.
 4586  *
 4587  **/
 4588 uint16_t
 4589 ptp_canon_eos_getremotemode (PTPParams* params, uint32_t *mode)
 4590 {
 4591     PTPContainer    ptp;
 4592 
 4593         PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetRemoteMode);
 4594 
 4595     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 4596     *mode = 0;
 4597     if (ptp.Nparam > 0)
 4598         *mode = ptp.Param1;
 4599     return PTP_RC_OK;
 4600 }
 4601 
 4602 /**
 4603  * ptp_canon_eos_get_viewfinder_image:
 4604  *
 4605  * This command gets a Viewfinder image from newer Nikons DSLRs.
 4606  *
 4607  * params:  PTPParams*
 4608  *
 4609  * Return values: Some PTP_RC_* code.
 4610  *
 4611  **/
 4612 uint16_t
 4613 ptp_canon_eos_get_viewfinder_image (PTPParams* params, unsigned char **data, unsigned int *size)
 4614 {
 4615         PTPContainer ptp;
 4616 
 4617     /* Saw 3 arguments ... 0x00200000 for EOS1000D, also used 0x00100000 */
 4618         PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetViewFinderData, 0x00200000 /* from trace */, 0, 0);
 4619         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 4620 }
 4621 
 4622 uint16_t
 4623 ptp_canon_eos_get_viewfinder_image_handler (PTPParams* params, PTPDataHandler*handler)
 4624 {
 4625         PTPContainer ptp;
 4626 
 4627     /* Saw 3 arguments ... 0x00200000 for EOS1000D, also used 0x00100000 */
 4628         PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetViewFinderData, 0x00200000 /* from trace */, 0, 0);
 4629         return ptp_transaction_new(params, &ptp, PTP_DP_GETDATA, 0, handler);
 4630 }
 4631 
 4632 /**
 4633  * ptp_nikon_check_event:
 4634  *
 4635  * This command checks the event queue on the Nikon.
 4636  *
 4637  * params:  PTPParams*
 4638  *      PTPUSBEventContainer **event - list of usb events.
 4639  *  int *evtcnt - number of usb events in event structure.
 4640  *
 4641  * Return values: Some PTP_RC_* code.
 4642  *
 4643  **/
 4644 uint16_t
 4645 ptp_nikon_check_event (PTPParams* params, PTPContainer** event, unsigned int* evtcnt)
 4646 {
 4647     PTPContainer    ptp;
 4648     unsigned char   *data = NULL;
 4649     unsigned int    size;
 4650 
 4651     PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetEvent);
 4652     *evtcnt = 0;
 4653     CHECK_PTP_RC(ptp_transaction (params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 4654     ptp_unpack_Nikon_EC (params, data, size, event, evtcnt);
 4655     free (data);
 4656     return PTP_RC_OK;
 4657 }
 4658 
 4659 /**
 4660  * ptp_nikon_check_eventex:
 4661  *
 4662  * This command checks the event queue on the Nikon.
 4663  *
 4664  * params:  PTPParams*
 4665  *      PTPUSBEventContainer **event - list of usb events.
 4666  *  int *evtcnt - number of usb events in event structure.
 4667  *
 4668  * Return values: Some PTP_RC_* code.
 4669  *
 4670  **/
 4671 uint16_t
 4672 ptp_nikon_check_eventex (PTPParams* params, PTPContainer** event, unsigned int* evtcnt)
 4673 {
 4674     PTPContainer    ptp;
 4675     unsigned char   *data = NULL;
 4676     unsigned int    size;
 4677 
 4678     PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetEventEx);
 4679     *evtcnt = 0;
 4680     CHECK_PTP_RC(ptp_transaction (params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 4681     ptp_unpack_Nikon_EC_EX (params, data, size, event, evtcnt);
 4682     free (data);
 4683     return PTP_RC_OK;
 4684 }
 4685 
 4686 /**
 4687  * ptp_nikon_getptpipinfo:
 4688  *
 4689  * This command gets the ptpip info data.
 4690  *
 4691  * params:  PTPParams*
 4692  *  unsigned char *data - data
 4693  *  unsigned int size   - size of returned data
 4694  *
 4695  * Return values: Some PTP_RC_* code.
 4696  *
 4697  **/
 4698 uint16_t
 4699 ptp_nikon_getptpipinfo (PTPParams* params, unsigned char **data, unsigned int *size)
 4700 {
 4701         PTPContainer ptp;
 4702 
 4703         PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetDevicePTPIPInfo);
 4704         return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size);
 4705 }
 4706 
 4707 /**
 4708  * ptp_nikon_getwifiprofilelist:
 4709  *
 4710  * This command gets the wifi profile list.
 4711  *
 4712  * params:  PTPParams*
 4713  *
 4714  * Return values: Some PTP_RC_* code.
 4715  *
 4716  **/
 4717 uint16_t
 4718 ptp_nikon_getwifiprofilelist (PTPParams* params)
 4719 {
 4720     PTPContainer    ptp;
 4721     uint16_t    ret;
 4722     unsigned char   *data = NULL;
 4723     unsigned int    size, pos, profn, n;
 4724     char        *buffer;
 4725     uint8_t     len;
 4726 
 4727         PTP_CNT_INIT(ptp, PTP_OC_NIKON_GetProfileAllData);
 4728     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 4729 
 4730     ret = PTP_RC_Undefined; /* FIXME: Add more precise error code */
 4731 
 4732     if (size < 2)
 4733         goto exit;
 4734 
 4735     params->wifi_profiles_version = data[0];
 4736     params->wifi_profiles_number = data[1];
 4737     free(params->wifi_profiles);
 4738 
 4739     params->wifi_profiles = calloc(params->wifi_profiles_number,sizeof(PTPNIKONWifiProfile));
 4740 
 4741     pos = 2;
 4742     profn = 0;
 4743     while (profn < params->wifi_profiles_number && pos < size) {
 4744         if (pos+6 >= size)
 4745             goto exit;
 4746         params->wifi_profiles[profn].id = data[pos++];
 4747         params->wifi_profiles[profn].valid = data[pos++];
 4748 
 4749         n = dtoh32a(&data[pos]);
 4750         pos += 4;
 4751         if (pos+n+4 >= size)
 4752             goto exit;
 4753         strncpy(params->wifi_profiles[profn].profile_name, (char*)&data[pos], n);
 4754         params->wifi_profiles[profn].profile_name[16] = '\0';
 4755         pos += n;
 4756 
 4757         params->wifi_profiles[profn].display_order = data[pos++];
 4758         params->wifi_profiles[profn].device_type = data[pos++];
 4759         params->wifi_profiles[profn].icon_type = data[pos++];
 4760 
 4761         if (!ptp_unpack_string(params, data, pos, size, &len, &buffer))
 4762             goto exit;
 4763         strncpy(params->wifi_profiles[profn].creation_date, buffer, sizeof(params->wifi_profiles[profn].creation_date));
 4764         free (buffer);
 4765         pos += (len*2+1);
 4766         if (pos+1 >= size)
 4767             goto exit;
 4768         /* FIXME: check if it is really last usage date */
 4769         if (!ptp_unpack_string(params, data, pos, size, &len, &buffer))
 4770             goto exit;
 4771         strncpy(params->wifi_profiles[profn].lastusage_date, buffer, sizeof(params->wifi_profiles[profn].lastusage_date));
 4772         free (buffer);
 4773         pos += (len*2+1);
 4774         if (pos+5 >= size)
 4775             goto exit;
 4776 
 4777         n = dtoh32a(&data[pos]);
 4778         pos += 4;
 4779         if (pos+n >= size)
 4780             goto exit;
 4781         strncpy(params->wifi_profiles[profn].essid, (char*)&data[pos], n);
 4782         params->wifi_profiles[profn].essid[32] = '\0';
 4783         pos += n;
 4784         pos += 1;
 4785         profn++;
 4786     }
 4787 
 4788 #if 0
 4789     PTPNIKONWifiProfile test;
 4790     memset(&test, 0, sizeof(PTPNIKONWifiProfile));
 4791     strcpy(test.profile_name, "MyTest");
 4792     test.icon_type = 1;
 4793     strcpy(test.essid, "nikon");
 4794     test.ip_address = 10 + 11 << 16 + 11 << 24;
 4795     test.subnet_mask = 24;
 4796     test.access_mode = 1;
 4797     test.wifi_channel = 1;
 4798     test.key_nr = 1;
 4799 
 4800     ptp_nikon_writewifiprofile(params, &test);
 4801 #endif
 4802     /* everything went Ok */
 4803     ret = PTP_RC_OK;
 4804 exit:
 4805     free (data);
 4806     return ret;
 4807 }
 4808 
 4809 /**
 4810  * ptp_nikon_writewifiprofile:
 4811  *
 4812  * This command gets the ptpip info data.
 4813  *
 4814  * params:  PTPParams*
 4815  *  unsigned int profilenr  - profile number
 4816  *  unsigned char *data - data
 4817  *  unsigned int size   - size of returned data
 4818  *
 4819  * Return values: Some PTP_RC_* code.
 4820  *
 4821  **/
 4822 uint16_t
 4823 ptp_nikon_writewifiprofile (PTPParams* params, PTPNIKONWifiProfile* profile)
 4824 {
 4825     PTPContainer ptp;
 4826     unsigned char buffer[1024];
 4827     unsigned char* data = buffer;
 4828     int size = 0;
 4829     int i;
 4830     uint8_t len;
 4831     int profilenr = -1;
 4832     unsigned char guid[16];
 4833 
 4834     ptp_nikon_getptpipguid(guid);
 4835 
 4836     if (!params->wifi_profiles)
 4837         CHECK_PTP_RC(ptp_nikon_getwifiprofilelist(params));
 4838 
 4839     for (i = 0; i < params->wifi_profiles_number; i++) {
 4840         if (!params->wifi_profiles[i].valid) {
 4841             profilenr = params->wifi_profiles[i].id;
 4842             break;
 4843         }
 4844     }
 4845 
 4846     if (profilenr == -1) {
 4847         /* No free profile! */
 4848         return PTP_RC_StoreFull;
 4849     }
 4850 
 4851     memset(buffer, 0, 1024);
 4852 
 4853     buffer[0x00] = 0x64; /* Version */
 4854 
 4855     /* Profile name */
 4856     htod32a(&buffer[0x01], 17);
 4857     /* 16 as third parameter, so there will always be a null-byte in the end */
 4858     strncpy((char*)&buffer[0x05], profile->profile_name, 16);
 4859 
 4860     buffer[0x16] = 0x00; /* Display order */
 4861     buffer[0x17] = profile->device_type;
 4862     buffer[0x18] = profile->icon_type;
 4863 
 4864     /* FIXME: Creation date: put a real date here */
 4865     ptp_pack_string(params, "19990909T090909", data, 0x19, &len);
 4866 
 4867     /* IP parameters */
 4868     memcpy(&buffer[0x3A],&profile->ip_address,sizeof(profile->ip_address));
 4869     /**((unsigned int*)&buffer[0x3A]) = profile->ip_address; *//* Do not reverse bytes */
 4870     buffer[0x3E] = profile->subnet_mask;
 4871     memcpy(&buffer[0x3F],&profile->gateway_address,sizeof(profile->gateway_address));
 4872     /**((unsigned int*)&buffer[0x3F]) = profile->gateway_address; */ /* Do not reverse bytes */
 4873     buffer[0x43] = profile->address_mode;
 4874 
 4875     /* Wifi parameters */
 4876     buffer[0x44] = profile->access_mode;
 4877     buffer[0x45] = profile->wifi_channel;
 4878 
 4879     htod32a(&buffer[0x46], 33); /* essid */
 4880      /* 32 as third parameter, so there will always be a null-byte in the end */
 4881     strncpy((char*)&buffer[0x4A], profile->essid, 32);
 4882 
 4883     buffer[0x6B] = profile->authentification;
 4884     buffer[0x6C] = profile->encryption;
 4885     htod32a(&buffer[0x6D], 64);
 4886     for (i = 0; i < 64; i++) {
 4887         buffer[0x71+i] = profile->key[i];
 4888     }
 4889     buffer[0xB1] = profile->key_nr;
 4890     memcpy(&buffer[0xB2], guid, 16);
 4891 
 4892     switch(profile->encryption) {
 4893     case 1: /* WEP 64bit */
 4894         htod16a(&buffer[0xC2], 5); /* (64-24)/8 = 5 */
 4895         break;
 4896     case 2: /* WEP 128bit */
 4897         htod16a(&buffer[0xC2], 13); /* (128-24)/8 = 13 */
 4898         break;
 4899     default:
 4900         htod16a(&buffer[0xC2], 0);
 4901     }
 4902     size = 0xC4;
 4903 
 4904     PTP_CNT_INIT(ptp, PTP_OC_NIKON_SendProfileData, profilenr);
 4905     return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 4906 }
 4907 
 4908 /**
 4909  * ptp_mtp_getobjectpropssupported:
 4910  *
 4911  * This command gets the object properties possible from the device.
 4912  *
 4913  * params:  PTPParams*
 4914  *  uint ofc        - object format code
 4915  *  unsigned int *propnum   - number of elements in returned array
 4916  *  uint16_t *props     - array of supported properties
 4917  *
 4918  * Return values: Some PTP_RC_* code.
 4919  *
 4920  **/
 4921 uint16_t
 4922 ptp_mtp_getobjectpropssupported (PTPParams* params, uint16_t ofc,
 4923          uint32_t *propnum, uint16_t **props
 4924 ) {
 4925     PTPContainer    ptp;
 4926     unsigned char   *data = NULL;
 4927     unsigned int    xsize = 0;
 4928 
 4929         PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectPropsSupported, ofc);
 4930     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &xsize));
 4931     if (!data) return PTP_RC_GeneralError;
 4932     *propnum=ptp_unpack_uint16_t_array (params, data, 0, xsize, props);
 4933     free(data);
 4934     return PTP_RC_OK;
 4935 }
 4936 
 4937 /**
 4938  * ptp_mtp_getobjectpropdesc:
 4939  *
 4940  * This command gets the object property description.
 4941  *
 4942  * params:  PTPParams*
 4943  *  uint16_t opc    - object property code
 4944  *  uint16_t ofc    - object format code
 4945  *
 4946  * Return values: Some PTP_RC_* code.
 4947  *
 4948  **/
 4949 uint16_t
 4950 ptp_mtp_getobjectpropdesc (
 4951     PTPParams* params, uint16_t opc, uint16_t ofc, PTPObjectPropDesc *opd
 4952 ) {
 4953     PTPContainer    ptp;
 4954     unsigned char   *data = NULL;
 4955     unsigned int    size;
 4956 
 4957         PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectPropDesc, opc, ofc);
 4958         CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 4959     ptp_unpack_OPD (params, data, opd, size);
 4960     free(data);
 4961     return PTP_RC_OK;
 4962 }
 4963 
 4964 /**
 4965  * ptp_mtp_getobjectpropvalue:
 4966  *
 4967  * This command gets the object properties of an object handle.
 4968  *
 4969  * params:  PTPParams*
 4970  *  uint32_t objectid   - object format code
 4971  *  uint16_t opc        - object prop code
 4972  *
 4973  * Return values: Some PTP_RC_* code.
 4974  *
 4975  **/
 4976 uint16_t
 4977 ptp_mtp_getobjectpropvalue (
 4978     PTPParams* params, uint32_t oid, uint16_t opc,
 4979     PTPPropertyValue *value, uint16_t datatype
 4980 ) {
 4981     PTPContainer    ptp;
 4982     uint16_t    ret = PTP_RC_OK;
 4983     unsigned char   *data = NULL;
 4984     unsigned int    size, offset = 0;
 4985 
 4986         PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectPropValue, oid, opc);
 4987         CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 4988         if (!ptp_unpack_DPV(params, data, &offset, size, value, datatype)) {
 4989                 ptp_debug (params, "ptp_mtp_getobjectpropvalue: unpacking DPV failed");
 4990                 ret = PTP_RC_GeneralError;
 4991         }
 4992     free(data);
 4993     return ret;
 4994 }
 4995 
 4996 /**
 4997  * ptp_mtp_setobjectpropvalue:
 4998  *
 4999  * This command gets the object properties of an object handle.
 5000  *
 5001  * params:  PTPParams*
 5002  *  uint32_t objectid   - object format code
 5003  *  uint16_t opc        - object prop code
 5004  *
 5005  * Return values: Some PTP_RC_* code.
 5006  *
 5007  **/
 5008 uint16_t
 5009 ptp_mtp_setobjectpropvalue (
 5010     PTPParams* params, uint32_t oid, uint16_t opc,
 5011     PTPPropertyValue *value, uint16_t datatype
 5012 ) {
 5013     PTPContainer    ptp;
 5014     uint16_t    ret;
 5015     unsigned char   *data = NULL;
 5016     uint32_t    size;
 5017 
 5018         PTP_CNT_INIT(ptp, PTP_OC_MTP_SetObjectPropValue, oid, opc);
 5019     size = ptp_pack_DPV(params, value, &data, datatype);
 5020         ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 5021     free(data);
 5022     return ret;
 5023 }
 5024 
 5025 uint16_t
 5026 ptp_mtp_getobjectreferences (PTPParams* params, uint32_t handle, uint32_t** ohArray, uint32_t* arraylen)
 5027 {
 5028     PTPContainer    ptp;
 5029     unsigned char   *data = NULL;
 5030     unsigned int    size;
 5031 
 5032     PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectReferences, handle);
 5033     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data , &size));
 5034     /* Sandisk Sansa skips the DATA phase, but returns OK as response.
 5035          * this will gives us a NULL here. Handle it. -Marcus */
 5036     if ((data == NULL) || (size == 0)) {
 5037         *arraylen = 0;
 5038         *ohArray = NULL;
 5039     } else {
 5040         *arraylen = ptp_unpack_uint32_t_array(params, data , 0, size, ohArray);
 5041     }
 5042     free(data);
 5043     return PTP_RC_OK;
 5044 }
 5045 
 5046 uint16_t
 5047 ptp_mtp_setobjectreferences (PTPParams* params, uint32_t handle, uint32_t* ohArray, uint32_t arraylen)
 5048 {
 5049     PTPContainer    ptp;
 5050     uint16_t    ret;
 5051     unsigned char   *data = NULL;
 5052     uint32_t    size;
 5053 
 5054     PTP_CNT_INIT(ptp, PTP_OC_MTP_SetObjectReferences, handle);
 5055     size = ptp_pack_uint32_t_array(params, ohArray, arraylen, &data);
 5056     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 5057     free(data);
 5058     return ret;
 5059 }
 5060 
 5061 uint16_t
 5062 ptp_mtp_getobjectproplist_generic (PTPParams* params, uint32_t handle, uint32_t formats, uint32_t properties, uint32_t propertygroups, uint32_t level, MTPProperties **props, int *nrofprops)
 5063 {
 5064     PTPContainer    ptp;
 5065     unsigned char   *data = NULL;
 5066     unsigned int    size;
 5067 
 5068     PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjPropList, handle, formats, properties, propertygroups, level);
 5069     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size));
 5070     *nrofprops = ptp_unpack_OPL(params, data, props, size);
 5071     free(data);
 5072     return PTP_RC_OK;
 5073 }
 5074 
 5075 uint16_t
 5076 ptp_mtp_getobjectproplist_level (PTPParams* params, uint32_t handle, uint32_t level, MTPProperties **props, int *nrofprops)
 5077 {
 5078     return ptp_mtp_getobjectproplist_generic (params, handle,
 5079              0x00000000U,  /* 0x00000000U should be "all formats" */
 5080              0xFFFFFFFFU,  /* 0xFFFFFFFFU should be "all properties" */
 5081              0,
 5082              level,
 5083              props,
 5084              nrofprops
 5085     );
 5086 }
 5087 
 5088 
 5089 uint16_t
 5090 ptp_mtp_getobjectproplist (PTPParams* params, uint32_t handle, MTPProperties **props, int *nrofprops)
 5091 {
 5092     return ptp_mtp_getobjectproplist_level(params, handle, 0xFFFFFFFFU, props, nrofprops);
 5093 }
 5094 
 5095 uint16_t
 5096 ptp_mtp_getobjectproplist_single (PTPParams* params, uint32_t handle, MTPProperties **props, int *nrofprops)
 5097 {
 5098     return ptp_mtp_getobjectproplist_level(params, handle, 0, props, nrofprops);
 5099 }
 5100 
 5101 uint16_t
 5102 ptp_mtp_sendobjectproplist (PTPParams* params, uint32_t* store, uint32_t* parenthandle, uint32_t* handle,
 5103                 uint16_t objecttype, uint64_t objectsize, MTPProperties *props, int nrofprops)
 5104 {
 5105     PTPContainer    ptp;
 5106     uint16_t    ret;
 5107     unsigned char   *data = NULL;
 5108     uint32_t    size;
 5109 
 5110     PTP_CNT_INIT(ptp, PTP_OC_MTP_SendObjectPropList, *store, *parenthandle, (uint32_t) objecttype,
 5111              (uint32_t) (objectsize >> 32), (uint32_t) (objectsize & 0xffffffffU)
 5112     );
 5113 
 5114     /* Set object handle to 0 for a new object */
 5115     size = ptp_pack_OPL(params,props,nrofprops,&data);
 5116     ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL);
 5117     free(data);
 5118     *store = ptp.Param1;
 5119     *parenthandle = ptp.Param2;
 5120     *handle = ptp.Param3;
 5121 
 5122     return ret;
 5123 }
 5124 
 5125 uint16_t
 5126 ptp_mtp_setobjectproplist (PTPParams* params, MTPProperties *props, int nrofprops)
 5127 {
 5128     PTPContainer    ptp;
 5129     unsigned char   *data = NULL;
 5130     uint32_t    size;
 5131 
 5132     PTP_CNT_INIT(ptp, PTP_OC_MTP_SetObjPropList);
 5133     size = ptp_pack_OPL(params,props,nrofprops,&data);
 5134     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL));
 5135     free(data);
 5136     return PTP_RC_OK;
 5137 }
 5138 
 5139 uint16_t
 5140 ptp_mtpz_sendwmdrmpdapprequest (PTPParams* params, unsigned char *appcertmsg, uint32_t size)
 5141 {
 5142     PTPContainer ptp;
 5143 
 5144     PTP_CNT_INIT(ptp, PTP_OC_MTP_WMDRMPD_SendWMDRMPDAppRequest);
 5145     return ptp_transaction (params, &ptp, PTP_DP_SENDDATA, size, &appcertmsg, NULL);
 5146 }
 5147 
 5148 uint16_t
 5149 ptp_mtpz_getwmdrmpdappresponse (PTPParams* params, unsigned char **response, uint32_t *size)
 5150 {
 5151     PTPContainer ptp;
 5152 
 5153     PTP_CNT_INIT(ptp, PTP_OC_MTP_WMDRMPD_GetWMDRMPDAppResponse);
 5154     *size = 0;
 5155     *response = NULL;
 5156     return ptp_transaction (params, &ptp, PTP_DP_GETDATA, 0, response, size);
 5157 }
 5158 
 5159 /****** CHDK interface ******/
 5160 
 5161 uint16_t
 5162 ptp_chdk_get_memory(PTPParams* params, int start, int num, unsigned char **buf)
 5163 {
 5164     PTPContainer ptp;
 5165 
 5166     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_GetMemory, start, num);
 5167     return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, buf, NULL);
 5168 }
 5169 
 5170 uint16_t
 5171 ptp_chdk_set_memory_long(PTPParams* params, int addr, int val)
 5172 {
 5173     PTPContainer ptp;
 5174     unsigned char *buf = (unsigned char *) &val; /* FIXME ... endianness? */
 5175 
 5176     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_SetMemory, addr, 4);
 5177     return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, 4, &buf, NULL);
 5178 }
 5179 
 5180 uint16_t
 5181 ptp_chdk_download(PTPParams* params, char *remote_fn, PTPDataHandler *handler)
 5182 {
 5183     PTPContainer ptp;
 5184 
 5185     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_TempData, 0);
 5186     CHECK_PTP_RC (ptp_transaction(params, &ptp, PTP_DP_SENDDATA, strlen(remote_fn), (unsigned char**)&remote_fn, NULL));
 5187 
 5188     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_DownloadFile);
 5189     return ptp_transaction_new (params, &ptp, PTP_DP_GETDATA, 0, handler);
 5190 }
 5191 
 5192 #if 0
 5193 int ptp_chdk_upload(PTPParams* params, char *local_fn, char *remote_fn)
 5194 {
 5195   uint16_t ret;
 5196   PTPContainer ptp;
 5197   char *buf = NULL;
 5198   FILE *f;
 5199   unsigned file_len,data_len,file_name_len;
 5200 
 5201   PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_UploadFile);
 5202 
 5203   f = fopen(local_fn,"rb");
 5204   if ( f == NULL )
 5205   {
 5206     ptp_error(params,"could not open file \'%s\'",local_fn);
 5207     return 0;
 5208   }
 5209 
 5210   fseek(f,0,SEEK_END);
 5211   file_len = ftell(f);
 5212   fseek(f,0,SEEK_SET);
 5213 
 5214   file_name_len = strlen(remote_fn);
 5215   data_len = 4 + file_name_len + file_len;
 5216   buf = malloc(data_len);
 5217   memcpy(buf,&file_name_len,4);
 5218   memcpy(buf+4,remote_fn,file_name_len);
 5219   fread(buf+4+file_name_len,1,file_len,f);
 5220 
 5221   fclose(f);
 5222 
 5223   ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, data_len, &buf, NULL);
 5224 
 5225   free(buf);
 5226 
 5227   if ( ret != PTP_RC_OK )
 5228   {
 5229     ptp_error(params,"unexpected return code 0x%x",ret);
 5230     return 0;
 5231   }
 5232   return 1;
 5233 }
 5234 
 5235 #endif
 5236 
 5237 /*
 5238  * Preliminary remote capture over USB code. Corresponding CHDK code is in the ptp-remote-capture-test
 5239  * This is under development and should not be included in builds for general distribution
 5240  */
 5241 /*
 5242  * isready: 0: not ready, lowest 2 bits: available image formats, 0x10000000: error
 5243  */
 5244 uint16_t
 5245 ptp_chdk_rcisready(PTPParams* params, int *isready, int *imgnum)
 5246 {
 5247     PTPContainer ptp;
 5248 
 5249     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_RemoteCaptureIsReady);
 5250     *isready = *imgnum = 0;
 5251     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 5252     *isready=ptp.Param1;
 5253     *imgnum=ptp.Param2;
 5254     return PTP_RC_OK;
 5255 }
 5256 
 5257 uint16_t
 5258 ptp_chdk_rcgetchunk(PTPParams* params, int fmt, ptp_chdk_rc_chunk *chunk)
 5259 {
 5260     PTPContainer ptp;
 5261 
 5262     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_RemoteCaptureGetData, fmt); //get chunk
 5263 
 5264     chunk->data = NULL;
 5265     chunk->size = 0;
 5266     chunk->offset = 0;
 5267     chunk->last = 0;
 5268     // TODO should allow ptp_getdata_transaction to send chunks directly to file, or to mem
 5269     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &chunk->data, NULL));
 5270     chunk->size = ptp.Param1;
 5271     chunk->last = (ptp.Param2 == 0);
 5272     chunk->offset = ptp.Param3; //-1 for none
 5273     return PTP_RC_OK;
 5274 }
 5275 
 5276 uint16_t
 5277 ptp_chdk_exec_lua(PTPParams* params, char *script, int flags, int *script_id, int *status)
 5278 {
 5279     PTPContainer ptp;
 5280 
 5281     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_ExecuteScript, PTP_CHDK_SL_LUA | flags);
 5282     *script_id = 0;
 5283     *status = 0;
 5284     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_SENDDATA, strlen(script)+1, (unsigned char**)&script, NULL));
 5285     *script_id = ptp.Param1;
 5286     *status = ptp.Param2;
 5287     return PTP_RC_OK;
 5288 }
 5289 
 5290 uint16_t
 5291 ptp_chdk_get_version(PTPParams* params, int *major, int *minor)
 5292 {
 5293     PTPContainer ptp;
 5294 
 5295     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_Version);
 5296     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 5297     *major = ptp.Param1;
 5298     *minor = ptp.Param2;
 5299     return PTP_RC_OK;
 5300 }
 5301 
 5302 uint16_t
 5303 ptp_chdk_get_script_status(PTPParams* params, unsigned *status)
 5304 {
 5305     PTPContainer ptp;
 5306 
 5307     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_ScriptStatus);
 5308     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 5309     *status = ptp.Param1;
 5310     return PTP_RC_OK;
 5311 }
 5312 uint16_t
 5313 ptp_chdk_get_script_support(PTPParams* params, unsigned *status)
 5314 {
 5315     PTPContainer ptp;
 5316 
 5317     PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_ScriptSupport);
 5318     CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL));
 5319     *status = ptp.Param1;
 5320     return PTP_RC_OK;
 5321 }
 5322