"Fossies" - the Fresh Open Source Software Archive 
Member "libgphoto2-2.5.27/camlibs/ptp2/olympus-wrap.c" (14 Feb 2021, 40724 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 "olympus-wrap.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 /* olympus_wrap.c
2 *
3 * Copyright (c) 2012-2013 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.1 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 * Notes:
21 * XDISCVRY.X3C file sent on start, empty.
22 */
23
24 #define _DEFAULT_SOURCE
25
26 #include "config.h"
27
28 #ifdef HAVE_LIBXML2
29
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <_stdint.h>
34
35 #include <libxml/parser.h>
36
37 #include "ptp.h"
38 #include "ptp-private.h"
39 #include "ptp-pack.c"
40 #include "olympus-wrap.h"
41
42 #include <gphoto2/gphoto2-library.h>
43 #include <gphoto2/gphoto2-setting.h>
44 #include <gphoto2/gphoto2-result.h>
45 #include <gphoto2/gphoto2-port-log.h>
46
47 /*
48 * The following things are the way the are just to ensure that USB
49 * wrapper packets have the correct byte-order on all types of machines.
50 * Intel byte order is used instead of "network" byte order :-(
51 */
52 typedef struct
53 { unsigned char c1, c2, c3, c4; } uw32_t; /* A type for 32-bit integers */
54 typedef struct
55 { unsigned char c1, c2, c3, c4; } uw4c_t; /* A type for 4-byte things */
56
57 static uw32_t uw_value(unsigned int value) /* Convert from host-integer to uw32_t */
58 {
59 uw32_t ret;
60 ret.c1 = (value & 0x000000ffUL);
61 ret.c2 = (value >> 8 & 0x000000ffUL);
62 ret.c3 = (value >> 16 & 0x000000ffUL);
63 ret.c4 = (value >> 24 & 0x000000ffUL);
64 return ret;
65 }
66
67 static unsigned char
68 cmdbyte (unsigned char nr) {
69 return nr | 0xc0;
70 }
71
72 /* Test for equality between two uw32_t's or two uw4c_t's. */
73 #define UW_EQUAL(a, b) \
74 ((a).c1==(b).c1 && (a).c2==(b).c2 && (a).c3==(b).c3 && (a).c4==(b).c4)
75
76 /*
77 * USB storage wrapper packets start with ASCII bytes "USBC".
78 * The responses back from the camera start with "USBS".
79 */
80 #define UW_MAGIC_OUT ((uw4c_t){ 'U','S','B','C' })
81 #define UW_MAGIC_IN ((uw4c_t){ 'U','S','B','S' })
82
83 #pragma pack(1)
84 /*
85 * The rest of the USB wrapper packet looks like this:
86 */
87
88 /* This is linux/include/linux/usb/storage.h, struct bulk_cb_wrap
89 * 31 byte length */
90 typedef struct
91 {
92 uw4c_t magic; /* The letters U S B C for packets sent to camera */
93 uw32_t tag; /* The SCSI command tag */
94 uw32_t rw_length; /* Length of data to be read or written next */
95 unsigned char flags; /* in / out flag mostly */
96 unsigned char lun; /* 0 here */
97 unsigned char length; /* of the CDB... but 0x0c is used here in the traces */
98 unsigned char cdb[16];
99 } uw_header_t;
100
101 /*
102 * This is the end response block from the camera looks like this:
103 *
104 * This is the generic bulk style USB Storage response block.
105 *
106 * linux/include/linux/usb/storage.h, struct bulk_cs_wrap */
107 typedef struct
108 {
109 uw4c_t magic; /* The letters U S B S for packets from camera */
110 uw32_t tag; /* A copy of whatever value the host made up */
111 uw32_t residue; /* residual read? */
112 char status; /* status byte */
113 } uw_response_t;
114
115
116 /* In the SCSI API, the CDB[16] block. */
117 typedef struct
118 {
119 unsigned char cmd;
120 char zero1[8];
121 uw32_t length;
122 char zero2[3];
123 } uw_scsicmd_t;
124
125 #pragma pack()
126
127 /* This is for the unique tag id for the UMS command / response
128 * It gets incremented by one for every command.
129 */
130 static int ums_tag = 0x42424242;
131 /*
132 * This routine is called after every UW_REQUEST_XXX to get an OK
133 * with a matching session ID.
134 */
135 static int
136 usb_wrap_OK (GPPort *dev, uw_header_t *hdr)
137 {
138 uw_response_t rsp;
139 int ret;
140 memset(&rsp, 0, sizeof(rsp));
141
142 GP_LOG_D ("usb_wrap_OK");
143 if ((ret = gp_port_read(dev, (char*)&rsp, sizeof(rsp))) != sizeof(rsp)) {
144 GP_LOG_D ("gp_port_read *** FAILED (%d vs %d bytes)", (int)sizeof(rsp), ret);
145 if (ret < GP_OK)
146 return ret;
147 return GP_ERROR;
148 }
149 if ( !UW_EQUAL(rsp.magic, UW_MAGIC_IN) ||
150 !UW_EQUAL(rsp.tag, hdr->tag))
151 {
152 GP_LOG_E ("usb_wrap_OK wrong session *** FAILED");
153 return GP_ERROR;
154 }
155 /*
156 * 32bit residual length (0) and 8 bit status (0) are good.
157 */
158 if ( rsp.residue.c1 != 0 ||
159 rsp.residue.c2 != 0 ||
160 rsp.residue.c3 != 0 ||
161 rsp.residue.c4 != 0 ||
162 rsp.status != 0) {
163 GP_LOG_E ("Error: usb_wrap_OK failed - residual non-0 or status %x", rsp.status);
164 return GP_ERROR;
165 }
166 return GP_OK;
167 }
168
169 /* so it mirrors:
170 ret = gp_port_send_scsi_cmd (camera->port, 1, (char*)&cmd, sizeof(cmd),
171 sense_buffer, sizeof(sense_buffer), (char*)&usbreq, usbreq.length);
172 */
173 static int
174 scsi_wrap_cmd(
175 GPPort *port,
176 int todev,
177 char *cmd, unsigned int cmdlen,
178 char *sense, unsigned int senselen,
179 char *data, unsigned int size
180 ) {
181 uw_header_t hdr;
182 int ret;
183
184 memset(&hdr, 0, sizeof(hdr));
185 hdr.magic = UW_MAGIC_OUT;
186 hdr.tag = uw_value(ums_tag);
187 ums_tag++;
188 hdr.rw_length = uw_value(size);
189 hdr.length = 12; /* seems to be always 12, even as we send 16 byte CDBs */
190 hdr.flags = todev?0:(1<<7);
191 hdr.lun = 0;
192
193 memcpy(hdr.cdb, cmd, cmdlen);
194
195 if ((ret=gp_port_write(port, (char*)&hdr, sizeof(hdr))) < GP_OK) {
196 GP_LOG_E ("scsi_wrap_cmd *** FAILED to write scsi cmd");
197 return GP_ERROR_IO;
198 }
199 if (todev) {
200 if ((ret=gp_port_write(port, (char*)data, size)) < GP_OK) {
201 GP_LOG_E ("scsi_wrap_cmd *** FAILED to write scsi data");
202 return GP_ERROR_IO;
203 }
204 } else {
205 if ((ret=gp_port_read(port, (char*)data, size)) < GP_OK) {
206 GP_LOG_E ("scsi_wrap_cmd *** FAILED to read scsi data");
207 return GP_ERROR_IO;
208 }
209 }
210 if ((ret=usb_wrap_OK(port, &hdr)) != GP_OK) {
211 GP_LOG_E ("scsi_wrap_cmd *** FAILED to get scsi reply");
212 return GP_ERROR_IO;
213 }
214 return GP_OK;
215 }
216
217 #define gp_port_send_scsi_cmd scsi_wrap_cmd
218
219 /* Transaction data phase description */
220 #define PTP_DP_NODATA 0x0000 /* no data phase */
221 #define PTP_DP_SENDDATA 0x0001 /* sending data */
222 #define PTP_DP_GETDATA 0x0002 /* receiving data */
223 #define PTP_DP_DATA_MASK 0x00ff /* data phase mask */
224
225 static uint16_t
226 ums_wrap_sendreq (PTPParams* params, PTPContainer* req, int dataphase) {
227 Camera *camera = ((PTPData *)params->data)->camera;
228 PTPUSBBulkContainer usbreq;
229 char buf[64];
230 int ret;
231 uw_scsicmd_t cmd;
232 char sense_buffer[32];
233
234 GP_LOG_D ("ums_wrap_sendreq");
235 /* Build appropriate USB container */
236 usbreq.length= htod32(PTP_USB_BULK_REQ_LEN-
237 (sizeof(uint32_t)*(5-req->Nparam)));
238 usbreq.type = htod16(PTP_USB_CONTAINER_COMMAND);
239 usbreq.code = htod16(req->Code);
240 usbreq.trans_id = htod32(req->Transaction_ID);
241 usbreq.payload.params.param1 = htod32(req->Param1);
242 usbreq.payload.params.param2 = htod32(req->Param2);
243 usbreq.payload.params.param3 = htod32(req->Param3);
244 usbreq.payload.params.param4 = htod32(req->Param4);
245 usbreq.payload.params.param5 = htod32(req->Param5);
246
247 memset(buf,0,sizeof(buf));
248
249 memset (&cmd, 0, sizeof(cmd));
250 cmd.cmd = cmdbyte(0);
251 cmd.length = uw_value(usbreq.length);
252
253 ret = gp_port_send_scsi_cmd (camera->port, 1, (char*)&cmd, sizeof(cmd),
254 sense_buffer, sizeof(sense_buffer), (char*)&usbreq, usbreq.length);
255 GP_LOG_D ("send_scsi_cmd ret %d", ret);
256 return PTP_RC_OK;
257 }
258
259 static uint16_t
260 ums_wrap_senddata (
261 PTPParams* params, PTPContainer* ptp, uint64_t sendlen, PTPDataHandler*getter
262 ) {
263 Camera *camera = ((PTPData *)params->data)->camera;
264 PTPUSBBulkContainer usbreq;
265 int ret;
266 unsigned long gotlen;
267 unsigned char *xdata;
268 uw_scsicmd_t cmd;
269 char sense_buffer[32];
270
271 GP_LOG_D ("ums_wrap_senddata");
272
273 memset (&cmd, 0, sizeof(cmd));
274 cmd.cmd = cmdbyte(1);
275 cmd.length = uw_value(sendlen+12);
276
277 xdata = malloc(sendlen + 12);
278 usbreq.length = htod32(sendlen + 12);
279 usbreq.type = htod16(PTP_USB_CONTAINER_DATA);
280 usbreq.code = htod16(ptp->Code);
281 usbreq.trans_id = htod32(ptp->Transaction_ID);
282 memcpy (xdata, &usbreq, 12);
283 ret = getter->getfunc(params, getter->priv, sendlen, xdata+12, &gotlen);
284 if (ret != PTP_RC_OK) {
285 GP_LOG_E ("ums_wrap_senddata *** data get from handler FAILED, ret %d", ret);
286 return ret;
287 }
288 if (gotlen != sendlen) {
289 GP_LOG_E ("ums_wrap_senddata *** data get from handler got %ld instead of %ld", gotlen, sendlen);
290 return PTP_ERROR_IO;
291 }
292
293 ret = gp_port_send_scsi_cmd (camera->port, 1, (char*)&cmd, sizeof(cmd),
294 sense_buffer, sizeof(sense_buffer), (char*)xdata, sendlen+12);
295
296 GP_LOG_D ("send_scsi_cmd ret %d", ret);
297
298 free (xdata);
299
300 return PTP_RC_OK;
301 }
302
303 static uint16_t
304 ums_wrap_getresp (PTPParams* params, PTPContainer* resp)
305 {
306 Camera *camera = ((PTPData *)params->data)->camera;
307 PTPUSBBulkContainer usbresp;
308 char buf[64];
309 int ret;
310 uw_scsicmd_t cmd;
311 char sense_buffer[32];
312
313 GP_LOG_D ("ums_wrap_getresp");
314 memset (&cmd, 0, sizeof(cmd));
315 cmd.cmd = cmdbyte(3);
316 cmd.length = uw_value(sizeof(buf));
317
318 ret = gp_port_send_scsi_cmd (camera->port, 0, (char*)&cmd, sizeof(cmd),
319 sense_buffer, sizeof(sense_buffer), (char*)buf, sizeof(buf));
320
321 GP_LOG_D ("send_scsi_cmd ret %d", ret);
322
323 memcpy (&usbresp, buf, sizeof(buf));
324 resp->Code = dtoh16(usbresp.code);
325 resp->Nparam = (dtoh32(usbresp.length)-PTP_USB_BULK_REQ_LEN)/sizeof(uint32_t);
326 resp->Param1 = dtoh32(usbresp.payload.params.param1);
327 resp->Param2 = dtoh32(usbresp.payload.params.param2);
328 resp->Param3 = dtoh32(usbresp.payload.params.param3);
329 resp->Param4 = dtoh32(usbresp.payload.params.param4);
330 resp->Param5 = dtoh32(usbresp.payload.params.param5);
331 return PTP_RC_OK;
332 }
333
334 static uint16_t
335 ums_wrap_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *putter)
336 {
337 Camera *camera = ((PTPData *)params->data)->camera;
338 PTPUSBBulkContainer usbresp;
339 char buf[64];
340 int ret;
341 unsigned long recvlen;
342 char *data;
343 uw_scsicmd_t cmd;
344 char sense_buffer[32];
345
346 GP_LOG_D ("ums_wrap_getdata");
347
348 memset(&cmd,0,sizeof(cmd));
349 cmd.cmd = cmdbyte(4);
350 cmd.length = uw_value(sizeof(buf));
351
352 ret = gp_port_send_scsi_cmd (camera->port, 0, (char*)&cmd, sizeof(cmd),
353 sense_buffer, sizeof(sense_buffer), (char*)buf, sizeof(buf));
354
355 GP_LOG_D ("send_scsi_cmd ret %d", ret);
356
357 memcpy (&usbresp, buf, sizeof(buf));
358 if ((dtoh16(usbresp.code) != ptp->Code) && (dtoh16(usbresp.code) != PTP_RC_OK)) {
359 GP_LOG_D ("ums_wrap_getdata *** PTP code %04x during PTP data in size read", dtoh16(usbresp.code));
360 /* break; */
361 }
362 if (dtoh16(usbresp.length) < 16) {
363 recvlen = 0;
364 GP_LOG_D ("ums_wrap_getdata *** PTP size %d during PTP data in size read, expected 16", dtoh16(usbresp.length));
365 } else {
366 recvlen = dtoh32(usbresp.payload.params.param1);
367 }
368 data = malloc (recvlen);
369 if (!data)
370 return PTP_ERROR_IO;
371
372 memset(&cmd,0,sizeof(cmd));
373 cmd.cmd = cmdbyte(2);
374 cmd.length = uw_value(recvlen);
375
376 ret = gp_port_send_scsi_cmd (camera->port, 0, (char*)&cmd, sizeof(cmd),
377 sense_buffer, sizeof(sense_buffer), (char*)data, recvlen);
378
379 GP_LOG_D ("send_scsi_cmd 2 ret %d", ret);
380 /* skip away the 12 byte header */
381 if (recvlen >= 16)
382 GP_LOG_DATA (data + PTP_USB_BULK_HDR_LEN, recvlen - PTP_USB_BULK_HDR_LEN, "ptp2/olympus/getdata");
383 ret = putter->putfunc ( params, putter->priv, recvlen - PTP_USB_BULK_HDR_LEN, (unsigned char*)data + PTP_USB_BULK_HDR_LEN);
384 free (data);
385 if (ret != PTP_RC_OK) {
386 GP_LOG_E ("ums_wrap_getdata FAILED to push data into put handle, ret %x", ret);
387 return PTP_ERROR_IO;
388 }
389 return PTP_RC_OK;
390 }
391
392 static char* generate_event_OK_xml(PTPParams *params, PTPContainer *ptp);
393 static int parse_event_xml(PTPParams *params, const char *txt, PTPContainer *resp);
394
395 static int
396 olympus_xml_transfer (PTPParams *params,
397 char *cmdxml, char **inxml
398 ) {
399 PTPContainer ptp2;
400 int res;
401 PTPObjectInfo oi;
402 unsigned char *resxml, *oidata = NULL;
403 uint32_t size, newhandle;
404 uint16_t ret;
405 PTPParams *outerparams = params->outer_params;
406
407 GP_LOG_D ("olympus_xml_transfer");
408 while (1) {
409 GP_LOG_D ("... checking camera for events ...");
410 ret = outerparams->event_check(outerparams, &ptp2);
411 if (ret == PTP_RC_OK) {
412 char *evxml;
413
414 GP_LOG_D ("event: code %04x, p %08x", ptp2.Code, ptp2.Param1);
415
416 if (ptp2.Code != PTP_EC_RequestObjectTransfer) {
417 ptp_add_event (params, &ptp2);
418 goto skip;
419 }
420 newhandle = ptp2.Param1;
421 if ((newhandle & 0xff000000) != 0x1e000000) {
422 GP_LOG_D ("event 0x%04x, handle 0x%08x received, no XML event, just passing on", ptp2.Code, ptp2.Param1);
423 ptp_add_event (params, &ptp2);
424 continue;
425 }
426
427 ret = ptp_getobjectinfo (outerparams, newhandle, &oi);
428 if (ret != PTP_RC_OK)
429 return ret;
430 eventhandler:
431 GP_LOG_D ("event xml transfer: got new file: %s", oi.Filename);
432 ret = ptp_getobject (outerparams, newhandle, (unsigned char**)&resxml);
433 if (ret != PTP_RC_OK)
434 return ret;
435 evxml = malloc (oi.ObjectCompressedSize + 1);
436 memcpy (evxml, resxml, oi.ObjectCompressedSize);
437 evxml[oi.ObjectCompressedSize] = 0x00;
438
439 GP_LOG_D ("file content: %s", evxml);
440
441 parse_event_xml (params, evxml, &ptp2);
442 /* parse it */
443
444 evxml = generate_event_OK_xml(params, &ptp2);
445
446 GP_LOG_D ("... sending XML event reply to camera ... ");
447 memset (&ptp2, 0 , sizeof (ptp2));
448 ptp2.Code = PTP_OC_SendObjectInfo;
449 ptp2.Nparam = 1;
450 ptp2.Param1 = 0x80000001;
451
452 memset (&oi, 0, sizeof (oi));
453 oi.ObjectFormat = PTP_OFC_Script;
454 oi.StorageID = 0x80000001;
455 oi.Filename = "HRSPONSE.X3C";
456 oi.ObjectCompressedSize = strlen(evxml);
457 size = ptp_pack_OI(params, &oi, &oidata);
458 res = ptp_transaction (outerparams, &ptp2, PTP_DP_SENDDATA, size, &oidata, NULL);
459 if (res != PTP_RC_OK)
460 return res;
461 free(oidata);
462 /*handle = ptp2.Param3; ... we do not use the returned handle and leave the file on camera. */
463
464 ptp2.Code = PTP_OC_SendObject;
465 ptp2.Nparam = 0;
466 res = ptp_transaction(outerparams, &ptp2, PTP_DP_SENDDATA, strlen(evxml), (unsigned char**)&evxml, NULL);
467 if (res != PTP_RC_OK)
468 return res;
469 continue;
470 }
471 skip:
472
473 GP_LOG_D ("... sending XML request to camera ... ");
474 memset (&ptp2, 0 , sizeof (ptp2));
475 ptp2.Code = PTP_OC_SendObjectInfo;
476 ptp2.Nparam = 1;
477 ptp2.Param1 = 0x80000001;
478
479 memset (&oi, 0, sizeof (oi));
480 oi.ObjectFormat = PTP_OFC_Script;
481 oi.StorageID = 0x80000001;
482 oi.Filename = "HREQUEST.X3C";
483 oi.ObjectCompressedSize = strlen(cmdxml);
484
485 /*
486 "HRSPONSE.X3C" ... sent back to camera after receiving an event.
487 <output><result>2001</result><ec102/></output
488 */
489
490 size = ptp_pack_OI(params, &oi, &oidata);
491 res = ptp_transaction (outerparams, &ptp2, PTP_DP_SENDDATA, size, &oidata, NULL);
492 if (res != PTP_RC_OK)
493 return res;
494 free(oidata);
495 /*handle = ptp2.Param3; ... we do not use the returned handle and leave the file on camera. */
496
497 ptp2.Code = PTP_OC_SendObject;
498 ptp2.Nparam = 0;
499 res = ptp_transaction(outerparams, &ptp2, PTP_DP_SENDDATA, strlen(cmdxml), (unsigned char**)&cmdxml, NULL);
500 if (res != PTP_RC_OK)
501 return res;
502
503 GP_LOG_D ("... waiting for camera ...");
504 redo:
505 ret = outerparams->event_wait(outerparams, &ptp2);
506 if (ret != PTP_RC_OK)
507 return ret;
508 GP_LOG_D ("event: code %04x, p %08x", ptp2.Code, ptp2.Param1);
509 if (ptp2.Code != PTP_EC_RequestObjectTransfer) {
510 ptp_add_event (params, &ptp2);
511 goto redo;
512 }
513 /* FIXME: check for 0x1e0000* ? */
514 newhandle = ptp2.Param1;
515 ret = ptp_getobjectinfo (outerparams, newhandle, &oi);
516 if (ret != PTP_RC_OK)
517 return ret;
518 GP_LOG_D ("regular xml transfer: got new file: %s", oi.Filename);
519 if (strcmp(oi.Filename,"DRSPONSE.X3C")) {
520 GP_LOG_E ("FIXME: regular xml transfer: got new file: %s", oi.Filename);
521 goto eventhandler;
522 }
523 ret = ptp_getobject (outerparams, newhandle, (unsigned char**)&resxml);
524 if (ret != PTP_RC_OK)
525 return ret;
526 *inxml = malloc (oi.ObjectCompressedSize + 1);
527 memcpy (*inxml, resxml, oi.ObjectCompressedSize);
528 (*inxml)[oi.ObjectCompressedSize] = 0x00;
529
530 GP_LOG_D ("file content: %s", *inxml);
531 /* parse it */
532 break;
533 }
534 return PTP_RC_OK;
535 }
536
537 static int
538 traverse_tree (PTPParams *params, int depth, xmlNodePtr node) {
539 xmlNodePtr next;
540 xmlChar *xchar;
541 int n;
542 char *xx;
543
544
545 if (!node) return FALSE;
546 xx = malloc(depth * 4 + 1);
547 memset (xx, ' ', depth*4);
548 xx[depth*4] = 0;
549
550 n = xmlChildElementCount (node);
551
552 next = node;
553 do {
554 ptp_debug(params,"%snode %s", xx, next->name);
555 ptp_debug(params,"%selements %d", xx, n);
556 xchar = xmlNodeGetContent (next);
557 ptp_debug(params,"%scontent %s", xx, xchar);
558 traverse_tree (params, depth+1,xmlFirstElementChild (next));
559 } while ((next = xmlNextElementSibling (next)));
560 free (xx);
561 return TRUE;
562 }
563
564 static int
565 parse_9581_tree (xmlNodePtr node) {
566 xmlNodePtr next;
567
568 next = xmlFirstElementChild (node);
569 while (next) {
570 if (!strcmp ((char*)next->name, "data")) {
571 char *decoded, *x;
572 char *xchars = (char*)xmlNodeGetContent (next);
573
574 x = decoded = malloc(strlen(xchars)+1);
575 while (xchars[0] && xchars[1]) {
576 int y;
577 sscanf(xchars,"%02x", &y);
578 *x++ = y;
579 xchars+=2;
580 }
581 *x = '\0';
582 GP_LOG_D ("9581: %s", decoded);
583
584
585 next = xmlNextElementSibling (next);
586 free (decoded);
587 continue;
588 }
589 GP_LOG_E ("9581: unhandled node type %s", next->name);
590 next = xmlNextElementSibling (next);
591 }
592 /*traverse_tree (0, node);*/
593 return TRUE;
594 }
595
596 static int
597 parse_910a_tree (xmlNodePtr node) {
598 xmlNodePtr next;
599
600 next = xmlFirstElementChild (node);
601 do {
602 if (!strcmp ((char*)next->name, "param")) {
603 unsigned int x;
604 xmlChar *xchar = xmlNodeGetContent (next);
605 if (!sscanf((char*)xchar,"%08x", &x)) {
606 fprintf(stderr,"could not parse param content %s\n", xchar);
607 }
608 fprintf(stderr,"param content is 0x%08x\n", x);
609 continue;
610 }
611 fprintf (stderr,"910a: unhandled type %s\n", next->name);
612 } while ((next = xmlNextElementSibling (next)));
613 /*traverse_tree (0, node);*/
614 return TRUE;
615 }
616
617 static int
618 parse_9302_tree (xmlNodePtr node) {
619 xmlNodePtr next;
620 xmlChar *xchar;
621
622 next = xmlFirstElementChild (node);
623 while (next) {
624 if (!strcmp((char*)next->name, "x3cVersion")) {
625 int x3cver;
626 xchar = xmlNodeGetContent (next);
627 sscanf((char*)xchar, "%04x", &x3cver);
628 GP_LOG_D ("x3cVersion %d.%d", (x3cver>>8)&0xff, x3cver&0xff);
629 goto xnext;
630 }
631 if (!strcmp((char*)next->name, "productIDs")) {
632 char *x, *nextspace;
633 int len;
634 x = (char*)(xchar = xmlNodeGetContent (next));
635 GP_LOG_D ("productIDs:");
636
637 do {
638 nextspace=strchr(x,' ');
639 if (nextspace) nextspace++;
640
641 /* ascii ptp string, 1 byte length, little endian 16 bit chars */
642 if (sscanf(x,"%02x", &len)) {
643 int i;
644 char *str = malloc(len+1);
645 for (i=0;i<len;i++) {
646 int xc;
647 if (sscanf(x+2+i*4,"%04x", &xc)) {
648 int cx;
649
650 cx = ((xc>>8) & 0xff) | ((xc & 0xff) << 8);
651 str[i] = cx;
652 }
653 str[len] = 0;
654 }
655 GP_LOG_D ("\t%s", str);
656 free (str);
657 }
658 x = nextspace;
659 } while (x);
660
661 goto xnext;
662 }
663 GP_LOG_E ("unknown node in 9301: %s", next->name);
664 xnext:
665 next = xmlNextElementSibling (next);
666 }
667 return TRUE;
668 }
669
670 #if 0
671 static int
672 parse_9301_value (PTPParams *params, const char *str, uint16_t type, PTPPropertyValue *propval) {
673 switch (type) {
674 case 6: { /*UINT32*/
675 unsigned int x;
676 if (!sscanf(str,"%08x", &x)) {
677 ptp_debug( params, "could not parse uint32 %s", str);
678 return PTP_RC_GeneralError;
679 }
680 ptp_debug( params, "\t%d", x);
681 propval->u32 = x;
682 break;
683 }
684 case 5: { /*INT32*/
685 int x;
686 if (!sscanf(str,"%08x", &x)) {
687 ptp_debug( params, "could not parse int32 %s", str);
688 return PTP_RC_GeneralError;
689 }
690 ptp_debug( params, "\t%d", x);
691 propval->i32 = x;
692 break;
693 }
694 case 4: { /*UINT16*/
695 unsigned int x;
696 if (!sscanf(str,"%04x", &x)) {
697 ptp_debug( params, "could not parse uint16 %s", str);
698 return PTP_RC_GeneralError;
699 }
700 ptp_debug( params, "\t%d", x);
701 propval->u16 = x;
702 break;
703 }
704 case 3: { /*INT16*/
705 int x;
706 if (!sscanf(str,"%04x", &x)) {
707 ptp_debug( params, "could not parse int16 %s", str);
708 return PTP_RC_GeneralError;
709 }
710 ptp_debug( params, "\t%d", x);
711 propval->i16 = x;
712 break;
713 }
714 case 2: { /*UINT8*/
715 unsigned int x;
716 if (!sscanf(str,"%02x", &x)) {
717 ptp_debug( params, "could not parse uint8 %s", str);
718 return PTP_RC_GeneralError;
719 }
720 ptp_debug( params, "\t%d", x);
721 propval->u8 = x;
722 break;
723 }
724 case 1: { /*INT8*/
725 int x;
726 if (!sscanf(str,"%02x", &x)) {
727 ptp_debug( params, "could not parse int8 %s", str);
728 return PTP_RC_GeneralError;
729 }
730 ptp_debug( params, "\t%d", x);
731 propval->i8 = x;
732 break;
733 }
734 case 65535: { /* string */
735 int len;
736
737 /* ascii ptp string, 1 byte length, little endian 16 bit chars */
738 if (sscanf(str,"%02x", &len)) {
739 int i;
740 char *xstr = malloc(len+1);
741 for (i=0;i<len;i++) {
742 int xc;
743 if (sscanf(str+2+i*4,"%04x", &xc)) {
744 int cx;
745
746 cx = ((xc>>8) & 0xff) | ((xc & 0xff) << 8);
747 xstr[i] = cx;
748 }
749 xstr[len] = 0;
750 }
751 ptp_debug( params, "\t%s", xstr);
752 propval->str = xstr;
753 break;
754 }
755 ptp_debug( params, "string %s not parseable!", str);
756 return PTP_RC_GeneralError;
757 }
758 case 7: /*INT64*/
759 case 8: /*UINT64*/
760 case 9: /*INT128*/
761 case 10: /*UINT128*/
762 default:
763 ptp_debug( params, "unhandled data type %d!", type);
764 return PTP_RC_GeneralError;
765 }
766 return PTP_RC_OK;
767 }
768
769
770 static int
771 parse_9301_propdesc (PTPParams *params, xmlNodePtr node, PTPDevicePropDesc *dpd) {
772 xmlNodePtr next;
773 int type = -1;
774
775 dpd->FormFlag = PTP_DPFF_None;
776 dpd->GetSet = PTP_DPGS_Get;
777 next = xmlFirstElementChild (node);
778 do {
779 if (!strcmp((char*)next->name,"type")) { /* propdesc.DataType */
780 if (!sscanf((char*)xmlNodeGetContent (next), "%04x", &type)) {
781 ptp_debug( params, "\ttype %s not parseable?",xmlNodeGetContent (next));
782 return 0;
783 }
784 ptp_debug( params, "type 0x%x", type);
785 dpd->DataType = type;
786 continue;
787 }
788 if (!strcmp((char*)next->name,"attribute")) { /* propdesc.GetSet */
789 int attr;
790
791 if (!sscanf((char*)xmlNodeGetContent (next), "%02x", &attr)) {
792 ptp_debug( params, "\tattr %s not parseable",xmlNodeGetContent (next));
793 return 0;
794 }
795 ptp_debug( params, "attribute 0x%x", attr);
796 dpd->GetSet = attr;
797 continue;
798 }
799 if (!strcmp((char*)next->name,"default")) { /* propdesc.FactoryDefaultValue */
800 ptp_debug( params, "default value");
801 parse_9301_value (params, (char*)xmlNodeGetContent (next), type, &dpd->FactoryDefaultValue);
802 continue;
803 }
804 if (!strcmp((char*)next->name,"value")) { /* propdesc.CurrentValue */
805 ptp_debug( params, "current value");
806 parse_9301_value (params, (char*)xmlNodeGetContent (next), type, &dpd->CurrentValue);
807 continue;
808 }
809 if (!strcmp((char*)next->name,"enum")) { /* propdesc.FORM.Enum */
810 int n,i;
811 char *s;
812
813 ptp_debug( params, "enum");
814 dpd->FormFlag = PTP_DPFF_Enumeration;
815 s = (char*)xmlNodeGetContent (next);
816 n = 0;
817 do {
818 s = strchr(s,' ');
819 if (s) s++;
820 n++;
821 } while (s);
822 dpd->FORM.Enum.NumberOfValues = n;
823 dpd->FORM.Enum.SupportedValue = calloc (n , sizeof(PTPPropertyValue));
824 s = (char*)xmlNodeGetContent (next);
825 i = 0;
826 do {
827 parse_9301_value (params, s, type, &dpd->FORM.Enum.SupportedValue[i]); /* should turn ' ' into \0? */
828 i++;
829 s = strchr(s,' ');
830 if (s) s++;
831 } while (s && (i<n));
832 continue;
833 }
834 if (!strcmp((char*)next->name,"range")) { /* propdesc.FORM.Enum */
835 char *s = (char*)xmlNodeGetContent (next);
836 dpd->FormFlag = PTP_DPFF_Range;
837 ptp_debug( params, "range");
838 parse_9301_value (params, s, type, &dpd->FORM.Range.MinimumValue); /* should turn ' ' into \0? */
839 s = strchr(s,' ');
840 if (!s) continue;
841 s++;
842 parse_9301_value (params, s, type, &dpd->FORM.Range.MaximumValue); /* should turn ' ' into \0? */
843 s = strchr(s,' ');
844 if (!s) continue;
845 s++;
846 parse_9301_value (params, s, type, &dpd->FORM.Range.StepSize); /* should turn ' ' into \0? */
847
848 continue;
849 }
850 ptp_debug (params, "\tpropdescvar: %s", next->name);
851 ptp_debug (params, "\tcontent: %s", (char*)xmlNodeGetContent(next));
852 traverse_tree (params, 3, xmlFirstElementChild(next));
853 } while ((next = xmlNextElementSibling (next)));
854 return PTP_RC_OK;
855 }
856
857 static int
858 parse_1015_tree (xmlNodePtr node, uint16_t type) {
859 PTPPropertyValue propval;
860 xmlNodePtr next;
861
862 next = xmlFirstElementChild (node);
863 return parse_value ((char*)xmlNodeGetContent (next), type, &propval);
864 }
865 #endif
866
867 static int
868 traverse_output_tree (PTPParams *params, xmlNodePtr node, PTPContainer *resp) {
869 xmlNodePtr next;
870 int cmd;
871
872 if (strcmp((char*)node->name,"output")) {
873 GP_LOG_E ("node is not output, but %s.", node->name);
874 return FALSE;
875 }
876 if (xmlChildElementCount(node) != 2) {
877 GP_LOG_E ("output: expected 2 children, got %ld.", xmlChildElementCount(node));
878 return FALSE;
879 }
880 next = xmlFirstElementChild (node);
881 if (!strcmp((char*)next->name,"result")) {
882 int result;
883 xmlChar *xchar;
884 xchar = xmlNodeGetContent (next);
885 if (!sscanf((char*)xchar,"%04x",&result))
886 GP_LOG_E ("failed scanning result from %s", xchar);
887 resp->Code = result;
888 GP_LOG_D ("ptp result is 0x%04x", result);
889
890 }
891 next = xmlNextElementSibling (next);
892 if (!sscanf ((char*)next->name, "c%04x", &cmd)) {
893 GP_LOG_E ("expected c<HEX>, have %s", next->name);
894 return FALSE;
895 }
896 GP_LOG_D ("cmd is 0x%04x", cmd);
897 switch (cmd) {
898 /* reviewed OK. */
899 case PTP_OC_OLYMPUS_Capture: return TRUE;
900 case PTP_OC_GetDevicePropDesc: return TRUE;
901
902 /* TODO */
903 #if 0
904 case PTP_OC_OLYMPUS_GetDeviceInfo: return parse_9301_tree (next); /* 9301 */
905 #endif
906 case PTP_OC_OLYMPUS_OpenSession: return parse_9302_tree (next);
907 case PTP_OC_OLYMPUS_GetCameraControlMode: return parse_910a_tree (next);
908 case PTP_OC_OLYMPUS_GetCameraID: return parse_9581_tree (next);
909
910 case PTP_OC_SetDevicePropValue: /* <output>\n<result>2001</result>\n<c1016>\n<pD135/>\n</c1016>\n</output> */
911 /* we could cross check the parameter, but its not strictly necessary */
912 return TRUE;
913 #if 0
914 case PTP_OC_GetDevicePropValue: return parse_1015_tree ( next , PTP_DTC_UINT32);
915 #endif
916 default:
917 return traverse_tree (params, 0, next);
918 }
919 return FALSE;
920 }
921
922 static int
923 traverse_input_tree (PTPParams *params, xmlNodePtr node, PTPContainer *resp) {
924 unsigned int curpar = 0;
925 int evt;
926 xmlNodePtr next = xmlFirstElementChild (node);
927 uint32_t pars[5];
928
929
930 if (!next) {
931 GP_LOG_E ("no nodes below input.");
932 return FALSE;
933 }
934
935 resp->Code = 0;
936 while (next) {
937 if (sscanf((char*)next->name,"e%x",&evt)) {
938 resp->Code = evt;
939
940 switch (evt) {
941 case PTP_EC_Olympus_PropertyChanged: {
942 xmlNodePtr propidnode = xmlFirstElementChild(next);
943
944 /* Gets a list of property that changed ... stuff into
945 * event queue. */
946 while (propidnode) {
947 int propid;
948
949 if (sscanf((char*)propidnode->name,"p%x", &propid)) {
950 PTPContainer ptp;
951
952 memset(&ptp, 0, sizeof(ptp));
953 ptp.Code = PTP_EC_DevicePropChanged;
954 ptp.Nparam = 1;
955 ptp.Param1 = propid;
956 ptp_add_event (params, &ptp);
957 }
958 propidnode = xmlNextElementSibling (propidnode);
959 }
960 break;
961 }
962 default:
963 if (xmlChildElementCount(node) != 0) {
964 GP_LOG_E ("event %s hat tree below?", (char*)next->name);
965 traverse_tree (params, 0, xmlFirstElementChild(next));
966 }
967 }
968 next = xmlNextElementSibling (next);
969 continue;
970 }
971 if (!strcmp((char*)next->name,"param")) {
972 int x;
973 if (sscanf((char*)xmlNodeGetContent(next),"%x", &x)) {
974 if (curpar < sizeof(pars)/sizeof(pars[0]))
975 pars[curpar++] = x;
976 else
977 GP_LOG_E ("ignore superfluous argument %s/%x", (char*)xmlNodeGetContent(next), x);
978 }
979 next = xmlNextElementSibling (next);
980 continue;
981 }
982 GP_LOG_E ("parsing event input node, unknown node %s", (char*)next->name);
983 next = xmlNextElementSibling (next);
984 }
985 resp->Nparam = curpar;
986 switch (curpar) {
987 case 5: resp->Param5 = pars[4]; /* fallthrough */
988 case 4: resp->Param4 = pars[3]; /* fallthrough */
989 case 3: resp->Param3 = pars[2]; /* fallthrough */
990 case 2: resp->Param2 = pars[1]; /* fallthrough */
991 case 1: resp->Param1 = pars[0]; /* fallthrough */
992 case 0: break;
993 }
994 /* FIXME: decode content and inject into PTP event queue. */
995 return TRUE;
996 }
997
998 static int
999 traverse_x3c_tree (PTPParams *params, xmlNodePtr node, PTPContainer *resp) {
1000 xmlNodePtr next;
1001
1002 if (!node)
1003 return FALSE;
1004 if (strcmp((char*)node->name,"x3c")) {
1005 GP_LOG_E ("node is not x3c, but %s.", node->name);
1006 return FALSE;
1007 }
1008 if (xmlChildElementCount(node) != 1) {
1009 GP_LOG_E ("x3c: expected 1 child, got %ld.", xmlChildElementCount(node));
1010 return FALSE;
1011 }
1012 next = xmlFirstElementChild (node);
1013 if (!strcmp((char*)next->name, "output"))
1014 return traverse_output_tree (params, next, resp);
1015 if (!strcmp((char*)next->name, "input"))
1016 return traverse_input_tree (params, next, resp); /* event */
1017 GP_LOG_E ("unknown name %s below x3c.", next->name);
1018 return FALSE;
1019 }
1020
1021 static int
1022 traverse_x3c_event_tree (PTPParams *params, xmlNodePtr node, PTPContainer *resp) {
1023 xmlNodePtr next;
1024
1025 if (!node)
1026 return FALSE;
1027 if (strcmp((char*)node->name,"x3c")) {
1028 GP_LOG_E ("node is not x3c, but %s.", node->name);
1029 return FALSE;
1030 }
1031 if (xmlChildElementCount(node) != 1) {
1032 GP_LOG_E ("x3c: expected 1 child, got %ld.", xmlChildElementCount(node));
1033 return FALSE;
1034 }
1035 next = xmlFirstElementChild (node);
1036 if (!strcmp((char*)next->name, "input"))
1037 return traverse_input_tree (params, next, resp); /* event */
1038 GP_LOG_E ("unknown name %s below x3c.", next->name);
1039 return FALSE;
1040 }
1041
1042 static int
1043 parse_xml(PTPParams *params, const char *txt, PTPContainer *resp) {
1044 xmlDocPtr docin;
1045 xmlNodePtr docroot;
1046
1047 docin = xmlReadMemory (txt, strlen(txt), "http://gphoto.org/", "utf-8", 0);
1048 if (!docin) return FALSE;
1049 docroot = xmlDocGetRootElement (docin);
1050 if (!docroot) return FALSE;
1051 return traverse_x3c_tree (params, docroot, resp);
1052 }
1053
1054 static int
1055 parse_event_xml(PTPParams *params, const char *txt, PTPContainer *resp) {
1056 xmlDocPtr docin;
1057 xmlNodePtr docroot;
1058
1059 docin = xmlReadMemory (txt, strlen(txt), "http://gphoto.org/", "utf-8", 0);
1060 if (!docin) return FALSE;
1061 docroot = xmlDocGetRootElement (docin);
1062 if (!docroot) return FALSE;
1063 return traverse_x3c_event_tree (params, docroot, resp);
1064 }
1065
1066 static void
1067 encode_command (xmlNodePtr inputnode, PTPContainer *ptp, unsigned char *data, int len)
1068 {
1069 xmlNodePtr cmdnode;
1070 char code[20];
1071
1072 sprintf(code,"c%04X", ptp->Code);
1073 cmdnode = xmlNewChild (inputnode, NULL, (xmlChar*)code, NULL);
1074
1075 switch (ptp->Code) {
1076 case 0x1014: { /* OK */
1077 sprintf (code, "p%04X", ptp->Param1);
1078 xmlNewChild (cmdnode, NULL, (xmlChar*)code, NULL);
1079 break;
1080 }
1081 case 0x1016: {
1082 char buf[20];
1083 xmlNodePtr pnode;
1084 /* zb <c1016><pD10D><value>000A000D</value></pD10D></c1016> */
1085 /* FIXME: might still be wrong. */
1086 /* We can directly byte encode the data we get from the PTP stack */
1087 /* ... BUT the byte order is bigendian (printed) vs encoded */
1088 int i;
1089 char *x = malloc (len*2+1);
1090
1091 if (len <= 4) { /* just dump the bytes in big endian byteorder */
1092 for (i=0;i<len;i++)
1093 sprintf(x+2*i,"%02X",data[len-i-1]);
1094 } else {
1095 for (i=0;i<len;i++)
1096 sprintf(x+2*i,"%02X",data[i]);
1097 }
1098 sprintf(buf,"p%04X", ptp->Param1);
1099 pnode = xmlNewChild (cmdnode, NULL, (xmlChar*)buf, NULL);
1100 xmlNewChild (pnode, NULL, (xmlChar*)"value", (xmlChar*)x);
1101 free (x);
1102 break;
1103 }
1104 default:
1105 if (ptp->Nparam) {
1106 switch (ptp->Nparam) {
1107 case 1:
1108 sprintf (code, "%08X", ptp->Param1);
1109 xmlNewChild (cmdnode, NULL, (xmlChar*)"param", (xmlChar*)code);
1110 break;
1111 case 2:
1112 sprintf (code, "%08X", ptp->Param1);
1113 xmlNewChild (cmdnode, NULL, (xmlChar*)"param", (xmlChar*)code);
1114 sprintf (code, "%08X", ptp->Param2);
1115 xmlNewChild (cmdnode, NULL, (xmlChar*)"param", (xmlChar*)code);
1116 break;
1117 }
1118 }
1119 break;
1120 }
1121 }
1122
1123 static char*
1124 generate_event_OK_xml(PTPParams *params, PTPContainer *ptp) {
1125 xmlDocPtr docout;
1126 xmlChar *output;
1127 int len;
1128 xmlNodePtr x3cnode, inputnode;
1129 char buf[10];
1130
1131 /*
1132 "HRSPONSE.X3C" ... sent back to camera after receiving an event.
1133 <output><result>2001</result><ec102/></output
1134 */
1135
1136 docout = xmlNewDoc ((xmlChar*)"1.0");
1137 x3cnode = xmlNewDocNode (docout, NULL, (xmlChar*)"x3c", NULL);
1138 xmlNewNs (x3cnode,(xmlChar*)"http://www1.olympus-imaging.com/ww/x3c",NULL);
1139 inputnode = xmlNewChild (x3cnode, NULL, (xmlChar*)"output", NULL);
1140
1141 sprintf (buf,"e%04X", ptp->Code);
1142
1143 xmlNewChild (inputnode, NULL, (xmlChar*)"result", (xmlChar*)"2001");
1144 xmlNewChild (inputnode, NULL, (xmlChar*)buf, NULL);
1145
1146 xmlDocSetRootElement (docout, x3cnode);
1147 xmlDocDumpMemory (docout, &output, &len);
1148
1149 GP_LOG_D ("generated xml is:");
1150 GP_LOG_D ("%s", output);
1151
1152 /* NOTE: Windows driver generates XML with CRLF, Unix just creates XML with LF.
1153 * Olympus E-410 does not seem to care. */
1154 return (char*)output;
1155 }
1156 static char*
1157 generate_xml(PTPParams *params, PTPContainer *ptp, unsigned char *data, int len) {
1158 xmlDocPtr docout;
1159 xmlChar *output;
1160 xmlNodePtr x3cnode;
1161 xmlNodePtr inputnode;
1162
1163 docout = xmlNewDoc ((xmlChar*)"1.0");
1164 x3cnode = xmlNewDocNode (docout, NULL, (xmlChar*)"x3c", NULL);
1165 xmlNewNs (x3cnode,(xmlChar*)"http://www1.olympus-imaging.com/ww/x3c",NULL);
1166 inputnode = xmlNewChild (x3cnode, NULL, (xmlChar*)"input", NULL);
1167
1168 /* The fun starts in here: */
1169 encode_command (inputnode, ptp, data, len);
1170
1171 xmlDocSetRootElement (docout, x3cnode);
1172 xmlDocDumpMemory (docout, &output, &len);
1173
1174 GP_LOG_D ("generated xml is:");
1175 GP_LOG_D ("%s", output);
1176
1177 /* NOTE: Windows driver generates XML with CRLF, Unix just creates XML with LF.
1178 * Olympus E-410 does not seem to care. */
1179 return (char*)output;
1180 }
1181
1182 static int
1183 is_outer_operation (PTPParams* params, uint16_t opcode) {
1184 unsigned int i;
1185
1186 GP_LOG_D ("is_outer_operation %04x", opcode);
1187 /* the ones we need before we can do getdeviceinfo */
1188 if (opcode == PTP_OC_OpenSession) return 1;
1189 if (opcode == PTP_OC_SendObjectInfo) return 1;
1190 if (opcode == PTP_OC_SendObject) return 1;
1191 if (opcode == PTP_OC_GetDeviceInfo) return 1;
1192 if (opcode == PTP_OC_GetStorageIDs) return 1;
1193
1194 /* all vendor ones are XML driven. */
1195 if ((opcode & 0x8000) == 0x8000) return 0;
1196
1197 /* Do nothing here, either do stuff in senddata, getdata or getresp,
1198 * which will get the PTPContainer req too. */
1199 for (i=0;i<params->outer_deviceinfo.OperationsSupported_len;i++)
1200 if (params->outer_deviceinfo.OperationsSupported[i]==opcode)
1201 return TRUE;
1202 GP_LOG_D ("is_outer_operation %04x - is WRAPPED", opcode);
1203 return FALSE;
1204 }
1205
1206 static uint16_t
1207 ums_wrap2_event_check (PTPParams* params, PTPContainer* req)
1208 {
1209 PTPContainer ptp2;
1210 int res;
1211 PTPObjectInfo oi;
1212 unsigned char *resxml, *oidata = NULL;
1213 uint32_t size, newhandle;
1214 uint16_t ret;
1215 PTPParams *outerparams = params->outer_params;
1216 char *evxml;
1217
1218 GP_LOG_D ("ums_wrap2_event_check");
1219
1220 while (1) {
1221 ret = outerparams->event_check(outerparams, &ptp2);
1222 if (ret != PTP_RC_OK)
1223 return ret;
1224
1225 GP_LOG_D ("event: code %04x, p %08x", ptp2.Code, ptp2.Param1);
1226
1227 if (ptp2.Code != PTP_EC_RequestObjectTransfer) {
1228 GP_LOG_D ("event 0x%04x received, just passing on", ptp2.Code);
1229 memcpy (req, &ptp2, sizeof(ptp2));
1230 return PTP_RC_OK;
1231 }
1232
1233 newhandle = ptp2.Param1;
1234
1235 if ((newhandle & 0xff000000) != 0x1e000000) {
1236 GP_LOG_D ("event 0x%04x, handle 0x%08x received, no XML event, just passing on", ptp2.Code, ptp2.Param1);
1237 ptp_add_event (params, &ptp2);
1238 continue;
1239 }
1240
1241 ret = ptp_getobjectinfo (outerparams, newhandle, &oi);
1242 if (ret != PTP_RC_OK)
1243 return ret;
1244 GP_LOG_D ("event xml: got new file: %s", oi.Filename);
1245 if (!strstr(oi.Filename,".X3C")) {
1246 GP_LOG_D ("PTP_EC_RequestObjectTransfer with non XML filename %s", oi.Filename);
1247 memcpy (req, &ptp2, sizeof(ptp2));
1248 return PTP_RC_OK;
1249 }
1250 ret = ptp_getobject (outerparams, newhandle, (unsigned char**)&resxml);
1251 if (ret != PTP_RC_OK)
1252 return ret;
1253 evxml = malloc (oi.ObjectCompressedSize + 1);
1254 memcpy (evxml, resxml, oi.ObjectCompressedSize);
1255 evxml[oi.ObjectCompressedSize] = 0x00;
1256
1257 GP_LOG_D ("file content: %s", evxml);
1258
1259 /* FIXME: handle the case where we get a non X3C file, like during capture */
1260
1261 /* parse it ... into req */
1262 parse_event_xml (params, evxml, req);
1263
1264 /* generate reply */
1265 evxml = generate_event_OK_xml(params, req);
1266
1267 GP_LOG_D ("... sending XML event reply to camera ... ");
1268 memset (&ptp2, 0 , sizeof (ptp2));
1269 ptp2.Code = PTP_OC_SendObjectInfo;
1270 ptp2.Nparam = 1;
1271 ptp2.Param1 = 0x80000001;
1272
1273 memset (&oi, 0, sizeof (oi));
1274 oi.ObjectFormat = PTP_OFC_Script;
1275 oi.StorageID = 0x80000001;
1276 oi.Filename = "HRSPONSE.X3C";
1277 oi.ObjectCompressedSize = strlen(evxml);
1278 size = ptp_pack_OI(params, &oi, &oidata);
1279 res = ptp_transaction (outerparams, &ptp2, PTP_DP_SENDDATA, size, &oidata, NULL);
1280 if (res != PTP_RC_OK)
1281 return res;
1282 free(oidata);
1283 /*handle = ptp2.Param3; ... we do not use the returned handle and leave the file on camera. */
1284
1285 ptp2.Code = PTP_OC_SendObject;
1286 ptp2.Nparam = 0;
1287 res = ptp_transaction(outerparams, &ptp2, PTP_DP_SENDDATA, strlen(evxml), (unsigned char**)&evxml, NULL);
1288 if (res != PTP_RC_OK)
1289 return res;
1290 return PTP_RC_OK;
1291 }
1292 }
1293
1294 static uint16_t
1295 ums_wrap2_sendreq (PTPParams* params, PTPContainer* req, int dataphase)
1296 {
1297 GP_LOG_D ("ums_wrap2_sendreq");
1298 if (is_outer_operation (params,req->Code))
1299 return ums_wrap_sendreq (params,req,dataphase);
1300 /* We do stuff in either senddata, getdata or getresp, not here. */
1301 params->olympus_cmd = NULL;
1302 params->olympus_reply = NULL;
1303 return PTP_RC_OK;
1304 }
1305
1306 static uint16_t
1307 ums_wrap2_senddata (
1308 PTPParams* params, PTPContainer* ptp, uint64_t sendlen, PTPDataHandler*getter
1309 ) {
1310 unsigned char *data;
1311 uint16_t ret;
1312 unsigned long gotlen;
1313
1314 if (is_outer_operation (params, ptp->Code))
1315 return ums_wrap_senddata (params, ptp, sendlen, getter);
1316
1317 GP_LOG_D ("ums_wrap2_senddata");
1318 data = malloc (sendlen);
1319 ret = getter->getfunc(params, getter->priv, sendlen, data, &gotlen);
1320 if (ret != PTP_RC_OK) {
1321 GP_LOG_D ("ums_wrap2_senddata *** data get from handler FAILED, ret %d", ret);
1322 return ret;
1323 }
1324 params->olympus_cmd = generate_xml (params, ptp, data, sendlen);
1325 free (data);
1326 /* Do not do stuff yet, do it in getresp */
1327 return PTP_RC_OK;
1328 }
1329
1330 static uint16_t
1331 ums_wrap2_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *putter) {
1332 char *resxml = NULL;
1333 uint16_t ret;
1334
1335 if (is_outer_operation (params, ptp->Code))
1336 return ums_wrap_getdata (params, ptp, putter);
1337
1338 GP_LOG_D ("ums_wrap2_getdata");
1339
1340 /* Either send or get data, not both. olympus_cmd is NULL now */
1341 params->olympus_cmd = generate_xml (params, ptp, NULL, 0);
1342
1343 /* Do the fun stuff. */
1344 ret = olympus_xml_transfer (params, params->olympus_cmd, &resxml);
1345 if (ret != PTP_RC_OK)
1346 return ret;
1347
1348 /* Remember the returned XML for getresp() for the PTP return code. */
1349 params->olympus_reply = resxml;
1350 switch (ptp->Code) {
1351 #if 0
1352 case PTP_OC_GetDevicePropDesc: {
1353 PTPPropertyDesc dpd;
1354 parse_9301_propdesc (xmlFirstElementChild (next), &dpd);
1355 /* decode the XML ... reencode the binary presentation of the propdesc */
1356 break;
1357 }
1358 #endif
1359 default:
1360 /* Just put the XML blob as-is as data... It will be processed in ptp.c */
1361 return putter->putfunc(params,putter->priv,strlen(resxml)+1,(unsigned char*)resxml);
1362 }
1363 }
1364
1365 static uint16_t
1366 ums_wrap2_getresp (PTPParams* params, PTPContainer* resp) {
1367 int ret;
1368
1369 if (is_outer_operation(params, resp->Code))
1370 return ums_wrap_getresp (params, resp);
1371
1372 GP_LOG_D ("ums_wrap2_getresp");
1373 if (!params->olympus_cmd) /* no data phase at all */
1374 params->olympus_cmd = generate_xml (params, resp, NULL, 0);
1375 if (!params->olympus_reply) {
1376 /* Do the actual handshake here. */
1377 ret = olympus_xml_transfer (params, params->olympus_cmd, ¶ms->olympus_reply);
1378 if (ret != PTP_RC_OK) {
1379 GP_LOG_E ("ums_wrap2_getresp: error %x from transfer", ret);
1380 return ret;
1381 }
1382 }
1383 parse_xml (params, params->olympus_reply, resp);
1384 return PTP_RC_OK;
1385 }
1386
1387 uint16_t
1388 olympus_setup (PTPParams *params) {
1389 PTPParams *outerparams;
1390
1391 params->getresp_func = ums_wrap2_getresp;
1392 params->senddata_func = ums_wrap2_senddata;
1393 params->getdata_func = ums_wrap2_getdata;
1394 params->sendreq_func = ums_wrap2_sendreq;
1395
1396 params->event_check = ums_wrap2_event_check;
1397 params->event_wait = ums_wrap2_event_check;
1398
1399 params->outer_params = outerparams = malloc (sizeof(PTPParams));
1400 memcpy(outerparams, params, sizeof(PTPParams));
1401 outerparams->sendreq_func = ums_wrap_sendreq;
1402 outerparams->getresp_func = ums_wrap_getresp;
1403 outerparams->senddata_func = ums_wrap_senddata;
1404 outerparams->getdata_func = ums_wrap_getdata;
1405 outerparams->getdata_func = ums_wrap_getdata;
1406
1407 /* events come just as PTP events */
1408 outerparams->event_check = ptp_usb_event_check;
1409 outerparams->event_wait = ptp_usb_event_wait;
1410
1411 return PTP_RC_OK;
1412 }
1413 #endif /* HAVE_LIBXML2 */