"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 }