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