"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/camlibs/ptp2/usb.c" (29 Oct 2020, 24585 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 "usb.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 /* usb.c
    2  *
    3  * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
    4  * Copyright (C) 2003-2016 Marcus Meissner <marcus@jet.franken.de>
    5  * Copyright (C) 2003-2017 Marcus Meissner <marcus@jet.franken.de>
    6  * Copyright (C) 2006-2007 Linus Walleij <triad@df.lth.se>
    7  *
    8  * This library is free software; you can redistribute it and/or
    9  * modify it under the terms of the GNU Lesser General Public
   10  * License as published by the Free Software Foundation; either
   11  * version 2 of the License, or (at your option) any later version.
   12  *
   13  * This library is distributed in the hope that it will be useful,
   14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   16  * Lesser General Public License for more details.
   17  *
   18  * You should have received a copy of the GNU Lesser General Public
   19  * License along with this library; if not, write to the
   20  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   21  * Boston, MA  02110-1301  USA
   22  */
   23 
   24 #define _DEFAULT_SOURCE
   25 #include <config.h>
   26 #include "ptp.h"
   27 #include "ptp-private.h"
   28 #include "ptp-bugs.h"
   29 
   30 #include <stdlib.h>
   31 #include <stdarg.h>
   32 #include <stdio.h>
   33 #include <string.h>
   34 
   35 #include <gphoto2/gphoto2-library.h>
   36 #include <gphoto2/gphoto2-port-log.h>
   37 #include <gphoto2/gphoto2-setting.h>
   38 
   39 #ifdef ENABLE_NLS
   40 #  include <libintl.h>
   41 #  undef _
   42 #  define _(String) dgettext (PACKAGE, String)
   43 #  ifdef gettext_noop
   44 #    define N_(String) gettext_noop (String)
   45 #  else
   46 #    define N_(String) (String)
   47 #  endif
   48 #else
   49 #  define textdomain(String) (String)
   50 #  define gettext(String) (String)
   51 #  define dgettext(Domain,Message) (Message)
   52 #  define dcgettext(Domain,Message,Type) (Message)
   53 #  define bindtextdomain(Domain,Directory) (Domain)
   54 #  define _(String) (String)
   55 #  define N_(String) (String)
   56 #endif
   57 
   58 #define CONTEXT_BLOCK_SIZE  200000
   59 
   60 #define PTP_CNT_INIT(cnt) {memset(&cnt,0,sizeof(cnt));}
   61 
   62 /* PTP2_FAST_TIMEOUT: how long (in milliseconds) we should wait for
   63  * an URB to come back on an interrupt endpoint */
   64 /* 100 is not enough for various cameras types. 150 seems to work better */
   65 #define PTP2_FAST_TIMEOUT       150
   66 
   67 /* Pack / unpack functions */
   68 
   69 #include "ptp-pack.c"
   70 
   71 /* send / receive functions */
   72 
   73 uint16_t
   74 ptp_usb_sendreq (PTPParams* params, PTPContainer* req, int dataphase)
   75 {
   76     int res, towrite, do_retry = TRUE;
   77     PTPUSBBulkContainer usbreq;
   78     Camera *camera = ((PTPData *)params->data)->camera;
   79 
   80     switch (req->Nparam) {
   81     default:
   82     case 0: GP_LOG_D ("Sending PTP_OC 0x%0x (%s) request...", req->Code, ptp_get_opcode_name(params, req->Code));
   83         break;
   84     case 1: GP_LOG_D ("Sending PTP_OC 0x%0x (%s) (0x%x) request...", req->Code, ptp_get_opcode_name(params, req->Code), req->Param1);
   85         break;
   86     case 2: GP_LOG_D ("Sending PTP_OC 0x%0x (%s) (0x%x,0x%x) request...", req->Code, ptp_get_opcode_name(params, req->Code), req->Param1, req->Param2);
   87         break;
   88     case 3: GP_LOG_D ("Sending PTP_OC 0x%0x (%s) (0x%x,0x%x,0x%x) request...", req->Code, ptp_get_opcode_name(params, req->Code), req->Param1, req->Param2, req->Param3);
   89         break;
   90     }
   91 
   92     /* build appropriate USB container */
   93     usbreq.length=htod32(PTP_USB_BULK_REQ_LEN-
   94         (sizeof(uint32_t)*(5-req->Nparam)));
   95     usbreq.type=htod16(PTP_USB_CONTAINER_COMMAND);
   96     usbreq.code=htod16(req->Code);
   97     usbreq.trans_id=htod32(req->Transaction_ID);
   98     usbreq.payload.params.param1=htod32(req->Param1);
   99     usbreq.payload.params.param2=htod32(req->Param2);
  100     usbreq.payload.params.param3=htod32(req->Param3);
  101     usbreq.payload.params.param4=htod32(req->Param4);
  102     usbreq.payload.params.param5=htod32(req->Param5);
  103     /* send it to responder */
  104     towrite = PTP_USB_BULK_REQ_LEN-(sizeof(uint32_t)*(5-req->Nparam));
  105 retry:
  106     res = gp_port_write (camera->port, (char*)&usbreq, towrite);
  107     if (res != towrite) {
  108         if (res < 0) {
  109             GP_LOG_E ("PTP_OC 0x%04x sending req failed: %s (%d)", req->Code, gp_port_result_as_string(res), res);
  110             if (res == GP_ERROR_IO_WRITE && do_retry) {
  111                 GP_LOG_D ("Clearing halt on OUT EP and retrying once.");
  112                 gp_port_usb_clear_halt (camera->port, GP_PORT_USB_ENDPOINT_OUT);
  113                 do_retry = FALSE;
  114                 goto retry;
  115             }
  116         } else
  117             GP_LOG_E ("PTP_OC 0x%04x sending req failed: wrote only %d of %d bytes", req->Code, res, towrite);
  118         return translate_gp_result_to_ptp(res);
  119     }
  120     return PTP_RC_OK;
  121 }
  122 
  123 uint16_t
  124 ptp_usb_senddata (PTPParams* params, PTPContainer* ptp,
  125           uint64_t size, PTPDataHandler *handler
  126 ) {
  127     uint16_t ret = PTP_RC_OK;
  128     int res, wlen;
  129     unsigned long datawlen;
  130     PTPUSBBulkContainer usbdata;
  131     unsigned long bytes_left_to_transfer, written;
  132     Camera *camera = ((PTPData *)params->data)->camera;
  133     unsigned char *bytes;
  134     int progressid = 0;
  135     int usecontext = (size > CONTEXT_BLOCK_SIZE);
  136     GPContext *context = ((PTPData *)params->data)->context;
  137 
  138     GP_LOG_D ("Sending PTP_OC 0x%0x (%s) data...", ptp->Code, ptp_get_opcode_name(params, ptp->Code));
  139     /* build appropriate USB container */
  140     usbdata.length  = htod32(PTP_USB_BULK_HDR_LEN+size);
  141     usbdata.type    = htod16(PTP_USB_CONTAINER_DATA);
  142     usbdata.code    = htod16(ptp->Code);
  143     usbdata.trans_id= htod32(ptp->Transaction_ID);
  144 
  145     if (params->split_header_data) {
  146         datawlen = 0;
  147         wlen = PTP_USB_BULK_HDR_LEN;
  148     } else {
  149         unsigned long gotlen;
  150         /* For all camera devices. */
  151         datawlen = (size<PTP_USB_BULK_PAYLOAD_LEN_WRITE)?size:PTP_USB_BULK_PAYLOAD_LEN_WRITE;
  152         wlen = PTP_USB_BULK_HDR_LEN + datawlen;
  153         ret = handler->getfunc(params, handler->priv, datawlen, usbdata.payload.data, &gotlen);
  154         if (ret != PTP_RC_OK)
  155             return ret;
  156         if (gotlen != datawlen)
  157             return PTP_RC_GeneralError;
  158     }
  159     res = gp_port_write (camera->port, (char*)&usbdata, wlen);
  160     if (res != wlen) {
  161         if (res < 0)
  162             GP_LOG_E ("PTP_OC 0x%04x sending data failed: %s (%d)", ptp->Code, gp_port_result_as_string(res), res);
  163         else
  164             GP_LOG_E ("PTP_OC 0x%04x sending data failed: wrote only %d of %d bytes", ptp->Code, res, wlen);
  165         return translate_gp_result_to_ptp(res);
  166     }
  167     if (size <= datawlen) { /* nothing more to do */
  168         written = wlen;
  169         goto finalize;
  170     }
  171     if (usecontext)
  172         progressid = gp_context_progress_start (context, (size/CONTEXT_BLOCK_SIZE), _("Uploading..."));
  173     bytes = malloc (4096);
  174     if (!bytes)
  175         return PTP_RC_GeneralError;
  176     /* if everything OK send the rest */
  177     bytes_left_to_transfer = size-datawlen;
  178     ret = PTP_RC_OK;
  179     written = 0;
  180     while(bytes_left_to_transfer > 0) {
  181         unsigned long readlen, toread, oldwritten = written;
  182 
  183         toread = 4096;
  184         if (toread > bytes_left_to_transfer)
  185             toread = bytes_left_to_transfer;
  186         ret = handler->getfunc (params, handler->priv, toread, bytes, &readlen);
  187         if (ret != PTP_RC_OK)
  188             break;
  189         res = gp_port_write (camera->port, (char*)bytes, readlen);
  190         if (res < 0) {
  191             ret = translate_gp_result_to_ptp(res);
  192             break;
  193         }
  194         bytes_left_to_transfer -= res;
  195         written += res;
  196         if (usecontext && (oldwritten/CONTEXT_BLOCK_SIZE < written/CONTEXT_BLOCK_SIZE))
  197             gp_context_progress_update (context, progressid, written/CONTEXT_BLOCK_SIZE);
  198 #if 0 /* Does not work this way... Hmm. */
  199         if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL) {
  200             ret = ptp_usb_control_cancel_request (params,ptp->Transaction_ID);
  201             if (ret == PTP_RC_OK)
  202                 ret = PTP_ERROR_CANCEL;
  203             break;
  204         }
  205 #endif
  206     }
  207     if (usecontext)
  208         gp_context_progress_stop (context, progressid);
  209     free (bytes);
  210 finalize:
  211     if ((ret == PTP_RC_OK) && ((written % params->maxpacketsize) == 0))
  212         gp_port_write (camera->port, "x", 0);
  213     if ((ret!=PTP_RC_OK) && (ret!=PTP_ERROR_CANCEL))
  214         ret = PTP_ERROR_IO;
  215     return ret;
  216 }
  217 
  218 static uint16_t
  219 ptp_usb_getpacket(PTPParams *params, PTPUSBBulkContainer *packet, uint32_t maxsize, uint32_t *rlen)
  220 {
  221     int     tries = 0, result;
  222     Camera      *camera = ((PTPData *)params->data)->camera;
  223 
  224     /* read the header and potentially the first data */
  225     if (params->response_packet_size > 0) {
  226         GP_LOG_D ("Returning previously buffered response packet.");
  227         /* If there is a buffered packet, just use it. */
  228 
  229         if (params->response_packet_size > maxsize)
  230             params->response_packet_size = maxsize;
  231 
  232         memcpy(packet, params->response_packet, params->response_packet_size);
  233         *rlen = params->response_packet_size;
  234         free(params->response_packet);
  235         params->response_packet = NULL;
  236         params->response_packet_size = 0;
  237         /* Here this signifies a "virtual read" */
  238         return PTP_RC_OK;
  239     }
  240 retry:
  241     /* A packet should come in a single read always. */
  242     result = gp_port_read (camera->port, (char*)packet, maxsize);
  243     /* This might be a left over zero-write of the device at the end of the previous transmission */
  244     if (result == 0)
  245         result = gp_port_read (camera->port, (char*)packet, maxsize);
  246     if (result > 0) {
  247         *rlen = result;
  248         return PTP_RC_OK;
  249     }
  250     if (result == GP_ERROR_IO_READ) {
  251         GP_LOG_D ("Clearing halt on IN EP and retrying once.");
  252         gp_port_usb_clear_halt (camera->port, GP_PORT_USB_ENDPOINT_IN);
  253         /* retrying only makes sense if we did not read anything yet */
  254         if (tries++ < 1)
  255             goto retry;
  256     }
  257     return translate_gp_result_to_ptp(result);
  258 }
  259 
  260 #define READLEN 512*1024 /* read blob size, mostly to avoid reading all of it at once. */
  261 
  262 uint16_t
  263 ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler)
  264 {
  265     uint16_t ret;
  266     PTPUSBBulkContainer usbdata;
  267     unsigned char   *data = NULL;
  268     uint32_t    bytes_to_read, bytes_read;
  269     Camera      *camera = ((PTPData *)params->data)->camera;
  270     int     report_progress, progress_id = 0, do_retry = TRUE, res = GP_OK;
  271     GPContext *context = ((PTPData *)params->data)->context;
  272 
  273     GP_LOG_D ("Reading PTP_OC 0x%0x (%s) data...", ptp->Code, ptp_get_opcode_name(params, ptp->Code));
  274     PTP_CNT_INIT(usbdata);
  275 
  276     ret = ptp_usb_getpacket (params, &usbdata, sizeof(usbdata), &bytes_read);
  277     if (ret != PTP_RC_OK)
  278         goto exit;
  279 
  280     if (bytes_read < PTP_USB_BULK_HDR_LEN) {
  281         GP_LOG_E ("Read short bulk packet in data phase %d vs %d vs min len %d", bytes_read, dtoh32(usbdata.length), (uint32_t)PTP_USB_BULK_HDR_LEN);
  282         ret = PTP_ERROR_IO;
  283         goto exit;
  284     }
  285 
  286     if (dtoh16(usbdata.type) != PTP_USB_CONTAINER_DATA) {
  287         /* We might have got a response instead. On error for instance. */
  288         if (dtoh16(usbdata.type) == PTP_USB_CONTAINER_RESPONSE) {
  289             /* responses are short and we should have it as-is right now */
  290             if (bytes_read != dtoh32(usbdata.length)) {
  291                 GP_LOG_E ("Read broken ptp response in data phase, read %d vs %d", bytes_read, dtoh32(usbdata.length));
  292                 ret = PTP_ERROR_IO;
  293                 goto exit;
  294             }
  295             if (dtoh32(usbdata.length) > sizeof(usbdata)) {
  296                 GP_LOG_E ("Read too large ptp response in data phase, packet %d bytes large", dtoh32(usbdata.length));
  297                 ret = PTP_ERROR_IO;
  298                 goto exit;
  299             }
  300             /* FIXME: maximum size of response packet perhaps ? */
  301             params->response_packet = malloc(dtoh32(usbdata.length));
  302             if (!params->response_packet) return PTP_RC_GeneralError;
  303             memcpy(params->response_packet, (uint8_t *) &usbdata, dtoh32(usbdata.length));
  304             params->response_packet_size = dtoh32(usbdata.length);
  305             ret = PTP_RC_OK;
  306         } else {
  307             ret = PTP_ERROR_DATA_EXPECTED;
  308         }
  309         goto exit;
  310     }
  311     if (dtoh16(usbdata.code)!=ptp->Code) {
  312         /* A creative Zen device breaks down here, by leaving out
  313              * Code and Transaction ID */
  314         if (MTP_ZEN_BROKEN_HEADER(params)) {
  315             GP_LOG_D ("Read broken PTP header (Code is %04x vs %04x), compensating.",
  316                   dtoh16(usbdata.code), ptp->Code);
  317             usbdata.code = dtoh16(ptp->Code);
  318             usbdata.trans_id = htod32(ptp->Transaction_ID);
  319         } else {
  320             GP_LOG_E ("Read broken PTP header (Code is %04x vs %04x).",
  321                   dtoh16(usbdata.code), ptp->Code );
  322 
  323             ret = PTP_ERROR_IO;
  324 
  325             /* if this is a valid packet that came late, drain it to allow reestablishing */
  326 
  327             if (bytes_read >= dtoh32(usbdata.length))
  328                 goto exit;
  329 
  330             bytes_to_read = dtoh32(usbdata.length) - bytes_read;
  331             bytes_read -= PTP_USB_BULK_HDR_LEN;
  332 
  333             data = malloc(READLEN);
  334             if (!data) goto exit;
  335             while (bytes_to_read > 0) {
  336                 unsigned long chunk_to_read = bytes_to_read;
  337 
  338                 /* if in read-until-short-packet mode, read one packet at a time */
  339                 /* else read in large blobs */
  340                 /* else read all but the last short packet depending on EP packetsize. */
  341                 if (chunk_to_read > READLEN)
  342                     chunk_to_read = READLEN;
  343                 else if (chunk_to_read > params->maxpacketsize)
  344                     chunk_to_read = chunk_to_read - (chunk_to_read % params->maxpacketsize);
  345                 res = gp_port_read (camera->port, (char*)data, chunk_to_read);
  346                 if (res == GP_ERROR_IO_READ)
  347                     break;
  348                 if (res <= 0)
  349                     break;
  350                 bytes_to_read -= res;
  351                 bytes_read += res;
  352             }
  353             free (data);
  354             data = NULL;
  355             goto exit;
  356         }
  357     }
  358     if (bytes_read > dtoh32(usbdata.length)) {
  359         /*
  360          * Buffer the surplus response packet if it is >=
  361          * PTP_USB_BULK_HDR_LEN
  362          * (i.e. it is probably an entire package)
  363          * else discard it as erroneous surplus data.
  364          * This will even work if more than 2 packets appear
  365          * in the same transaction, they will just be handled
  366          * iteratively.
  367          *
  368          * Marcus observed stray bytes on iRiver devices;
  369          * these are still discarded.
  370          */
  371         uint32_t surplen = bytes_read - dtoh32(usbdata.length);
  372 
  373         if (surplen >= PTP_USB_BULK_HDR_LEN) {
  374             params->response_packet = malloc(surplen);
  375             if (!params->response_packet) return PTP_RC_GeneralError;
  376             memcpy(params->response_packet, (uint8_t *) &usbdata + dtoh32(usbdata.length), surplen);
  377             params->response_packet_size = surplen;
  378         } else {
  379             GP_LOG_D ("Read %ld bytes too much, expect problems!",
  380                   (long)(bytes_read - dtoh32(usbdata.length)));
  381         }
  382         bytes_read = dtoh32(usbdata.length);
  383     }
  384 
  385     /* For most PTP devices rlen is 512 == sizeof(usbdata)
  386      * here. For MTP devices splitting header and data it might
  387      * be PTP_USB_BULK_HDR_LEN (12).
  388      */
  389     /* autodetect split header/data MTP devices */
  390     if (dtoh32(usbdata.length) > PTP_USB_BULK_HDR_LEN && (bytes_read==PTP_USB_BULK_HDR_LEN))
  391         params->split_header_data = 1;
  392 
  393     /* Copy the payload bytes we already read (with the first usb packet) */
  394     ret = handler->putfunc (params, handler->priv, bytes_read - PTP_USB_BULK_HDR_LEN, usbdata.payload.data);
  395     if (ret != PTP_RC_OK)
  396         goto exit;
  397 
  398     /* Check if we are done already... */
  399     if (bytes_read >= dtoh32(usbdata.length))
  400         goto exit;
  401 
  402     /* If not read the rest of it. */
  403     /* Make bytes_to_read contain the number of remaining payload-bytes to read. */
  404     bytes_to_read = dtoh32(usbdata.length) - bytes_read;
  405     /* Make bytes_read contain the number of payload-bytes already read. */
  406     bytes_read -= PTP_USB_BULK_HDR_LEN;
  407 
  408     data = malloc(READLEN);
  409     if (!data) return PTP_RC_GeneralError;
  410 
  411     report_progress = (bytes_to_read > 2*CONTEXT_BLOCK_SIZE) && (dtoh32(usbdata.length) != 0xffffffffU);
  412 
  413     /* On partial reads, do not report progress, this might lead to flickering progress bars.
  414      * FIXME: would be better to pass in a flag
  415      */
  416     if (    (ptp->Code == PTP_OC_GetPartialObject)                  ||
  417         (   (params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON)  &&
  418             (   (ptp->Code == PTP_OC_CANON_EOS_GetPartialObject)    ||
  419                 (ptp->Code == PTP_OC_CANON_EOS_GetPartialObject64)  ||
  420                 (ptp->Code == PTP_OC_CANON_EOS_GetPartialObjectEx)  ||
  421                 (ptp->Code == PTP_OC_CANON_EOS_GetPartialObjectEX64)
  422             )
  423         )                                   ||
  424         (ptp->Code == PTP_OC_ANDROID_GetPartialObject64)
  425     )
  426         report_progress = 0;
  427 
  428     if (report_progress)
  429         progress_id = gp_context_progress_start (context, (bytes_to_read/CONTEXT_BLOCK_SIZE), _("Downloading..."));
  430     while (bytes_to_read > 0) {
  431         unsigned long chunk_to_read = bytes_to_read;
  432 
  433         /* if in read-until-short-packet mode, read one packet at a time */
  434         /* else read in large blobs */
  435         /* else read all but the last short packet depending on EP packetsize. */
  436         if (dtoh32(usbdata.length) == 0xffffffffU)
  437             chunk_to_read = PTP_USB_BULK_HS_MAX_PACKET_LEN_READ;
  438         else if (chunk_to_read > READLEN)
  439             chunk_to_read = READLEN;
  440         else if (chunk_to_read > params->maxpacketsize)
  441             chunk_to_read = chunk_to_read - (chunk_to_read % params->maxpacketsize);
  442         res = gp_port_read (camera->port, (char*)data, chunk_to_read);
  443         if (res == GP_ERROR_IO_READ && do_retry) {
  444             GP_LOG_D ("Clearing halt on IN EP and retrying once.");
  445             gp_port_usb_clear_halt (camera->port, GP_PORT_USB_ENDPOINT_IN);
  446             /* retrying only once and only if we did not read anything yet */
  447             do_retry = FALSE;
  448             continue;
  449         } else if (res <= 0) {
  450             ret = translate_gp_result_to_ptp(res);
  451             break;
  452         } else
  453             do_retry = FALSE; /* once we have successfully read any data, don't try again */
  454         ret = handler->putfunc (params, handler->priv, res, data);
  455         if (ret != PTP_RC_OK)
  456             break;
  457         if (dtoh32(usbdata.length) == 0xffffffffU) {
  458             /* once we have read a short packet, we are done. */
  459             if (res < PTP_USB_BULK_HS_MAX_PACKET_LEN_READ)
  460                 bytes_to_read = 0;
  461         } else
  462             bytes_to_read -= res;
  463         bytes_read += res;
  464         if (report_progress && ((bytes_read-res)/CONTEXT_BLOCK_SIZE < bytes_read/CONTEXT_BLOCK_SIZE))
  465             gp_context_progress_update (context, progress_id, bytes_read/CONTEXT_BLOCK_SIZE);
  466         /* Only cancel transfers larger than 1MB. as
  467          * canceling did not work on eos_get_viewfinder of 200kb */
  468         if ((bytes_read > 1024*1024) && gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL) {
  469             ret = PTP_ERROR_CANCEL;
  470             break;
  471         }
  472     }
  473     if (report_progress)
  474         gp_context_progress_stop (context, progress_id);
  475 
  476 exit:
  477     free (data);
  478 
  479     if ((ret!=PTP_RC_OK) && (ret!=PTP_ERROR_CANCEL)) {
  480         GP_LOG_E ("PTP_OC 0x%04x receiving data failed: %s (0x%04x)", ptp->Code, ptp_strerror(ret, params->deviceinfo.VendorExtensionID), ret);
  481         return PTP_ERROR_IO;
  482     }
  483     return ret;
  484 }
  485 
  486 uint16_t
  487 ptp_usb_getresp (PTPParams* params, PTPContainer* resp)
  488 {
  489     uint16_t        ret;
  490     uint32_t        rlen;
  491     PTPUSBBulkContainer usbresp;
  492     /*GPContext     *context = ((PTPData *)params->data)->context;*/
  493 
  494     GP_LOG_D ("Reading PTP_OC 0x%0x (%s) response...", resp->Code, ptp_get_opcode_name(params, resp->Code));
  495     PTP_CNT_INIT(usbresp);
  496     /* read response, it should never be longer than sizeof(usbresp) */
  497     ret = ptp_usb_getpacket(params, &usbresp, sizeof(usbresp), &rlen);
  498 
  499     if (ret!=PTP_RC_OK) {
  500         ret = PTP_ERROR_IO;
  501     } else
  502     if (rlen < 12) {
  503         ret = PTP_ERROR_IO;
  504     } else
  505     if (rlen != dtoh32(usbresp.length)) {
  506         ret = PTP_ERROR_IO;
  507     } else
  508     if (dtoh16(usbresp.type)!=PTP_USB_CONTAINER_RESPONSE) {
  509         ret = PTP_ERROR_RESP_EXPECTED;
  510     } else
  511     if (dtoh16(usbresp.code)!=resp->Code) {
  512         ret = dtoh16(usbresp.code);
  513     }
  514     if (ret!=PTP_RC_OK) {
  515         GP_LOG_E ("PTP_OC 0x%04x receiving resp failed: %s (0x%04x)", resp->Code, ptp_strerror(ret, params->deviceinfo.VendorExtensionID), ret);
  516         return ret;
  517     }
  518     /* build an appropriate PTPContainer */
  519     resp->Code=dtoh16(usbresp.code);
  520     resp->SessionID=params->session_id;
  521     resp->Transaction_ID=dtoh32(usbresp.trans_id);
  522     if (resp->Transaction_ID != params->transaction_id - 1) {
  523         if (MTP_ZEN_BROKEN_HEADER(params)) {
  524             GP_LOG_D ("Read broken PTP header (transid is %08x vs %08x), compensating.",
  525                   resp->Transaction_ID, params->transaction_id - 1
  526             );
  527             resp->Transaction_ID=params->transaction_id-1;
  528         }
  529         /* else will be handled by ptp.c as error. */
  530     }
  531     resp->Nparam=(rlen-12)/4;
  532     resp->Param1=dtoh32(usbresp.payload.params.param1);
  533     resp->Param2=dtoh32(usbresp.payload.params.param2);
  534     resp->Param3=dtoh32(usbresp.payload.params.param3);
  535     resp->Param4=dtoh32(usbresp.payload.params.param4);
  536     resp->Param5=dtoh32(usbresp.payload.params.param5);
  537     return ret;
  538 }
  539 
  540 /* Event handling functions */
  541 
  542 /* PTP Events wait for or check mode */
  543 #define PTP_EVENT_CHECK         0x0000  /* waits for */
  544 #define PTP_EVENT_CHECK_FAST        0x0001  /* checks */
  545 #define PTP_EVENT_CHECK_QUEUE       0x0002  /* just looks in the queue */
  546 
  547 static inline uint16_t
  548 ptp_usb_event (PTPParams* params, PTPContainer* event, int wait)
  549 {
  550     int         result, timeout, fasttimeout;
  551     unsigned long       rlen;
  552     PTPUSBEventContainer    usbevent;
  553     Camera          *camera = ((PTPData *)params->data)->camera;
  554 
  555     if (params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON)
  556         fasttimeout = PTP2_FAST_TIMEOUT*2;
  557     else
  558         fasttimeout = PTP2_FAST_TIMEOUT;
  559 
  560     PTP_CNT_INIT(usbevent);
  561 
  562     if (event==NULL)
  563         return PTP_ERROR_BADPARAM;
  564 
  565     switch(wait) {
  566     case PTP_EVENT_CHECK:
  567         result = gp_port_check_int (camera->port, (char*)&usbevent, sizeof(usbevent));
  568         if (result <= 0) result = gp_port_check_int (camera->port, (char*)&usbevent, sizeof(usbevent));
  569         break;
  570     case PTP_EVENT_CHECK_FAST:
  571         gp_port_get_timeout (camera->port, &timeout);
  572         gp_port_set_timeout (camera->port, fasttimeout);
  573         result = gp_port_check_int (camera->port, (char*)&usbevent, sizeof(usbevent));
  574         if (result <= 0) result = gp_port_check_int (camera->port, (char*)&usbevent, sizeof(usbevent));
  575         gp_port_set_timeout (camera->port, timeout);
  576         break;
  577     case PTP_EVENT_CHECK_QUEUE:
  578         gp_port_get_timeout (camera->port, &timeout);
  579         gp_port_set_timeout (camera->port, 0); /* indicates no waiting at all */
  580         result = gp_port_check_int (camera->port, (char*)&usbevent, sizeof(usbevent));
  581         gp_port_set_timeout (camera->port, timeout);
  582         break;
  583     default:
  584         return PTP_ERROR_BADPARAM;
  585     }
  586     if (result < 0) {
  587         if ((result != GP_ERROR_TIMEOUT) || (wait != PTP_EVENT_CHECK_FAST))
  588             GP_LOG_E ("Reading PTP event failed: %s (%d)", gp_port_result_as_string(result), result);
  589         return translate_gp_result_to_ptp(result);
  590     }
  591     if (result == 0) {
  592         GP_LOG_E ("Reading PTP event failed: a 0 read occurred, assuming timeout.");
  593         return PTP_ERROR_TIMEOUT;
  594     }
  595     rlen = result;
  596     if (rlen < 8) {
  597         GP_LOG_E ("Reading PTP event failed: only %ld bytes read", rlen);
  598         return PTP_ERROR_IO;
  599     }
  600 
  601     /* Only do the additional reads for "events". Canon IXUS 2 likes to
  602      * send unrelated data.
  603      */
  604     if (    (dtoh16(usbevent.type) == PTP_USB_CONTAINER_EVENT) &&
  605         (dtoh32(usbevent.length) > rlen)
  606     ) {
  607         GP_LOG_D ("Canon incremental read (done: %ld, todo: %d)", rlen, dtoh32(usbevent.length));
  608         gp_port_get_timeout (camera->port, &timeout);
  609         gp_port_set_timeout (camera->port, PTP2_FAST_TIMEOUT);
  610         while (dtoh32(usbevent.length) > rlen) {
  611             result = gp_port_check_int (camera->port, ((char*)&usbevent)+rlen, sizeof(usbevent)-rlen);
  612             if (result <= 0)
  613                 break;
  614             rlen += result;
  615         }
  616         gp_port_set_timeout (camera->port, timeout);
  617     }
  618     /* if we read anything over interrupt endpoint it must be an event */
  619     /* build an appropriate PTPContainer */
  620     event->Nparam  = (rlen-12)/4;
  621     event->Code   = dtoh16(usbevent.code);
  622     event->SessionID=params->session_id;
  623     event->Transaction_ID=dtoh32(usbevent.trans_id);
  624     event->Param1 = dtoh32(usbevent.param1);
  625     event->Param2 = dtoh32(usbevent.param2);
  626     event->Param3 = dtoh32(usbevent.param3);
  627     return PTP_RC_OK;
  628 }
  629 
  630 uint16_t
  631 ptp_usb_event_check_queue (PTPParams* params, PTPContainer* event) {
  632 
  633     return ptp_usb_event (params, event, PTP_EVENT_CHECK_QUEUE);
  634 }
  635 
  636 uint16_t
  637 ptp_usb_event_check (PTPParams* params, PTPContainer* event) {
  638 
  639     return ptp_usb_event (params, event, PTP_EVENT_CHECK_FAST);
  640 }
  641 
  642 uint16_t
  643 ptp_usb_event_wait (PTPParams* params, PTPContainer* event) {
  644 
  645     return ptp_usb_event (params, event, PTP_EVENT_CHECK);
  646 }
  647 
  648 uint16_t
  649 ptp_usb_control_get_extended_event_data (PTPParams *params, char *buffer, int *size) {
  650     Camera      *camera = ((PTPData *)params->data)->camera;
  651     int     ret;
  652     GPPortSettings  settings;
  653 
  654     GP_LOG_D ("Getting extended event data.");
  655     gp_port_get_settings (camera->port, &settings);
  656     ret = gp_port_usb_msg_class_read (camera->port, 0x65, 0x0000, settings.usb.interface, buffer, *size);
  657     if (ret < GP_OK)
  658         return PTP_ERROR_IO;
  659     *size = ret;
  660     return PTP_RC_OK;
  661 }
  662 
  663 uint16_t
  664 ptp_usb_control_device_reset_request (PTPParams *params) {
  665     Camera      *camera = ((PTPData *)params->data)->camera;
  666     int     ret;
  667     GPPortSettings  settings;
  668 
  669     GP_LOG_D ("Sending usb device reset request.");
  670     gp_port_get_settings (camera->port, &settings);
  671     ret = gp_port_usb_msg_class_write (camera->port, 0x66, 0x0000, settings.usb.interface, NULL, 0);
  672     if (ret < GP_OK)
  673         return PTP_ERROR_IO;
  674     return PTP_RC_OK;
  675 }
  676 
  677 uint16_t
  678 ptp_usb_control_get_device_status (PTPParams *params, char *buffer, int *size) {
  679     Camera      *camera = ((PTPData *)params->data)->camera;
  680     int     ret;
  681     GPPortSettings  settings;
  682 
  683     GP_LOG_D ("Getting usb device status.");
  684     gp_port_get_settings (camera->port, &settings);
  685     ret = gp_port_usb_msg_class_read (camera->port, 0x67, 0x0000, settings.usb.interface, buffer, *size);
  686     if (ret < GP_OK)
  687         return PTP_ERROR_IO;
  688     *size = ret;
  689     return PTP_RC_OK;
  690 }
  691 
  692 uint16_t
  693 ptp_usb_control_cancel_request (PTPParams *params, uint32_t transactionid) {
  694     Camera      *camera = ((PTPData *)params->data)->camera;
  695     int     ret;
  696     unsigned char   buffer[6];
  697     GPPortSettings  settings;
  698 
  699     GP_LOG_D ("Sending cancel request.");
  700     gp_port_get_settings (camera->port, &settings);
  701 
  702     htod16a(&buffer[0],PTP_EC_CancelTransaction);
  703     htod32a(&buffer[2],transactionid);
  704     ret = gp_port_usb_msg_class_write (camera->port, 0x64, 0x0000, settings.usb.interface, (char*)buffer, sizeof (buffer));
  705     if (ret < GP_OK)
  706         return PTP_ERROR_IO;
  707     return PTP_RC_OK;
  708 }