"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/camlibs/ptp2/fujiptpip.c" (14 Feb 2021, 27173 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 "fujiptpip.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 /* fujiptpip.c
    2  *
    3  * Copyright (C) 2020 Marcus Meissner <marcus@jet.franken.de>
    4  *
    5  * This library is free software; you can redistribute it and/or
    6  * modify it under the terms of the GNU Lesser General Public
    7  * License as published by the Free Software Foundation; either
    8  * version 2 of the License, or (at your option) any later version.
    9  *
   10  * This library is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13  * Lesser General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU Lesser General Public
   16  * License along with this library; if not, write to the
   17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   18  * Boston, MA  02110-1301  USA
   19  */
   20 /*
   21  * This is a copy of ptpip.c...
   22  *
   23  * This is working, but might be buggy.
   24  *
   25  * Only the setup packet is similar to PTP/IP.
   26  * The rest speaks a protocol very like to the USB Bulk protocol.
   27  *
   28  * <32bit length> <16 bit transfertype> <16 bit code> <32bit transaction id> <...data...>
   29  *
   30  *
   31  * transfertype as usual:
   32  * - 1: send command (with optional parameters)
   33  * - 2: send data (data follows transid)
   34  * - 3: response (and optional parameters)
   35  * - 4: event (over event pipe)
   36  *
   37  * For JPEG pipe, also <length> <data...> blobs are sent. There is a 14 byte blob in front of the FF D8 start.
   38  *
   39  * There are 3 TCP pipes:
   40  * - command pipe , port 55740
   41  * - event pipe , port 55741 (camera remote port starts listen when you run "InitiateOpenCapture")
   42  * - jpeg pipe , port 55742 (camera remote port starts listen when you run "InitiateOpenCapture")
   43  */
   44 #define _DEFAULT_SOURCE
   45 #define _DARWIN_C_SOURCE
   46 #include "config.h"
   47 
   48 #include <stdlib.h>
   49 #include <string.h>
   50 #include <stdio.h>
   51 #include <time.h>
   52 #include <errno.h>
   53 #include <sys/types.h>
   54 #ifdef HAVE_SYS_SELECT_H
   55 #include <sys/select.h>
   56 #endif
   57 
   58 #ifdef WIN32
   59 # include <winsock2.h>
   60 # include <ws2tcpip.h>
   61 #else
   62 # include <sys/socket.h>
   63 # include <netinet/in.h>
   64 #endif
   65 #include "ptpip-private.h"
   66 
   67 #include <gphoto2/gphoto2-library.h>
   68 #include <gphoto2/gphoto2-port-log.h>
   69 #include <gphoto2/gphoto2-setting.h>
   70 
   71 #include "ptp.h"
   72 #include "ptp-private.h"
   73 
   74 #define PTPIP_VERSION_MAJOR 0x0001
   75 #define PTPIP_VERSION_MINOR 0x0000
   76 
   77 #ifdef ENABLE_NLS
   78 #  include <libintl.h>
   79 #  undef _
   80 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
   81 #  ifdef gettext_noop
   82 #    define N_(String) gettext_noop (String)
   83 #  else
   84 #    define N_(String) (String)
   85 #  endif
   86 #else
   87 #  define textdomain(String) (String)
   88 #  define gettext(String) (String)
   89 #  define dgettext(Domain,Message) (Message)
   90 #  define dcgettext(Domain,Message,Type) (Message)
   91 #  define bindtextdomain(Domain,Directory) (Domain)
   92 #  define _(String) (String)
   93 #  define N_(String) (String)
   94 #endif
   95 
   96 #include "ptp.h"
   97 #include "ptp-bugs.h"
   98 
   99 #include "ptp-pack.c"
  100 
  101 #define fujiptpip_len       0
  102 #define fujiptpip_type      4   /* not always present */
  103 
  104 #define fujiptpip_cmd_dataphase 4
  105 #define fujiptpip_cmd_code  6
  106 #define fujiptpip_cmd_transid   8
  107 #define fujiptpip_cmd_param1    12
  108 #define fujiptpip_cmd_param2    16
  109 #define fujiptpip_cmd_param3    20
  110 #define fujiptpip_cmd_param4    24
  111 #define fujiptpip_cmd_param5    28
  112 
  113 #define PTP_EVENT_CHECK         0x0000  /* waits for */
  114 #define PTP_EVENT_CHECK_FAST        0x0001  /* checks */
  115 static uint16_t ptp_fujiptpip_check_event (PTPParams* params);
  116 static uint16_t ptp_fujiptpip_event (PTPParams* params, PTPContainer* event, int wait);
  117 
  118 /* send / receive functions */
  119 uint16_t
  120 ptp_fujiptpip_sendreq (PTPParams* params, PTPContainer* req, int dataphase)
  121 {
  122     int     ret;
  123     int     len = fujiptpip_cmd_param1 +req->Nparam*4;
  124     unsigned char   *request = malloc(len);
  125 
  126     switch (req->Nparam) {
  127     default:
  128     case 0: GP_LOG_D ("Sending PTP_OC 0x%0x (%s) request...", req->Code, ptp_get_opcode_name(params, req->Code));
  129         break;
  130     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);
  131         break;
  132     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);
  133         break;
  134     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);
  135         break;
  136     }
  137 
  138     ptp_fujiptpip_check_event (params);
  139 
  140     /*htod32a(&request[ptpip_type],PTPIP_CMD_REQUEST);*/
  141     htod32a(&request[fujiptpip_len],len);
  142     /* sending data = 2, receiving data or no data = 1 */
  143     /*if ((dataphase&PTP_DP_DATA_MASK) == PTP_DP_SENDDATA)
  144         htod16a(&request[fujiptpip_cmd_dataphase],2);
  145     else*/
  146         htod16a(&request[fujiptpip_cmd_dataphase],1);
  147     htod16a(&request[fujiptpip_cmd_code],req->Code);
  148     htod32a(&request[fujiptpip_cmd_transid],req->Transaction_ID);
  149 
  150     switch (req->Nparam) {
  151     case 5: htod32a(&request[fujiptpip_cmd_param5],req->Param5);/* fallthrough */
  152     case 4: htod32a(&request[fujiptpip_cmd_param4],req->Param4);/* fallthrough */
  153     case 3: htod32a(&request[fujiptpip_cmd_param3],req->Param3);/* fallthrough */
  154     case 2: htod32a(&request[fujiptpip_cmd_param2],req->Param2);/* fallthrough */
  155     case 1: htod32a(&request[fujiptpip_cmd_param1],req->Param1);/* fallthrough */
  156     case 0:
  157     default:
  158         break;
  159     }
  160     GP_LOG_DATA ( (char*)request, len, "ptpip/oprequest data:");
  161     ret = write (params->cmdfd, request, len);
  162     free (request);
  163     if (ret == -1)
  164         perror ("sendreq/write to cmdfd");
  165     if (ret != len) {
  166         GP_LOG_E ("ptp_fujiptpip_sendreq() len =%d but ret=%d", len, ret);
  167         return PTP_RC_OK;
  168     }
  169     return PTP_RC_OK;
  170 }
  171 
  172 static uint16_t
  173 ptp_fujiptpip_generic_read (PTPParams *params, int fd, PTPIPHeader *hdr, unsigned char**data, int withtype) {
  174     int ret, len, curread;
  175     unsigned char *xhdr;
  176     unsigned int hdrlen;
  177 
  178     xhdr = (unsigned char*)hdr; curread = 0;
  179     hdrlen = len = sizeof (PTPIPHeader);
  180     if (!withtype)
  181         hdrlen = len = sizeof(uint32_t);
  182 
  183     while (curread < len) {
  184         ret = read (fd, xhdr + curread, len - curread);
  185         if (ret == -1) {
  186             perror ("read PTPIPHeader");
  187             return PTP_RC_GeneralError;
  188         }
  189         GP_LOG_DATA ((char*)xhdr+curread, ret, "ptpip/generic_read header:");
  190         curread += ret;
  191         if (ret == 0) {
  192             GP_LOG_E ("End of stream after reading %d bytes of ptpipheader", ret);
  193             return PTP_RC_GeneralError;
  194         }
  195     }
  196     len = dtoh32 (hdr->length) - hdrlen;
  197     if (len < 0) {
  198         GP_LOG_E ("len < 0, %d?", len);
  199         return PTP_RC_GeneralError;
  200     }
  201     *data = malloc (len);
  202     if (!*data) {
  203         GP_LOG_E ("malloc failed.");
  204         return PTP_RC_GeneralError;
  205     }
  206     curread = 0;
  207     while (curread < len) {
  208         ret = read (fd, (*data)+curread, len-curread);
  209         if (ret == -1) {
  210             GP_LOG_E ("error %d in reading PTPIP data", errno);
  211             free (*data);*data = NULL;
  212             return PTP_RC_GeneralError;
  213         } else {
  214             GP_LOG_DATA ((char*)((*data)+curread), ret, "ptpip/generic_read data:");
  215         }
  216         if (ret == 0)
  217             break;
  218         curread += ret;
  219     }
  220     if (curread != len) {
  221         GP_LOG_E ("read PTPIP data, ret %d vs len %d", ret, len);
  222         free (*data);*data = NULL;
  223         return PTP_RC_GeneralError;
  224     }
  225     return PTP_RC_OK;
  226 }
  227 
  228 static uint16_t
  229 ptp_fujiptpip_cmd_read (PTPParams* params, PTPIPHeader *hdr, unsigned char** data) {
  230     ptp_fujiptpip_check_event (params);
  231     return ptp_fujiptpip_generic_read (params, params->cmdfd, hdr, data, 0);
  232 }
  233 
  234 static uint16_t
  235 ptp_fujiptpip_evt_read (PTPParams* params, PTPIPHeader *hdr, unsigned char** data) {
  236     return ptp_fujiptpip_generic_read (params, params->evtfd, hdr, data, 0);
  237 }
  238 
  239 static uint16_t
  240 ptp_fujiptpip_jpg_read (PTPParams* params, PTPIPHeader *hdr, unsigned char** data) {
  241     return ptp_fujiptpip_generic_read (params, params->jpgfd, hdr, data, 0);
  242 }
  243 
  244 static uint16_t
  245 ptp_fujiptpip_check_event (PTPParams* params) {
  246     PTPContainer    event;
  247     uint16_t    ret;
  248 
  249     event.Code = 0;
  250     ret = ptp_fujiptpip_event (params, &event, PTP_EVENT_CHECK_FAST);
  251     if (ret != PTP_RC_OK)
  252         return ret;
  253     if (event.Code == 0)
  254         return ret;
  255     return ptp_add_event (params, &event);
  256 }
  257 
  258 #define fujiptpip_data_datatype     4
  259 #define fujiptpip_data_code     6
  260 #define fujiptpip_data_transid      8
  261 #define fujiptpip_data_payload      12
  262 
  263 #define WRITE_BLOCKSIZE 65536
  264 uint16_t
  265 ptp_fujiptpip_senddata (PTPParams* params, PTPContainer* ptp,
  266         uint64_t size, PTPDataHandler *handler
  267 ) {
  268     unsigned char   request[fujiptpip_data_payload];
  269     unsigned int    curwrite, towrite;
  270     int     ret;
  271     unsigned char*  xdata;
  272 
  273     GP_LOG_D ("Sending PTP_OC 0x%0x (%s) data...", ptp->Code, ptp_get_opcode_name(params, ptp->Code));
  274     //htod32a(&request[ptpip_type],PTPIP_START_DATA_PACKET);
  275     htod32a(&request[fujiptpip_len],sizeof(request)+size);
  276     htod16a(&request[fujiptpip_data_datatype],2);
  277     htod16a(&request[fujiptpip_data_code],ptp->Code);
  278     htod32a(&request[fujiptpip_data_transid],ptp->Transaction_ID);
  279     GP_LOG_DATA ((char*)request, sizeof(request), "ptpip/senddata header:");
  280     ret = write (params->cmdfd, request, sizeof(request));
  281     if (ret == -1)
  282         perror ("sendreq/write to cmdfd");
  283     if (ret != sizeof(request)) {
  284         GP_LOG_E ("ptp_fujiptpip_senddata() len=%d but ret=%d", (int)sizeof(request), ret);
  285         return PTP_RC_GeneralError;
  286     }
  287     xdata = malloc(WRITE_BLOCKSIZE);
  288     if (!xdata) return PTP_RC_GeneralError;
  289     curwrite = 0;
  290     while (curwrite < size) {
  291         unsigned long written, towrite2, xtowrite;
  292 
  293         ptp_fujiptpip_check_event (params);
  294 
  295         towrite = size - curwrite;
  296         if (towrite > WRITE_BLOCKSIZE) {
  297             towrite = WRITE_BLOCKSIZE;
  298         }
  299         ret = handler->getfunc (params, handler->priv, towrite, xdata, &xtowrite);
  300         if (ret == -1) {
  301             perror ("getfunc in senddata failed");
  302             free (xdata);
  303             return PTP_RC_GeneralError;
  304         }
  305         towrite2 = xtowrite;
  306         GP_LOG_DATA ((char*)xdata, towrite2, "ptpip/senddata data:");
  307         written = 0;
  308         while (written < towrite2) {
  309             ret = write (params->cmdfd, xdata+written, towrite2-written);
  310             if (ret == -1) {
  311                 perror ("write in senddata failed");
  312                 free (xdata);
  313                 return PTP_RC_GeneralError;
  314             }
  315             written += ret;
  316         }
  317         curwrite += towrite;
  318     }
  319     free (xdata);
  320     return PTP_RC_OK;
  321 }
  322 
  323 #define fujiptpip_getdata_payload       8
  324 
  325 static unsigned char hardcoded_deviceinfo[] = {
  326 100, 0,         /* standard version */
  327 PTP_VENDOR_FUJI, 0, /* vendor extension id */
  328 0, 0, 100, 0,       /* vendor ext version */
  329 
  330 0x16,
  331 0x66, 0x00,
  332 0x75, 0x00,
  333 0x6a, 0x00,
  334 0x69, 0x00,
  335 0x66, 0x00,
  336 0x69, 0x00,
  337 0x6c, 0x00,
  338 0x6d, 0x00,
  339 0x2e, 0x00,
  340 0x63, 0x00,
  341 0x6f, 0x00,
  342 0x2e, 0x00,
  343 0x6a, 0x00,
  344 0x70, 0x00,
  345 0x3a, 0x00,
  346 0x20, 0x00,
  347 0x31, 0x00,
  348 0x2e, 0x00,
  349 0x30, 0x00,
  350 0x3b, 0x00,
  351 0x20, 0x00,
  352 0x00, 0x00,
  353 
  354 0x00, 0x00, /* functional mode */
  355 
  356 0x22, 0x00, 0x00, 0x00, /* opcodes */
  357 0x01, 0x10,
  358 0x02, 0x10,
  359 0x03, 0x10,
  360 0x04, 0x10,
  361 0x05, 0x10,
  362 0x06, 0x10,
  363 0x07, 0x10,
  364 0x08, 0x10,
  365 0x09, 0x10,
  366 0x0a, 0x10,
  367 0x0b, 0x10,
  368 0x0e, 0x10,
  369 0x0f, 0x10,
  370 0x14, 0x10,
  371 0x15, 0x10,
  372 0x16, 0x10,
  373 0x17, 0x10,
  374 0x18, 0x10,
  375 0x1b, 0x10,
  376 0x1c, 0x10,
  377 0x0c, 0x90,
  378 0x0d, 0x90,
  379 0x1d, 0x90,
  380 0x01, 0x98,
  381 0x02, 0x98,
  382 0x03, 0x98,
  383 0x05, 0x98,
  384     /* manually added */
  385 0x22, 0x90,
  386 0x26, 0x90,
  387 0x27, 0x90,
  388 0x2b, 0x90,
  389 0x2c, 0x90,
  390 0x2d, 0x90,
  391 0x2e, 0x90,
  392 
  393 0x06, 0x00, 0x00, 0x00, /* events */
  394 0x02, 0x40,
  395 0x03, 0x40,
  396 0x04, 0x40,
  397 0x05, 0x40,
  398 0x0d, 0x40,
  399 0x06, 0xc0,
  400 
  401 0xa8, 0x00, 0x00, 0x00, /* device prop codes */
  402 0x01, 0x50, 0x03, 0x50, 0x05, 0x50, 0x0a, 0x50, 0x0b, 0x50, 0x0c, 0x50, 0x0e, 0x50, 0x0f,
  403 0x50, 0x11, 0x50, 0x12, 0x50, 0x15, 0x50, 0x18, 0x50, 0x19, 0x50, 0x1c, 0x50, 0x01, 0xd0, 0x02,
  404 0xd0, 0x03, 0xd0, 0x04, 0xd0, 0x05, 0xd0, 0x07, 0xd0, 0x08, 0xd0, 0x09, 0xd0, 0x0a, 0xd0, 0x0b,
  405 0xd0, 0x0c, 0xd0, 0x0d, 0xd0, 0x0e, 0xd0, 0x0f, 0xd0, 0x10, 0xd0, 0x11, 0xd0, 0x12, 0xd0, 0x13,
  406 0xd0, 0x14, 0xd0, 0x15, 0xd0, 0x16, 0xd0, 0x17, 0xd0, 0x18, 0xd0, 0x19, 0xd0, 0x1a, 0xd0, 0x1b,
  407 0xd0, 0x1c, 0xd0, 0x00, 0xd1, 0x01, 0xd1, 0x02, 0xd1, 0x03, 0xd1, 0x04, 0xd1, 0x05, 0xd1, 0x06,
  408 0xd1, 0x07, 0xd1, 0x08, 0xd1, 0x09, 0xd1, 0x0a, 0xd1, 0x0b, 0xd1, 0x0c, 0xd1, 0x0d, 0xd1, 0x0e,
  409 0xd1, 0x0f, 0xd1, 0x10, 0xd1, 0x11, 0xd1, 0x12, 0xd1, 0x13, 0xd1, 0x14, 0xd1, 0x15, 0xd1, 0x16,
  410 0xd1, 0x17, 0xd1, 0x18, 0xd1, 0x19, 0xd1, 0x1a, 0xd1, 0x1b, 0xd1, 0x1c, 0xd1, 0x1d, 0xd1, 0x1e,
  411 0xd1, 0x1f, 0xd1, 0x20, 0xd1, 0x21, 0xd1, 0x22, 0xd1, 0x23, 0xd1, 0x24, 0xd1, 0x25, 0xd1, 0x26,
  412 0xd1, 0x27, 0xd1, 0x28, 0xd1, 0x29, 0xd1, 0x2a, 0xd1, 0x2b, 0xd1, 0x2c, 0xd1, 0x2d, 0xd1, 0x2e,
  413 0xd1, 0x2f, 0xd1, 0x30, 0xd1, 0x31, 0xd1, 0x32, 0xd1, 0x33, 0xd1, 0x34, 0xd1, 0x35, 0xd1, 0x36,
  414 0xd1, 0x37, 0xd1, 0x38, 0xd1, 0x39, 0xd1, 0x3a, 0xd1, 0x3b, 0xd1, 0x3c, 0xd1, 0x3d, 0xd1, 0x3e,
  415 0xd1, 0x3f, 0xd1, 0x40, 0xd1, 0x41, 0xd1, 0x42, 0xd1, 0x43, 0xd1, 0x44, 0xd1, 0x45, 0xd1, 0x46,
  416 0xd1, 0x47, 0xd1, 0x48, 0xd1, 0x49, 0xd1, 0x4a, 0xd1, 0x4b, 0xd1, 0x4c, 0xd1, 0x4d, 0xd1, 0x4e,
  417 0xd1, 0x4f, 0xd1, 0x50, 0xd1, 0x51, 0xd1, 0x52, 0xd1, 0x53, 0xd1, 0x54, 0xd1, 0x55, 0xd1, 0x57,
  418 0xd1, 0x58, 0xd1, 0x59, 0xd1, 0x5a, 0xd1, 0x5b, 0xd1, 0x5c, 0xd1, 0x5d, 0xd1, 0x5e, 0xd1, 0x5f,
  419 0xd1, 0x60, 0xd1, 0x61, 0xd1, 0x00, 0xd2, 0x01, 0xd2, 0x02, 0xd2, 0x03, 0xd2, 0x04, 0xd2, 0x05,
  420 0xd2, 0x06, 0xd2, 0x07, 0xd2, 0x08, 0xd2, 0x09, 0xd2, 0x0a, 0xd2, 0x0b, 0xd2, 0x0c, 0xd2, 0x0d,
  421 0xd2, 0x0e, 0xd2, 0x0f, 0xd2, 0x10, 0xd2, 0x11, 0xd2, 0x12, 0xd2, 0x13, 0xd2, 0x14, 0xd2, 0x15,
  422 0xd2, 0x16, 0xd2, 0x17, 0xd2, 0x18, 0xd2, 0x19, 0xd2, 0x1a, 0xd2, 0x1b, 0xd2, 0x06, 0xd4, 0x07,
  423 0xd4,
  424 
  425 0x03, 0x00, 0x00, 0x00, /* capture formats */
  426 0x00, 0x38,
  427 0x01, 0x38,
  428 0x03, 0xb1,
  429 
  430 0x04, 0x00, 0x00, 0x00, /* image formats */
  431 0x00, 0x38,
  432 0x01, 0x38,
  433 0x03, 0xb1,
  434 0x0d, 0x38,
  435 
  436 0x09,       /* vendor "FUJIFILM" */
  437 0x46, 0x00,
  438 0x55, 0x00,
  439 0x4a, 0x00,
  440 0x49, 0x00,
  441 0x46, 0x00,
  442 0x49, 0x00,
  443 0x4c, 0x00,
  444 0x4d, 0x00,
  445 0x00, 0x00,
  446 
  447 0x06,       /* device "X-T42" */
  448 0x58, 0x00,
  449 0x2d, 0x00,
  450 0x54, 0x00,
  451 0x34, 0x00,
  452 0x32, 0x00,
  453 0x00, 0x00,
  454 
  455 0x05,       /* device version ... "1.01" */
  456 0x31, 0x00,
  457 0x2e, 0x00,
  458 0x30, 0x00,
  459 0x31, 0x00,
  460 0x00, 0x00,
  461 
  462 0x1f,       /* serial number */
  463 0x30, 0x00,
  464 0x30, 0x00,
  465 0x30, 0x00,
  466 0x30, 0x00,
  467 0x30, 0x00,
  468 0x30, 0x00,
  469 0x30, 0x00,
  470 0x30, 0x00,
  471 0x30, 0x00,
  472 0x30, 0x00,
  473 0x30, 0x00,
  474 0x30, 0x00,
  475 0x30, 0x00,
  476 0x30, 0x00,
  477 0x30, 0x00,
  478 0x30, 0x00,
  479 0x30, 0x00,
  480 0x30, 0x00,
  481 0x30, 0x00,
  482 0x30, 0x00,
  483 0x30, 0x00,
  484 0x30, 0x00,
  485 0x30, 0x00,
  486 0x30, 0x00,
  487 0x30, 0x00,
  488 0x30, 0x00,
  489 0x30, 0x00,
  490 0x30, 0x00,
  491 0x30, 0x00,
  492 0x30, 0x00,
  493 0x00, 0x00,
  494 };
  495 
  496 uint16_t
  497 ptp_fujiptpip_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) {
  498     PTPIPHeader     hdr;
  499     unsigned char       *xdata = NULL;
  500     uint16_t        ret;
  501     int         xret;
  502 
  503     GP_LOG_D ("Reading PTP_OC 0x%0x (%s) data...", ptp->Code, ptp_get_opcode_name(params, ptp->Code));
  504     ret = ptp_fujiptpip_cmd_read (params, &hdr, &xdata);
  505     if (ret != PTP_RC_OK)
  506         return ret;
  507 
  508     /* the Fuji X-T4 does only return an empty deviceinfo ... so we synthesize one */
  509     if ((ptp->Code == PTP_OC_GetDeviceInfo) && (dtoh32(hdr.length)-fujiptpip_getdata_payload-4 == 0)) {
  510         GP_LOG_D("synthesizing Fuji DeviceInfo");
  511         xret = handler->putfunc (params, handler->priv, sizeof(hardcoded_deviceinfo),hardcoded_deviceinfo);
  512     } else {
  513         GP_LOG_DATA ((char*)(xdata+fujiptpip_getdata_payload), dtoh32(hdr.length)-fujiptpip_getdata_payload-4, "fujiptpip/getdatda data:");
  514         xret = handler->putfunc (params, handler->priv,
  515             dtoh32(hdr.length)-fujiptpip_getdata_payload-4, xdata+fujiptpip_getdata_payload
  516         );
  517     }
  518     free (xdata);
  519     if (xret != PTP_RC_OK) {
  520         GP_LOG_E ("failed to putfunc of returned data");
  521         return GP_ERROR;
  522     }
  523     return PTP_RC_OK;
  524 }
  525 
  526 #define fujiptpip_dataphase 0
  527 #define fujiptpip_resp_code 2
  528 #define fujiptpip_resp_transid  4
  529 #define fujiptpip_resp_param1   8
  530 #define fujiptpip_resp_param2   12
  531 #define fujiptpip_resp_param3   16
  532 #define fujiptpip_resp_param4   20
  533 #define fujiptpip_resp_param5   24
  534 
  535 uint16_t
  536 ptp_fujiptpip_getresp (PTPParams* params, PTPContainer* resp)
  537 {
  538     PTPIPHeader hdr;
  539     unsigned char   *data = NULL;
  540     uint16_t    ret;
  541     int     n;
  542 
  543     GP_LOG_D ("Reading PTP_OC 0x%0x (%s) response...", resp->Code, ptp_get_opcode_name(params, resp->Code));
  544     ret = ptp_fujiptpip_cmd_read (params, &hdr, &data);
  545     if (ret != PTP_RC_OK)
  546         return GP_ERROR;
  547 
  548     switch (dtoh16a(data)) {
  549     case 3:
  550         GP_LOG_D("PTPIP_CMD_RESPONSE");
  551         resp->Code      = dtoh16a(&data[fujiptpip_resp_code]);
  552         resp->Transaction_ID    = dtoh32a(&data[fujiptpip_resp_transid]);
  553         n = (dtoh32(hdr.length) - sizeof(uint32_t) - fujiptpip_resp_param1)/sizeof(uint32_t);
  554         switch (n) {
  555         case 5: resp->Param5 = dtoh32a(&data[fujiptpip_resp_param5]);/* fallthrough */
  556         case 4: resp->Param4 = dtoh32a(&data[fujiptpip_resp_param4]);/* fallthrough */
  557         case 3: resp->Param3 = dtoh32a(&data[fujiptpip_resp_param3]);/* fallthrough */
  558         case 2: resp->Param2 = dtoh32a(&data[fujiptpip_resp_param2]);/* fallthrough */
  559         case 1: resp->Param1 = dtoh32a(&data[fujiptpip_resp_param1]);/* fallthrough */
  560         case 0: break;
  561         default:
  562             GP_LOG_E ("response got %d parameters?", n);
  563             break;
  564         }
  565         break;
  566     default:
  567         GP_LOG_E ("response type %d packet?", dtoh16a(data));
  568         break;
  569     }
  570     free (data);
  571     return PTP_RC_OK;
  572 }
  573 
  574 #define fujiptpip_initcmd_protocolversion   8
  575 #define fujiptpip_initcmd_guid          12
  576 #define fujiptpip_initcmd_name          28
  577 
  578 static uint16_t
  579 ptp_fujiptpip_init_command_request (PTPParams* params)
  580 {
  581     char        hostname[100];
  582     unsigned char*  cmdrequest;
  583     unsigned int    i;
  584     int         len, ret;
  585     unsigned char   guid[16];
  586 
  587     ptp_nikon_getptpipguid(guid);
  588 #if !defined (WIN32)
  589     if (gethostname (hostname, sizeof(hostname)))
  590         return PTP_RC_GeneralError;
  591 #else
  592     DWORD hostname_size = (DWORD)sizeof(hostname);
  593     if (!GetComputerNameA(hostname, &hostname_size))
  594         return PTP_RC_GeneralError;
  595 #endif
  596     len = fujiptpip_initcmd_name + (strlen(hostname)+1)*2;
  597 
  598     cmdrequest = malloc(len);
  599     htod32a(&cmdrequest[fujiptpip_type],PTPIP_INIT_COMMAND_REQUEST);
  600     htod32a(&cmdrequest[fujiptpip_len],len);
  601 
  602     htod32a(&cmdrequest[fujiptpip_initcmd_protocolversion], 0x8f53e4f2);    /* magic number */
  603 
  604     memcpy(&cmdrequest[fujiptpip_initcmd_guid], guid, 16);
  605     for (i=0;i<strlen(hostname)+1;i++) {
  606         /* -> ucs-2 in little endian */
  607         cmdrequest[fujiptpip_initcmd_name+i*2] = hostname[i];
  608         cmdrequest[fujiptpip_initcmd_name+i*2+1] = 0;
  609     }
  610 
  611     /*
  612     htod16a(&cmdrequest[fujiptpip_initcmd_name+(strlen(hostname)+1)*2],PTPIP_VERSION_MINOR);
  613     htod16a(&cmdrequest[fujiptpip_initcmd_name+(strlen(hostname)+1)*2+2],PTPIP_VERSION_MAJOR);
  614     */
  615 
  616 
  617     GP_LOG_DATA ((char*)cmdrequest, len, "ptpip/init_cmd data:");
  618     ret = PTPSOCK_WRITE (params->cmdfd, cmdrequest, len);
  619     free (cmdrequest);
  620     if (ret == PTPSOCK_ERR) {
  621         perror("write init cmd request");
  622         return PTP_RC_GeneralError;
  623     }
  624     GP_LOG_E ("return %d / len %d", ret, len);
  625     if (ret != len) {
  626         GP_LOG_E ("return %d vs len %d", ret, len);
  627         return PTP_RC_GeneralError;
  628     }
  629     return PTP_RC_OK;
  630 }
  631 
  632 #define ptpip_cmdack_idx    0
  633 #define ptpip_cmdack_guid   4
  634 #define ptpip_cmdack_name   20
  635 
  636 static uint16_t
  637 ptp_fujiptpip_init_command_ack (PTPParams* params)
  638 {
  639     PTPIPHeader hdr;
  640     unsigned char   *data = NULL;
  641     uint16_t    ret;
  642     int     i;
  643     unsigned short  *name;
  644 
  645     ret = ptp_fujiptpip_generic_read (params, params->cmdfd, &hdr, &data, 1);
  646     if (ret != PTP_RC_OK)
  647         return ret;
  648     if (hdr.type != dtoh32(PTPIP_INIT_COMMAND_ACK)) {
  649         GP_LOG_E ("bad type returned %d", htod32(hdr.type));
  650         free (data);
  651         if (hdr.type == PTPIP_INIT_FAIL) /* likely reason is permission denied */
  652             return PTP_RC_AccessDenied;
  653         return PTP_RC_GeneralError;
  654     }
  655     params->eventpipeid = dtoh32a(&data[ptpip_cmdack_idx]);
  656     memcpy (params->cameraguid, &data[ptpip_cmdack_guid], 16);
  657     name = (unsigned short*)&data[ptpip_cmdack_name];
  658     for (i=0;name[i];i++) /* EMPTY */;
  659     params->cameraname = calloc((i+1),sizeof(uint16_t));
  660     for (i=0;name[i];i++)
  661         params->cameraname[i] = name[i];
  662     free (data);
  663     return PTP_RC_OK;
  664 }
  665 
  666 #define fujiptpip_eventinit_idx 8
  667 #define fujiptpip_eventinit_size    12
  668 
  669 int
  670 ptp_fujiptpip_init_event (PTPParams* params, const char *address)
  671 {
  672     char        *addr, *s, *p;
  673     int     port, eventport, tries;
  674     struct sockaddr_in  saddr;
  675 
  676     memset(&saddr,0,sizeof(saddr));
  677 
  678     GP_LOG_D ("connecting to %s.", address);
  679     if (NULL == strchr (address,':'))
  680         return GP_ERROR_BAD_PARAMETERS;
  681 
  682     addr = strdup (address);
  683     if (!addr)
  684         return GP_ERROR_NO_MEMORY;
  685     s = strchr (addr,':');
  686     if (!s) {
  687         GP_LOG_E ("addr %s should contain a :", address);
  688         free (addr);
  689         return GP_ERROR_BAD_PARAMETERS;
  690     }
  691     *s = '\0';
  692     p = strchr (s+1,':');
  693     port = 55740;
  694     eventport = port+1;
  695     if (p) {
  696         *p = '\0';
  697         if (!sscanf (p+1,"%d",&port)) {
  698             fprintf(stderr,"failed to scan for port in %s\n", p+1);
  699             free (addr);
  700             return GP_ERROR_BAD_PARAMETERS;
  701         }
  702         /* different event port ? */
  703         p = strchr (p+1,':');
  704         if (p) {
  705             if (!sscanf (p+1,"%d",&eventport)) {
  706                 fprintf(stderr,"failed to scan for eventport in %s\n", p+1);
  707                 free (addr);
  708                 return GP_ERROR_BAD_PARAMETERS;
  709             }
  710         }
  711     }
  712 #ifdef HAVE_INET_ATON
  713     if (!inet_aton (s+1,  &saddr.sin_addr)) {
  714 #else
  715     if (inet_pton(AF_INET, s+1, &saddr.sin_addr) != 1) {
  716 #endif
  717         fprintf(stderr,"failed to scan for addr in %s\n", s+1);
  718         free (addr);
  719         return GP_ERROR_BAD_PARAMETERS;
  720     }
  721     free (addr);
  722 
  723     tries = 2;
  724     saddr.sin_family    = AF_INET;
  725     saddr.sin_port      = htons(eventport);
  726     do {
  727         if (PTPSOCK_ERR != connect (params->evtfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)))
  728             break;
  729         if ((errno == ECONNREFUSED) && (tries--)) {
  730             GP_LOG_D ("event connect failed, retrying after short wait");
  731             int sleep_ms = 100;
  732 #ifdef WIN32
  733             Sleep(sleep_ms);
  734 #else
  735             usleep(sleep_ms*1000);
  736 #endif
  737             continue;
  738         }
  739         GP_LOG_E ("could not connect event");
  740         PTPSOCK_CLOSE (params->evtfd);
  741         return GP_ERROR_IO;
  742     } while (1);
  743     GP_LOG_D ("fujiptpip event connected!");
  744     tries = 2;
  745     saddr.sin_family    = AF_INET;
  746     saddr.sin_port      = htons(eventport+1);
  747     do {
  748         if (PTPSOCK_ERR != connect (params->jpgfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)))
  749             break;
  750         if ((errno == ECONNREFUSED) && (tries--)) {
  751             GP_LOG_D ("jpeg connect failed, retrying after short wait");
  752             int sleep_ms = 100;
  753 #ifdef WIN32
  754             Sleep(sleep_ms);
  755 #else
  756             usleep(sleep_ms*1000);
  757 #endif
  758             continue;
  759         }
  760         GP_LOG_E ("could not connect event");
  761         PTPSOCK_CLOSE (params->jpgfd);
  762         return GP_ERROR_IO;
  763     } while (1);
  764     return GP_OK;
  765 }
  766 
  767 
  768 /* Event handling functions */
  769 
  770 /* PTP Events wait for or check mode */
  771 
  772 #define ptpip_event_type        0
  773 #define ptpip_event_code        2
  774 #define ptpip_event_transid 4
  775 #define ptpip_event_param1  8
  776 #define ptpip_event_param2  12
  777 #define ptpip_event_param3  16
  778 #define ptpip_event_param4  20
  779 
  780 static uint16_t
  781 ptp_fujiptpip_event (PTPParams* params, PTPContainer* event, int wait)
  782 {
  783     fd_set      infds;
  784     struct timeval  timeout;
  785     int ret;
  786     unsigned char*  data = NULL;
  787     PTPIPHeader hdr;
  788     int n;
  789 
  790     while (1) {
  791         FD_ZERO(&infds);
  792         FD_SET(params->evtfd, &infds);
  793         timeout.tv_sec = 0;
  794         if (wait == PTP_EVENT_CHECK_FAST)
  795             timeout.tv_usec = 1;
  796         else
  797             timeout.tv_usec = 1000; /* 1/1000 second  .. perhaps wait longer? */
  798 
  799         ret = select (params->evtfd+1, &infds, NULL, NULL, &timeout);
  800         if (1 != ret) {
  801             if (-1 == ret) {
  802                 GP_LOG_D ("select returned error, errno is %d", errno);
  803                 return PTP_ERROR_IO;
  804             }
  805             return PTP_ERROR_TIMEOUT;
  806         }
  807 
  808         ret = ptp_fujiptpip_evt_read (params, &hdr, &data);
  809         if (ret != PTP_RC_OK)
  810             return ret;
  811         GP_LOG_D ("length %d", hdr.length);
  812         break;
  813     }
  814 
  815     event->Code     = dtoh16a(&data[ptpip_event_code]);
  816     event->Transaction_ID   = dtoh32a(&data[ptpip_event_transid]);
  817     n = (dtoh32(hdr.length) - sizeof(uint32_t) - ptpip_event_param1)/sizeof(uint32_t);
  818     switch (n) {
  819     case 4: event->Param4 = dtoh32a(&data[ptpip_event_param4]);/* fallthrough */
  820     case 3: event->Param3 = dtoh32a(&data[ptpip_event_param3]);/* fallthrough */
  821     case 2: event->Param2 = dtoh32a(&data[ptpip_event_param2]);/* fallthrough */
  822     case 1: event->Param1 = dtoh32a(&data[ptpip_event_param1]);/* fallthrough */
  823     case 0: break;
  824     default:
  825         GP_LOG_E ("response got %d parameters?", n);
  826         break;
  827     }
  828     free (data);
  829     return PTP_RC_OK;
  830 }
  831 
  832 uint16_t
  833 ptp_fujiptpip_event_check_queue (PTPParams* params, PTPContainer* event) {
  834     /* the fast check just takes 1ms, so lets keep it */
  835     return ptp_fujiptpip_event (params, event, PTP_EVENT_CHECK_FAST);
  836 }
  837 
  838 uint16_t
  839 ptp_fujiptpip_event_check (PTPParams* params, PTPContainer* event) {
  840     return ptp_fujiptpip_event (params, event, PTP_EVENT_CHECK_FAST);
  841 }
  842 
  843 uint16_t
  844 ptp_fujiptpip_event_wait (PTPParams* params, PTPContainer* event) {
  845     return ptp_fujiptpip_event (params, event, PTP_EVENT_CHECK);
  846 }
  847 
  848 uint16_t
  849 ptp_fujiptpip_jpeg (PTPParams* params, unsigned char** xdata, unsigned int *xsize)
  850 {
  851     fd_set      infds;
  852     struct timeval  timeout;
  853     int ret;
  854     unsigned char*  data = NULL;
  855     PTPIPHeader hdr;
  856 
  857     while (1) {
  858         FD_ZERO(&infds);
  859         FD_SET(params->jpgfd, &infds);
  860         timeout.tv_sec = 1;
  861         timeout.tv_usec = 0;
  862 
  863         ret = select (params->jpgfd+1, &infds, NULL, NULL, &timeout);
  864         if (1 != ret) {
  865             if (-1 == ret) {
  866                 GP_LOG_D ("select returned error, errno is %d", errno);
  867                 return PTP_ERROR_IO;
  868             }
  869             return PTP_ERROR_TIMEOUT;
  870         }
  871 
  872         ret = ptp_fujiptpip_jpg_read (params, &hdr, &data);
  873         if (ret != PTP_RC_OK)
  874             return ret;
  875 
  876         *xdata = data;
  877         *xsize = hdr.length - sizeof(uint32_t);
  878         break;
  879     }
  880     return PTP_RC_OK;
  881 }
  882 
  883 
  884 int
  885 ptp_fujiptpip_connect (PTPParams* params, const char *address) {
  886     char        *addr, *s, *p;
  887     int     port, eventport;
  888     struct sockaddr_in  saddr;
  889     uint16_t    ret;
  890 
  891     memset(&saddr,0,sizeof(saddr));
  892 
  893     GP_LOG_D ("connecting to %s.", address);
  894     if (NULL == strchr (address,':'))
  895         return GP_ERROR_BAD_PARAMETERS;
  896 
  897     addr = strdup (address);
  898     if (!addr)
  899         return GP_ERROR_NO_MEMORY;
  900     s = strchr (addr,':');
  901     if (!s) {
  902         GP_LOG_E ("addr %s should contain a :", address);
  903         free (addr);
  904         return GP_ERROR_BAD_PARAMETERS;
  905     }
  906     *s = '\0';
  907     p = strchr (s+1,':');
  908     port = 55740;
  909     eventport = port+1;
  910     if (p) {
  911         *p = '\0';
  912         if (!sscanf (p+1,"%d",&port)) {
  913             fprintf(stderr,"failed to scan for port in %s\n", p+1);
  914             free (addr);
  915             return GP_ERROR_BAD_PARAMETERS;
  916         }
  917         /* different event port ? */
  918         p = strchr (p+1,':');
  919         if (p) {
  920             if (!sscanf (p+1,"%d",&eventport)) {
  921                 fprintf(stderr,"failed to scan for eventport in %s\n", p+1);
  922                 free (addr);
  923                 return GP_ERROR_BAD_PARAMETERS;
  924             }
  925         }
  926     }
  927 #ifdef HAVE_INET_ATON
  928     if (!inet_aton (s+1,  &saddr.sin_addr)) {
  929 #else
  930     if (inet_pton(AF_INET, s+1, &saddr.sin_addr) != 1) {
  931 #endif
  932         fprintf(stderr,"failed to scan for addr in %s\n", s+1);
  933         free (addr);
  934         return GP_ERROR_BAD_PARAMETERS;
  935     }
  936     saddr.sin_port      = htons(port);
  937     saddr.sin_family    = AF_INET;
  938     free (addr);
  939     PTPSOCK_SOCKTYPE cmdfd = params->cmdfd = socket (PF_INET, SOCK_STREAM, PTPSOCK_PROTO);
  940     if (cmdfd == PTPSOCK_INVALID) {
  941         perror ("socket cmd");
  942         return GP_ERROR_BAD_PARAMETERS;
  943     }
  944     PTPSOCK_SOCKTYPE evtfd = params->evtfd = socket (PF_INET, SOCK_STREAM, PTPSOCK_PROTO);
  945     if (evtfd == PTPSOCK_INVALID) {
  946         perror ("socket evt");
  947         PTPSOCK_CLOSE (params->cmdfd);
  948         return GP_ERROR_BAD_PARAMETERS;
  949     }
  950     PTPSOCK_SOCKTYPE jpgfd = params->jpgfd = socket (PF_INET, SOCK_STREAM, 0);
  951     if (jpgfd == PTPSOCK_INVALID) {
  952         perror ("socket jpg");
  953         PTPSOCK_CLOSE (params->evtfd);
  954         PTPSOCK_CLOSE (params->cmdfd);
  955         return GP_ERROR_BAD_PARAMETERS;
  956     }
  957     if (PTPSOCK_ERR == connect (params->cmdfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in))) {
  958         perror ("connect cmd");
  959         PTPSOCK_CLOSE (params->cmdfd);
  960         PTPSOCK_CLOSE (params->evtfd);
  961         return GP_ERROR_IO;
  962     }
  963     ret = ptp_fujiptpip_init_command_request (params);
  964     if (ret != PTP_RC_OK) {
  965         PTPSOCK_CLOSE (params->cmdfd);
  966         PTPSOCK_CLOSE (params->evtfd);
  967         return translate_ptp_result (ret);
  968     }
  969     ret = ptp_fujiptpip_init_command_ack (params);
  970     if (ret != PTP_RC_OK) {
  971         PTPSOCK_CLOSE (params->cmdfd);
  972         PTPSOCK_CLOSE (params->evtfd);
  973         return translate_ptp_result (ret);
  974     }
  975     GP_LOG_D ("fujiptpip connected!");
  976     return GP_OK;
  977 }