"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/camlibs/ptp2/ptpip.c" (14 Feb 2021, 23421 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 "ptpip.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 /* ptpip.c
    2  *
    3  * Copyright (C) 2006 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 working, but unfinished!
   22  * - Event handling not finished.
   23  * - Some configure checking magic missing for the special header files
   24  *   and functions.
   25  * - Not everything implementation correctly cross checked.
   26  * - Coolpix P3 does not give transfer status (image 000x/000y), and reports an
   27  *   error when transfers finish correctly.
   28  *
   29  * Nikon WU-1* adapters might use 0011223344556677 as GUID always...
   30  */
   31 #define _DEFAULT_SOURCE
   32 #define _DARWIN_C_SOURCE
   33 #include "config.h"
   34 
   35 #include <stdlib.h>
   36 #include <string.h>
   37 #include <stdio.h>
   38 #include <time.h>
   39 #include <errno.h>
   40 #include <sys/types.h>
   41 #ifdef HAVE_SYS_SELECT_H
   42 #include <sys/select.h>
   43 #endif
   44 
   45 #include "ptpip-private.h"
   46 
   47 #ifdef WIN32
   48 # include <winsock2.h>
   49 # include <ws2tcpip.h>
   50 #else
   51 # include <sys/socket.h>
   52 # include <netinet/in.h>
   53 #endif
   54 
   55 #include <gphoto2/gphoto2-library.h>
   56 #include <gphoto2/gphoto2-port-log.h>
   57 #include <gphoto2/gphoto2-setting.h>
   58 
   59 #include "ptp.h"
   60 #include "ptp-private.h"
   61 
   62 #define PTPIP_VERSION_MAJOR 0x0001
   63 #define PTPIP_VERSION_MINOR 0x0000
   64 
   65 #ifdef ENABLE_NLS
   66 #  include <libintl.h>
   67 #  undef _
   68 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
   69 #  ifdef gettext_noop
   70 #    define N_(String) gettext_noop (String)
   71 #  else
   72 #    define N_(String) (String)
   73 #  endif
   74 #else
   75 #  define textdomain(String) (String)
   76 #  define gettext(String) (String)
   77 #  define dgettext(Domain,Message) (Message)
   78 #  define dcgettext(Domain,Message,Type) (Message)
   79 #  define bindtextdomain(Domain,Directory) (Domain)
   80 #  define _(String) (String)
   81 #  define N_(String) (String)
   82 #endif
   83 
   84 #include "ptp.h"
   85 #include "ptp-bugs.h"
   86 
   87 #include "ptp-pack.c"
   88 
   89 #define ptpip_len       0
   90 #define ptpip_type      4
   91 
   92 #define ptpip_cmd_dataphase 8
   93 #define ptpip_cmd_code      12
   94 #define ptpip_cmd_transid   14
   95 #define ptpip_cmd_param1    18
   96 #define ptpip_cmd_param2    22
   97 #define ptpip_cmd_param3    26
   98 #define ptpip_cmd_param4    30
   99 #define ptpip_cmd_param5    34
  100 
  101 #define PTP_EVENT_CHECK         0x0000  /* waits for */
  102 #define PTP_EVENT_CHECK_FAST        0x0001  /* checks */
  103 static uint16_t ptp_ptpip_check_event (PTPParams* params);
  104 static uint16_t ptp_ptpip_event (PTPParams* params, PTPContainer* event, int wait);
  105 
  106 /* send / receive functions */
  107 uint16_t
  108 ptp_ptpip_sendreq (PTPParams* params, PTPContainer* req, int dataphase)
  109 {
  110     int     ret;
  111     int     len = 18+req->Nparam*4;
  112     unsigned char   *request = malloc(len);
  113 
  114     switch (req->Nparam) {
  115     default:
  116     case 0: GP_LOG_D ("Sending PTP_OC 0x%0x (%s) request...", req->Code, ptp_get_opcode_name(params, req->Code));
  117         break;
  118     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);
  119         break;
  120     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);
  121         break;
  122     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);
  123         break;
  124     }
  125 
  126     ptp_ptpip_check_event (params);
  127 
  128     htod32a(&request[ptpip_type],PTPIP_CMD_REQUEST);
  129     htod32a(&request[ptpip_len],len);
  130     /* sending data = 2, receiving data or no data = 1 */
  131     if ((dataphase&PTP_DP_DATA_MASK) == PTP_DP_SENDDATA)
  132         htod32a(&request[ptpip_cmd_dataphase],2);
  133     else
  134         htod32a(&request[ptpip_cmd_dataphase],1);
  135     htod16a(&request[ptpip_cmd_code],req->Code);
  136     htod32a(&request[ptpip_cmd_transid],req->Transaction_ID);
  137 
  138     switch (req->Nparam) {
  139     case 5: htod32a(&request[ptpip_cmd_param5],req->Param5);/* fallthrough */
  140     case 4: htod32a(&request[ptpip_cmd_param4],req->Param4);/* fallthrough */
  141     case 3: htod32a(&request[ptpip_cmd_param3],req->Param3);/* fallthrough */
  142     case 2: htod32a(&request[ptpip_cmd_param2],req->Param2);/* fallthrough */
  143     case 1: htod32a(&request[ptpip_cmd_param1],req->Param1);/* fallthrough */
  144     case 0:
  145     default:
  146         break;
  147     }
  148     GP_LOG_DATA ( (char*)request, len, "ptpip/oprequest data:");
  149     ret = PTPSOCK_WRITE(params->cmdfd, request, len);
  150     free (request);
  151     if (ret == PTPSOCK_ERR) {
  152         perror ("sendreq/write to cmdfd");
  153         return GP_ERROR_IO;
  154     }
  155     if (ret != len) {
  156         GP_LOG_E ("ptp_ptpip_sendreq() len =%d but ret=%d", len, ret);
  157         return PTP_RC_OK;
  158     }
  159     return PTP_RC_OK;
  160 }
  161 
  162 static uint16_t
  163 ptp_ptpip_generic_read (PTPParams *params, int fd, PTPIPHeader *hdr, unsigned char**data) {
  164     int ret, len, curread;
  165     unsigned char *xhdr;
  166 
  167     xhdr = (unsigned char*)hdr; curread = 0; len = sizeof (PTPIPHeader);
  168     while (curread < len) {
  169         ret = PTPSOCK_READ (fd, xhdr + curread, len - curread);
  170         if (ret == PTPSOCK_ERR) {
  171             perror ("read PTPIPHeader");
  172             return PTP_RC_GeneralError;
  173         }
  174         GP_LOG_DATA ((char*)xhdr+curread, ret, "ptpip/generic_read header:");
  175         curread += ret;
  176         if (ret == 0) {
  177             GP_LOG_E ("End of stream after reading %d bytes of ptpipheader", ret);
  178             return PTP_RC_GeneralError;
  179         }
  180     }
  181     len = dtoh32 (hdr->length) - sizeof (PTPIPHeader);
  182     if (len < 0) {
  183         GP_LOG_E ("len < 0, %d?", len);
  184         return PTP_RC_GeneralError;
  185     }
  186     *data = malloc (len);
  187     if (!*data) {
  188         GP_LOG_E ("malloc failed.");
  189         return PTP_RC_GeneralError;
  190     }
  191     curread = 0;
  192     while (curread < len) {
  193         ret = PTPSOCK_READ (fd, (*data)+curread, len-curread);
  194         if (ret == PTPSOCK_ERR) {
  195             GP_LOG_E ("error %d in reading PTPIP data", errno);
  196             free (*data);*data = NULL;
  197             return PTP_RC_GeneralError;
  198         } else {
  199             GP_LOG_DATA ((char*)((*data)+curread), ret, "ptpip/generic_read data:");
  200         }
  201         if (ret == 0)
  202             break;
  203         curread += ret;
  204     }
  205     if (curread != len) {
  206         GP_LOG_E ("read PTPIP data, ret %d vs len %d", ret, len);
  207         free (*data);*data = NULL;
  208         return PTP_RC_GeneralError;
  209     }
  210     return PTP_RC_OK;
  211 }
  212 
  213 static uint16_t
  214 ptp_ptpip_cmd_read (PTPParams* params, PTPIPHeader *hdr, unsigned char** data) {
  215     ptp_ptpip_check_event (params);
  216     return ptp_ptpip_generic_read (params, params->cmdfd, hdr, data);
  217 }
  218 
  219 static uint16_t
  220 ptp_ptpip_evt_read (PTPParams* params, PTPIPHeader *hdr, unsigned char** data) {
  221     return ptp_ptpip_generic_read (params, params->evtfd, hdr, data);
  222 }
  223 
  224 static uint16_t
  225 ptp_ptpip_check_event (PTPParams* params) {
  226     PTPContainer    event;
  227     uint16_t    ret;
  228 
  229     event.Code = 0;
  230     ret = ptp_ptpip_event (params, &event, PTP_EVENT_CHECK_FAST);
  231     if (ret != PTP_RC_OK)
  232         return ret;
  233     if (event.Code == 0)
  234         return ret;
  235     return ptp_add_event (params, &event);
  236 }
  237 
  238 #define ptpip_startdata_transid     0
  239 #define ptpip_startdata_totallen    4
  240 #define ptpip_startdata_unknown     8
  241 #define ptpip_data_transid      0
  242 #define ptpip_data_payload      4
  243 
  244 #define WRITE_BLOCKSIZE 65536
  245 uint16_t
  246 ptp_ptpip_senddata (PTPParams* params, PTPContainer* ptp,
  247         uint64_t size, PTPDataHandler *handler
  248 ) {
  249     unsigned char   request[0x14];
  250     unsigned int    curwrite, towrite;
  251     int     ret;
  252     unsigned char*  xdata;
  253 
  254     GP_LOG_D ("Sending PTP_OC 0x%0x (%s) data...", ptp->Code, ptp_get_opcode_name(params, ptp->Code));
  255     htod32a(&request[ptpip_type],PTPIP_START_DATA_PACKET);
  256     htod32a(&request[ptpip_len],sizeof(request));
  257     htod32a(&request[ptpip_startdata_transid  + 8],ptp->Transaction_ID);
  258     htod32a(&request[ptpip_startdata_totallen + 8],size);
  259     htod32a(&request[ptpip_startdata_unknown  + 8],0);
  260     GP_LOG_DATA ((char*)request, sizeof(request), "ptpip/senddata header:");
  261     ret = PTPSOCK_WRITE (params->cmdfd, request, sizeof(request));
  262     if (ret == PTPSOCK_ERR) {
  263         perror ("sendreq/write to cmdfd");
  264         return GP_ERROR_IO;
  265     }
  266     if (ret != sizeof(request)) {
  267         GP_LOG_E ("ptp_ptpip_senddata() len=%d but ret=%d", (int)sizeof(request), ret);
  268         return PTP_RC_GeneralError;
  269     }
  270     xdata = malloc(WRITE_BLOCKSIZE+8+4);
  271     if (!xdata) return PTP_RC_GeneralError;
  272     curwrite = 0;
  273     while (curwrite < size) {
  274         unsigned long type, written, towrite2, xtowrite;
  275 
  276         ptp_ptpip_check_event (params);
  277 
  278         towrite = size - curwrite;
  279         if (towrite > WRITE_BLOCKSIZE) {
  280             towrite = WRITE_BLOCKSIZE;
  281             type    = PTPIP_DATA_PACKET;
  282         } else {
  283             type    = PTPIP_END_DATA_PACKET;
  284         }
  285         ret = handler->getfunc (params, handler->priv, towrite, &xdata[ptpip_data_payload+8], &xtowrite);
  286         if (ret == -1) {
  287             perror ("getfunc in senddata failed");
  288             free (xdata);
  289             return PTP_RC_GeneralError;
  290         }
  291         towrite2 = xtowrite + 12;
  292         htod32a(&xdata[ptpip_type], type);
  293         htod32a(&xdata[ptpip_len], towrite2);
  294         htod32a(&xdata[ptpip_data_transid+8], ptp->Transaction_ID);
  295         GP_LOG_DATA ((char*)xdata, towrite2, "ptpip/senddata data:");
  296         written = 0;
  297         while (written < towrite2) {
  298             ret = PTPSOCK_WRITE (params->cmdfd, xdata+written, towrite2-written);
  299             if (ret == PTPSOCK_ERR) {
  300                 perror ("write in senddata failed");
  301                 free (xdata);
  302                 return PTP_RC_GeneralError;
  303             }
  304             written += ret;
  305         }
  306         curwrite += towrite;
  307     }
  308     free (xdata);
  309     return PTP_RC_OK;
  310 }
  311 
  312 uint16_t
  313 ptp_ptpip_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) {
  314     PTPIPHeader     hdr;
  315     unsigned char       *xdata = NULL;
  316     uint16_t        ret;
  317     unsigned long       toread, curread;
  318     int         xret;
  319 
  320     GP_LOG_D ("Reading PTP_OC 0x%0x (%s) data...", ptp->Code, ptp_get_opcode_name(params, ptp->Code));
  321     ret = ptp_ptpip_cmd_read (params, &hdr, &xdata);
  322     if (ret != PTP_RC_OK)
  323         return ret;
  324 
  325     if (dtoh32(hdr.type) == PTPIP_CMD_RESPONSE) { /* might happen if we have no data transfer due to error? */
  326         GP_LOG_E ("Unexpected ptp response, ptp code %x", dtoh16a(&xdata[0]));
  327         return dtoh16a(&xdata[0]);
  328     }
  329     if (dtoh32(hdr.type) != PTPIP_START_DATA_PACKET) {
  330         GP_LOG_E ("got reply type %d\n", dtoh32(hdr.type));
  331         return PTP_RC_GeneralError;
  332     }
  333     toread = dtoh32a(&xdata[ptpip_data_payload]);
  334     free (xdata); xdata = NULL;
  335     curread = 0;
  336     while (curread < toread) {
  337         ret = ptp_ptpip_cmd_read (params, &hdr, &xdata);
  338         if (ret != PTP_RC_OK)
  339             return ret;
  340         if (dtoh32(hdr.type) == PTPIP_END_DATA_PACKET) {
  341             unsigned long datalen = dtoh32(hdr.length)-8-ptpip_data_payload;
  342             if (datalen > (toread-curread)) {
  343                 GP_LOG_E ("returned data is too much, expected %ld, got %ld",
  344                       (toread-curread), datalen
  345                 );
  346                 break;
  347             }
  348             xret = handler->putfunc (params, handler->priv,
  349                 datalen, xdata+ptpip_data_payload
  350             );
  351             if (xret != PTP_RC_OK) {
  352                 GP_LOG_E ("failed to putfunc of returned data");
  353                 break;
  354             }
  355             curread += datalen;
  356             free (xdata); xdata = NULL;
  357             continue;
  358         }
  359         if (dtoh32(hdr.type) == PTPIP_DATA_PACKET) {
  360             unsigned long datalen = dtoh32(hdr.length)-8-ptpip_data_payload;
  361             if (datalen > (toread-curread)) {
  362                 GP_LOG_E ("returned data is too much, expected %ld, got %ld",
  363                       (toread-curread), datalen
  364                 );
  365                 break;
  366             }
  367             xret = handler->putfunc (params, handler->priv,
  368                 datalen, xdata+ptpip_data_payload
  369             );
  370             if (xret != PTP_RC_OK) {
  371                 GP_LOG_E ("failed to putfunc of returned data");
  372                 break;
  373             }
  374             curread += datalen;
  375             free (xdata); xdata = NULL;
  376             continue;
  377         }
  378         GP_LOG_E ("ret type %d", hdr.type);
  379     }
  380     if (curread < toread)
  381         return PTP_RC_GeneralError;
  382     return PTP_RC_OK;
  383 }
  384 
  385 #define ptpip_resp_code     0
  386 #define ptpip_resp_transid  2
  387 #define ptpip_resp_param1   6
  388 #define ptpip_resp_param2   10
  389 #define ptpip_resp_param3   14
  390 #define ptpip_resp_param4   18
  391 #define ptpip_resp_param5   22
  392 
  393 uint16_t
  394 ptp_ptpip_getresp (PTPParams* params, PTPContainer* resp)
  395 {
  396     PTPIPHeader hdr;
  397     unsigned char   *data = NULL;
  398     uint16_t    ret;
  399     int     n;
  400 
  401     GP_LOG_D ("Reading PTP_OC 0x%0x (%s) response...", resp->Code, ptp_get_opcode_name(params, resp->Code));
  402 retry:
  403     ret = ptp_ptpip_cmd_read (params, &hdr, &data);
  404     if (ret != PTP_RC_OK)
  405         return ret;
  406 
  407     switch (dtoh32(hdr.type)) {
  408     case PTPIP_END_DATA_PACKET:
  409         resp->Transaction_ID    = dtoh32a(&data[0]);
  410         GP_LOG_D("PTPIP_END_DATA_PACKET (tid = 0x%08x)", resp->Transaction_ID);
  411         free (data);
  412         data = NULL;
  413         goto retry;
  414     case PTPIP_CMD_RESPONSE:
  415         resp->Code      = dtoh16a(&data[ptpip_resp_code]);
  416         resp->Transaction_ID    = dtoh32a(&data[ptpip_resp_transid]);
  417         GP_LOG_D("PTPIP_CMD_RESPONSE (result=0x%04x, tid=0x%08x)", resp->Code, resp->Transaction_ID);
  418         n = (dtoh32(hdr.length) - sizeof(hdr) - ptpip_resp_param1)/sizeof(uint32_t);
  419         switch (n) {
  420         case 5: resp->Param5 = dtoh32a(&data[ptpip_resp_param5]);/* fallthrough */
  421         case 4: resp->Param4 = dtoh32a(&data[ptpip_resp_param4]);/* fallthrough */
  422         case 3: resp->Param3 = dtoh32a(&data[ptpip_resp_param3]);/* fallthrough */
  423         case 2: resp->Param2 = dtoh32a(&data[ptpip_resp_param2]);/* fallthrough */
  424         case 1: resp->Param1 = dtoh32a(&data[ptpip_resp_param1]);/* fallthrough */
  425         case 0: break;
  426         default:
  427             GP_LOG_E ("response got %d parameters?", n);
  428             break;
  429         }
  430         break;
  431     default:
  432         GP_LOG_E ("response type %d packet?", dtoh32(hdr.type));
  433         break;
  434     }
  435     free (data);
  436     return PTP_RC_OK;
  437 }
  438 
  439 #define ptpip_initcmd_guid  8
  440 #define ptpip_initcmd_name  24
  441 
  442 static uint16_t
  443 ptp_ptpip_init_command_request (PTPParams* params)
  444 {
  445     char        hostname[100];
  446     unsigned char*  cmdrequest;
  447     unsigned int    i;
  448     int         len, ret;
  449     unsigned char   guid[16];
  450 
  451     ptp_nikon_getptpipguid(guid);
  452 #if !defined (WIN32)
  453     if (gethostname (hostname, sizeof(hostname)))
  454         return PTP_RC_GeneralError;
  455 #else
  456     DWORD hostname_size = (DWORD)sizeof(hostname);
  457     if (!GetComputerNameA(hostname, &hostname_size))
  458         return PTP_RC_GeneralError;
  459 #endif
  460     len = ptpip_initcmd_name + (strlen(hostname)+1)*2 + 4;
  461 
  462     cmdrequest = malloc(len);
  463     htod32a(&cmdrequest[ptpip_type],PTPIP_INIT_COMMAND_REQUEST);
  464     htod32a(&cmdrequest[ptpip_len],len);
  465 
  466     memcpy(&cmdrequest[ptpip_initcmd_guid], guid, 16);
  467     for (i=0;i<strlen(hostname)+1;i++) {
  468         /* -> ucs-2 in little endian */
  469         cmdrequest[ptpip_initcmd_name+i*2] = hostname[i];
  470         cmdrequest[ptpip_initcmd_name+i*2+1] = 0;
  471     }
  472     htod16a(&cmdrequest[ptpip_initcmd_name+(strlen(hostname)+1)*2],PTPIP_VERSION_MINOR);
  473     htod16a(&cmdrequest[ptpip_initcmd_name+(strlen(hostname)+1)*2+2],PTPIP_VERSION_MAJOR);
  474 
  475     GP_LOG_DATA ((char*)cmdrequest, len, "ptpip/init_cmd data:");
  476     ret = PTPSOCK_WRITE (params->cmdfd, cmdrequest, len);
  477     free (cmdrequest);
  478     if (ret == PTPSOCK_ERR) {
  479         perror("write init cmd request");
  480         return PTP_RC_GeneralError;
  481     }
  482     GP_LOG_E ("return %d / len %d", ret, len);
  483     if (ret != len) {
  484         GP_LOG_E ("return %d vs len %d", ret, len);
  485         return PTP_RC_GeneralError;
  486     }
  487     return PTP_RC_OK;
  488 }
  489 
  490 #define ptpip_cmdack_idx    0
  491 #define ptpip_cmdack_guid   4
  492 #define ptpip_cmdack_name   20
  493 
  494 static uint16_t
  495 ptp_ptpip_init_command_ack (PTPParams* params)
  496 {
  497     PTPIPHeader hdr;
  498     unsigned char   *data = NULL;
  499     uint16_t    ret;
  500     int     i;
  501     unsigned short  *name;
  502 
  503     ret = ptp_ptpip_generic_read (params, params->cmdfd, &hdr, &data);
  504     if (ret != PTP_RC_OK)
  505         return ret;
  506     if (hdr.type != dtoh32(PTPIP_INIT_COMMAND_ACK)) {
  507         GP_LOG_E ("bad type returned %d", htod32(hdr.type));
  508         free (data);
  509         if (hdr.type == PTPIP_INIT_FAIL) /* likely reason is permission denied */
  510             return PTP_RC_AccessDenied;
  511         return PTP_RC_GeneralError;
  512     }
  513     params->eventpipeid = dtoh32a(&data[ptpip_cmdack_idx]);
  514     memcpy (params->cameraguid, &data[ptpip_cmdack_guid], 16);
  515     name = (unsigned short*)&data[ptpip_cmdack_name];
  516     for (i=0;name[i];i++) /* EMPTY */;
  517     params->cameraname = calloc((i+1),sizeof(uint16_t));
  518     for (i=0;name[i];i++)
  519         params->cameraname[i] = name[i];
  520     free (data);
  521     return PTP_RC_OK;
  522 }
  523 
  524 #define ptpip_eventinit_idx 8
  525 #define ptpip_eventinit_size    12
  526 static uint16_t
  527 ptp_ptpip_init_event_request (PTPParams* params)
  528 {
  529     unsigned char   evtrequest[ptpip_eventinit_size];
  530     int         ret;
  531 
  532     htod32a(&evtrequest[ptpip_type],PTPIP_INIT_EVENT_REQUEST);
  533     htod32a(&evtrequest[ptpip_len],ptpip_eventinit_size);
  534     htod32a(&evtrequest[ptpip_eventinit_idx],params->eventpipeid);
  535 
  536     GP_LOG_DATA ((char*)evtrequest, ptpip_eventinit_size, "ptpip/init_event data:");
  537     ret = PTPSOCK_WRITE (params->evtfd, evtrequest, ptpip_eventinit_size);
  538     if (ret == PTPSOCK_ERR) {
  539         perror("write init evt request");
  540         return PTP_RC_GeneralError;
  541     }
  542     if (ret != ptpip_eventinit_size) {
  543         GP_LOG_E ("unexpected retsize %d, expected %d", ret, ptpip_eventinit_size);
  544         return PTP_RC_GeneralError;
  545     }
  546     return PTP_RC_OK;
  547 }
  548 
  549 static uint16_t
  550 ptp_ptpip_init_event_ack (PTPParams* params)
  551 {
  552     PTPIPHeader hdr;
  553     unsigned char   *data = NULL;
  554     uint16_t    ret;
  555 
  556     ret = ptp_ptpip_evt_read (params, &hdr, &data);
  557     if (ret != PTP_RC_OK)
  558         return ret;
  559     free (data);
  560     if (hdr.type != dtoh32(PTPIP_INIT_EVENT_ACK)) {
  561         GP_LOG_E ("bad type returned %d\n", htod32(hdr.type));
  562         return PTP_RC_GeneralError;
  563     }
  564     return PTP_RC_OK;
  565 }
  566 
  567 
  568 /* Event handling functions */
  569 
  570 /* PTP Events wait for or check mode */
  571 
  572 #define ptpip_event_code    0
  573 #define ptpip_event_transid 2
  574 #define ptpip_event_param1  6
  575 #define ptpip_event_param2  10
  576 #define ptpip_event_param3  14
  577 
  578 static uint16_t
  579 ptp_ptpip_event (PTPParams* params, PTPContainer* event, int wait)
  580 {
  581     fd_set      infds;
  582     struct timeval  timeout;
  583     int ret;
  584     unsigned char*  data = NULL;
  585     PTPIPHeader hdr;
  586     int n;
  587 
  588     while (1) {
  589         FD_ZERO(&infds);
  590         FD_SET(params->evtfd, &infds);
  591         timeout.tv_sec = 0;
  592         if (wait == PTP_EVENT_CHECK_FAST)
  593             timeout.tv_usec = 1;
  594         else
  595             timeout.tv_usec = 1000; /* 1/1000 second  .. perhaps wait longer? */
  596 
  597         ret = select (params->evtfd+1, &infds, NULL, NULL, &timeout);
  598         if (1 != ret) {
  599             if (-1 == ret) {
  600                 GP_LOG_D ("select returned error, errno is %d", errno);
  601                 return PTP_ERROR_IO;
  602             }
  603             return PTP_ERROR_TIMEOUT;
  604         }
  605 
  606         ret = ptp_ptpip_evt_read (params, &hdr, &data);
  607         if (ret != PTP_RC_OK)
  608             return ret;
  609         GP_LOG_D ("hdr type %d, length %d", hdr.type, hdr.length);
  610 
  611         if (dtoh32(hdr.type) == PTPIP_EVENT) {
  612             break;
  613         }
  614 
  615         /* TODO: Handle cancel transaction and ping/pong
  616          * If not PTPIP_EVENT, process it and wait for next PTPIP_EVENT
  617          */
  618         GP_LOG_E ("unknown/unhandled event type %d", dtoh32(hdr.type));
  619     }
  620 
  621     event->Code     = dtoh16a(&data[ptpip_event_code]);
  622     event->Transaction_ID   = dtoh32a(&data[ptpip_event_transid]);
  623     n = (dtoh32(hdr.length) - sizeof(hdr) - ptpip_event_param1)/sizeof(uint32_t);
  624     switch (n) {
  625     case 3: event->Param3 = dtoh32a(&data[ptpip_event_param3]);/* fallthrough */
  626     case 2: event->Param2 = dtoh32a(&data[ptpip_event_param2]);/* fallthrough */
  627     case 1: event->Param1 = dtoh32a(&data[ptpip_event_param1]);/* fallthrough */
  628     case 0: break;
  629     default:
  630         GP_LOG_E ("response got %d parameters?", n);
  631         break;
  632     }
  633     free (data);
  634     return PTP_RC_OK;
  635 }
  636 
  637 uint16_t
  638 ptp_ptpip_event_check_queue (PTPParams* params, PTPContainer* event) {
  639     /* the fast check just takes 1ms, so lets keep it */
  640     return ptp_ptpip_event (params, event, PTP_EVENT_CHECK_FAST);
  641 }
  642 
  643 uint16_t
  644 ptp_ptpip_event_check (PTPParams* params, PTPContainer* event) {
  645     return ptp_ptpip_event (params, event, PTP_EVENT_CHECK_FAST);
  646 }
  647 
  648 uint16_t
  649 ptp_ptpip_event_wait (PTPParams* params, PTPContainer* event) {
  650     return ptp_ptpip_event (params, event, PTP_EVENT_CHECK);
  651 }
  652 
  653 /**
  654  * ptp_nikon_getwifiguid:
  655  *
  656  * This command gets the GUID of this machine. If it does not exists, it creates
  657  * one.
  658  *
  659  * params:  PTPParams*
  660  *
  661  * Return values: Some PTP_RC_* code.
  662  *
  663  **/
  664 void
  665 ptp_nikon_getptpipguid (unsigned char* guid) {
  666     char buffer[1024];
  667     int i;
  668     long val;
  669     int valid;
  670     char* endptr;
  671     char* pos;
  672 
  673     gp_setting_get("ptp2_ip","guid",buffer);
  674 
  675     if (strlen(buffer) == 47) { /* 47 = 16*2 (numbers) + 15 (semi-colons) */
  676         pos = buffer;
  677         valid = 1;
  678         for (i = 0; i < 16; i++) {
  679             val = strtol(pos, &endptr, 16);
  680             if (((*endptr != ':') && (*endptr != 0)) || (endptr != pos+2)) {
  681                 valid = 0;
  682                 break;
  683             }
  684             guid[i] = (unsigned char)val;
  685             pos += 3;
  686         }
  687         /*printf("GUID ");
  688         for (i = 0; i < 16; i++) {
  689             printf("%02x:", guid[i]);
  690         }
  691         printf("\n");*/
  692         if (valid)
  693             return;
  694     }
  695 
  696     /*fprintf(stderr, "Invalid GUID\n");*/
  697 
  698     /* Generate an ID */
  699     srand(time(NULL));
  700     buffer[0] = 0;
  701     pos = buffer;
  702     for (i = 0; i < 16; i++) {
  703         guid[i] = (unsigned char) ((256.0 * rand()) / RAND_MAX);
  704         pos += sprintf(pos, "%02x:", guid[i]);
  705     }
  706     buffer[47] = 0;
  707 
  708     /*printf("New GUID: %s\n", buffer);*/
  709 
  710     gp_setting_set("ptp2_ip","guid",buffer);
  711 }
  712 
  713 
  714 int
  715 ptp_ptpip_connect (PTPParams* params, const char *address) {
  716     char        *addr, *s, *p;
  717     int     port, eventport, tries;
  718     struct sockaddr_in  saddr;
  719     uint16_t    ret;
  720 
  721     GP_LOG_D ("connecting to %s.", address);
  722     if (NULL == strchr (address,':'))
  723         return GP_ERROR_BAD_PARAMETERS;
  724 
  725     addr = strdup (address);
  726     if (!addr)
  727         return GP_ERROR_NO_MEMORY;
  728     s = strchr (addr,':');
  729     if (!s) {
  730         GP_LOG_E ("addr %s should contain a :", address);
  731         free (addr);
  732         return GP_ERROR_BAD_PARAMETERS;
  733     }
  734     *s = '\0';
  735     p = strchr (s+1,':');
  736     eventport = port = 15740;
  737     if (p) {
  738         *p = '\0';
  739         if (!sscanf (p+1,"%d",&port)) {
  740             fprintf(stderr,"failed to scan for port in %s\n", p+1);
  741             free (addr);
  742             return GP_ERROR_BAD_PARAMETERS;
  743         }
  744         /* different event port ? */
  745         p = strchr (p+1,':');
  746         if (p) {
  747             if (!sscanf (p+1,"%d",&eventport)) {
  748                 fprintf(stderr,"failed to scan for eventport in %s\n", p+1);
  749                 free (addr);
  750                 return GP_ERROR_BAD_PARAMETERS;
  751             }
  752         }
  753     }
  754 #ifdef HAVE_INET_ATON
  755     if (!inet_aton (s+1,  &saddr.sin_addr)) {
  756 #else
  757     if (inet_pton(AF_INET, s+1, &saddr.sin_addr) != 1) {
  758 #endif
  759         fprintf(stderr,"failed to scan for addr in %s\n", s+1);
  760         free (addr);
  761         return GP_ERROR_BAD_PARAMETERS;
  762     }
  763     saddr.sin_port      = htons(port);
  764     saddr.sin_family    = AF_INET;
  765     free (addr);
  766     PTPSOCK_SOCKTYPE cmdfd = params->cmdfd = socket (PF_INET, SOCK_STREAM, PTPSOCK_PROTO);
  767     if (cmdfd == PTPSOCK_INVALID) {
  768         perror ("socket cmd");
  769         return GP_ERROR_BAD_PARAMETERS;
  770     }
  771     PTPSOCK_SOCKTYPE evtfd = params->evtfd = socket (PF_INET, SOCK_STREAM, PTPSOCK_PROTO);
  772     if (evtfd == PTPSOCK_INVALID) {
  773         perror ("socket evt");
  774         PTPSOCK_CLOSE (params->cmdfd);
  775         return GP_ERROR_BAD_PARAMETERS;
  776     }
  777     if (PTPSOCK_ERR == connect (params->cmdfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in))) {
  778         perror ("connect cmd");
  779         PTPSOCK_CLOSE (params->cmdfd);
  780         PTPSOCK_CLOSE (params->evtfd);
  781         return GP_ERROR_IO;
  782     }
  783     ret = ptp_ptpip_init_command_request (params);
  784     if (ret != PTP_RC_OK) {
  785         PTPSOCK_CLOSE (params->cmdfd);
  786         PTPSOCK_CLOSE (params->evtfd);
  787         return translate_ptp_result (ret);
  788     }
  789     ret = ptp_ptpip_init_command_ack (params);
  790     if (ret != PTP_RC_OK) {
  791         PTPSOCK_CLOSE (params->cmdfd);
  792         PTPSOCK_CLOSE (params->evtfd);
  793         return translate_ptp_result (ret);
  794     }
  795     /* seen on Ricoh Theta, camera is not immediately ready. try again two times. */
  796     tries = 2;
  797     saddr.sin_port      = htons(eventport);
  798     do {
  799         if (PTPSOCK_ERR != connect (params->evtfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)))
  800             break;
  801         if ((errno == ECONNREFUSED) && (tries--)) {
  802             GP_LOG_D ("event connect failed, retrying after short wait");
  803             int sleep_ms = 100;
  804 #ifdef WIN32
  805             Sleep(sleep_ms);
  806 #else
  807             usleep(sleep_ms*1000);
  808 #endif
  809             continue;
  810         }
  811         GP_LOG_E ("could not connect event");
  812         PTPSOCK_CLOSE (params->cmdfd);
  813         PTPSOCK_CLOSE (params->evtfd);
  814         return GP_ERROR_IO;
  815     } while (1);
  816     ret = ptp_ptpip_init_event_request (params);
  817     if (ret != PTP_RC_OK)
  818         return translate_ptp_result (ret);
  819     ret = ptp_ptpip_init_event_ack (params);
  820     if (ret != PTP_RC_OK)
  821         return translate_ptp_result (ret);
  822     GP_LOG_D ("ptpip connected!");
  823     return GP_OK;
  824 }