blob: b1e00d6ede22986291d58a894bae7cd69cf37df6 [file] [log] [blame]
Linus Walleijeb8c6fe2006-02-03 09:46:22 +00001/* ptp.c
2 *
3 * Copyright (C) 2001-2005 Mariusz Woloszyn <emsi@ipartners.pl>
4 *
5 * This file is part of libptp2.
6 *
7 * libptp2 is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * libptp2 is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with libptp2; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <config.h>
23#include "ptp.h"
24#include "ptp-pack.h"
25
26#include <stdlib.h>
27#include <stdarg.h>
28#include <stdio.h>
29#include <string.h>
30
31#ifdef ENABLE_NLS
32# include <libintl.h>
33# undef _
34# define _(String) dgettext (PACKAGE, String)
35# ifdef gettext_noop
36# define N_(String) gettext_noop (String)
37# else
38# define N_(String) (String)
39# endif
40#else
41# define textdomain(String) (String)
42# define gettext(String) (String)
43# define dgettext(Domain,Message) (Message)
44# define dcgettext(Domain,Message,Type) (Message)
45# define bindtextdomain(Domain,Directory) (Domain)
46# define _(String) (String)
47# define N_(String) (String)
48#endif
49
50/* global callback function */
51Progress_Callback* globalCallback;
52
53static void
54ptp_debug (PTPParams *params, const char *format, ...)
55{
56 va_list args;
57
58 va_start (args, format);
59 if (params->debug_func!=NULL)
60 params->debug_func (params->data, format, args);
61 else
62 {
63 vfprintf (stderr, format, args);
64 fprintf (stderr,"\n");
65 fflush (stderr);
66 }
67 va_end (args);
68}
69
70static void
71ptp_error (PTPParams *params, const char *format, ...)
72{
73 va_list args;
74
75 va_start (args, format);
76 if (params->error_func!=NULL)
77 params->error_func (params->data, format, args);
78 else
79 {
80 vfprintf (stderr, format, args);
81 fprintf (stderr,"\n");
82 fflush (stderr);
83 }
84 va_end (args);
85}
86
87/* send / receive functions */
88
89uint16_t
90ptp_usb_sendreq (PTPParams* params, PTPContainer* req)
91{
92 uint16_t ret;
93 PTPUSBBulkContainer usbreq;
94
95 /* build appropriate USB container */
96 usbreq.length=htod32(PTP_USB_BULK_REQ_LEN-
97 (sizeof(uint32_t)*(5-req->Nparam)));
98 usbreq.type=htod16(PTP_USB_CONTAINER_COMMAND);
99 usbreq.code=htod16(req->Code);
100 usbreq.trans_id=htod32(req->Transaction_ID);
101 usbreq.payload.params.param1=htod32(req->Param1);
102 usbreq.payload.params.param2=htod32(req->Param2);
103 usbreq.payload.params.param3=htod32(req->Param3);
104 usbreq.payload.params.param4=htod32(req->Param4);
105 usbreq.payload.params.param5=htod32(req->Param5);
106 /* send it to responder */
107 ret=params->write_func((unsigned char *)&usbreq,
108 PTP_USB_BULK_REQ_LEN-(sizeof(uint32_t)*(5-req->Nparam)),
109 params->data);
110 if (ret!=PTP_RC_OK) {
111 ret = PTP_ERROR_IO;
112/* ptp_error (params,
113 "PTP: request code 0x%04x sending req error 0x%04x",
114 req->Code,ret); */
115 }
116 return ret;
117}
118
119/*
120 Modified for MTP support by RAL 2005-12-21
121
122 This is much changed from the original libptp ptp_usb_senddata.
123
124 Observations from sniffing WMP10 and some testing:
125
126 Data is sent in blocks of 0xe000 (BLOCK_SIZE). If the filesize
127 is 0 mod 0x200 (MTP_DEVICE_BUF_SIZE), we must make a USB write of
128 zero bytes. I assume this is because the buffer size on the device
129 is 0x200 bytes and end of transfer is signalled by getting an unfull
130 buffer or a transfer of zero bytes. Not obvious why this is required,
131 but it does work.
132 */
133
134uint16_t
135ptp_usb_senddata (PTPParams* params, PTPContainer* ptp,
136 unsigned char *data, unsigned int size)
137{
138 uint16_t ret;
139 PTPUSBBulkContainerSend usbdata;
140 unsigned int remain = size;
141 int done = 0;
142
143 /* build appropriate USB container */
144 usbdata.length=htod32(sizeof(usbdata)+size);
145 usbdata.type=htod16(PTP_USB_CONTAINER_DATA);
146 usbdata.code=htod16(ptp->Code);
147 usbdata.trans_id=htod32(ptp->Transaction_ID);
148
149 /* only print if size < something */
150 /*
151 if (size < BLOCK_SIZE)
152 {
153 printf("-------------------------\n");
154 printf("Sending usbdata size %d\n", sizeof(usbdata));
155 for (i = 0; i < sizeof(usbdata); i += 8)
156 {
157 int j = i;
158 for (; j<sizeof(usbdata) && j<i+8; j++)
159 printf("0x%02x ", ((unsigned char *)&usbdata)[j]);
160 printf("\n");
161 }
162 printf("Sending data size %d\n", size);
163 for (i = 0; i < size; i += 8)
164 {
165 int j = i;
166 for (; j<size && j<i+8; j++)
167 printf("0x%02x ", data[j]);
168 printf("\n");
169 }
170 printf("-------------------------\n");
171 }
172 */
173 ret=params->write_func((unsigned char *)&usbdata, sizeof(usbdata), params->data);
174 if (ret!=PTP_RC_OK) {
175 ret = PTP_ERROR_IO;
176 return ret;
177 }
178
179 extern Progress_Callback* globalCallback;
180
181 while (done == 0)
182 {
183 int bytesdone = size-remain;
184 int bytestosend = remain>BLOCK_SIZE?BLOCK_SIZE:remain;
185 if (globalCallback != NULL)
186 {
187 if (bytesdone % CALLBACK_SIZE == 0)
188 globalCallback(bytesdone, size);
189 }
190 ret=params->write_func(data, bytestosend, params->data);
191 if (ret!=PTP_RC_OK) {
192 ret = PTP_ERROR_IO;
193 return ret;
194 }
195 if (remain <= BLOCK_SIZE)
196 done = 1;
197 else
198 {
199 remain -= bytestosend;
200 data+=bytestosend;
201 }
202 }
203
204 if (done != 0 && globalCallback != NULL)
205 globalCallback(size, size);
206
207 /* write zero to end for some reason... but only sometimes!! */
208 if (done != 0 && size % MTP_DEVICE_BUF_SIZE == 0)
209 {
210 ret=params->write_func(data, 0, params->data);
211 }
212
213 if (ret!=PTP_RC_OK)
214 ret = PTP_ERROR_IO;
215 return ret;
216}
217
218/*
219 Modified for MTP support by RAL 2005-12-21
220
221 This is changed from the original libptp ptp_usb_getdata.
222
223 It appears as though the MTP devices don't use the usb payload-
224 which is set to all zeroes. So just ignore the zeroes and start
225 after the payload.
226 */
227
228uint16_t
229ptp_usb_getdata (PTPParams* params, PTPContainer* ptp,
230 unsigned char **data)
231{
232 uint16_t ret;
233 PTPUSBBulkContainer usbdata;
234 uint32_t read = 0;
235 uint32_t bytesToRead = CALLBACK_SIZE;
236 extern Progress_Callback* globalCallback;
237
238 PTP_CNT_INIT(usbdata);
239#if 0
240 if (*data!=NULL) return PTP_ERROR_BADPARAM;
241#endif
242 uint32_t len;
243 /* read first(?) part of data */
244 ret=params->read_func((unsigned char *)&usbdata,
245 sizeof(usbdata), params->data);
246
247/* {
248 int i = 0;
249
250 printf("-------------------------\n");
251 printf("got data size %d\n", sizeof(usbdata));
252 for (i = 0; i < sizeof(usbdata); i += 8)
253 {
254 int j = i;
255 for (; j<sizeof(usbdata) && j<i+8; j++)
256 printf("0x%02x ", ((unsigned char *)&usbdata)[j]);
257 printf("\n");
258 }
259 printf("-------------------------\n");
260 }
261*/
262
263 if (ret!=PTP_RC_OK) {
264 ret = PTP_ERROR_IO;
265 } else
266 if (dtoh16(usbdata.type)!=PTP_USB_CONTAINER_DATA) {
267 ret = PTP_ERROR_DATA_EXPECTED;
268 } else
269 if (dtoh16(usbdata.code)!=ptp->Code) {
270 ret = dtoh16(usbdata.code);
271 } else {
272 /* evaluate data length */
273 len=dtoh32(usbdata.length)-PTP_USB_BULK_HDR_LEN;
274 /* test by RAL: some data coming back has this length - how do we deal with it? */
275 if (dtoh32(usbdata.length) == 0xffffffff)
276 len = 0x1fffff;
277 /* allocate memory for data if not allocated already */
278 if (*data==NULL) *data=calloc(len,1);
279
280 if (globalCallback == NULL)
281 ret=params->read_func(((unsigned char *)(*data)), len, params->data);
282 else
283 {
284 while (read < len)
285 {
286 bytesToRead=(len-read > CALLBACK_SIZE)?CALLBACK_SIZE:len-read;
287 ret=params->read_func(&(((unsigned char *)(*data))[read]), bytesToRead, params->data);
288 if (ret!=PTP_RC_OK)
289 break;
290 read+=bytesToRead;
291 globalCallback(read, len);
292 }
293 }
294 if (ret!=PTP_RC_OK) {
295 ret = PTP_ERROR_IO;
296 }
297 }
298 return ret;
299}
300
301uint16_t
302ptp_usb_getresp (PTPParams* params, PTPContainer* resp)
303{
304 uint16_t ret;
305 PTPUSBBulkContainer usbresp;
306
307 PTP_CNT_INIT(usbresp);
308 /* read response, it should never be longer than sizeof(usbresp) */
309 ret=params->read_func((unsigned char *)&usbresp,
310 sizeof(usbresp), params->data);
311
312 if (ret!=PTP_RC_OK) {
313 ret = PTP_ERROR_IO;
314 } else
315 if (dtoh16(usbresp.type)!=PTP_USB_CONTAINER_RESPONSE) {
316 ret = PTP_ERROR_RESP_EXPECTED;
317 } else
318 if (dtoh16(usbresp.code)!=resp->Code) {
319 ret = dtoh16(usbresp.code);
320 }
321 if (ret!=PTP_RC_OK) {
322/* ptp_error (params,
323 "PTP: request code 0x%04x getting resp error 0x%04x",
324 resp->Code, ret);*/
325 return ret;
326 }
327 /* build an appropriate PTPContainer */
328 resp->Code=dtoh16(usbresp.code);
329 resp->SessionID=params->session_id;
330 resp->Transaction_ID=dtoh32(usbresp.trans_id);
331 resp->Param1=dtoh32(usbresp.payload.params.param1);
332 resp->Param2=dtoh32(usbresp.payload.params.param2);
333 resp->Param3=dtoh32(usbresp.payload.params.param3);
334 resp->Param4=dtoh32(usbresp.payload.params.param4);
335 resp->Param5=dtoh32(usbresp.payload.params.param5);
336
337 return ret;
338}
339
340/* major PTP functions */
341
342/**
343 * ptp_transaction:
344 * params: PTPParams*
345 * PTPContainer* ptp - general ptp container
346 * uint16_t flags - lower 8 bits - data phase description
347 * unsigned int sendlen - senddata phase data length
348 * char** data - send or receive data buffer pointer
349 *
350 * Performs PTP transaction. ptp is a PTPContainer with appropriate fields
351 * filled in (i.e. operation code and parameters). It's up to caller to do
352 * so.
353 * The flags decide thether the transaction has a data phase and what is its
354 * direction (send or receive).
355 * If transaction is sending data the sendlen should contain its length in
356 * bytes, otherwise it's ignored.
357 * The data should contain an address of a pointer to data going to be sent
358 * or is filled with such a pointer address if data are received depending
359 * od dataphase direction (send or received) or is beeing ignored (no
360 * dataphase).
361 * The memory for a pointer should be preserved by the caller, if data are
362 * beeing retreived the appropriate amount of memory is beeing allocated
363 * (the caller should handle that!).
364 *
365 * Return values: Some PTP_RC_* code.
366 * Upon success PTPContainer* ptp contains PTP Response Phase container with
367 * all fields filled in.
368 **/
369uint16_t
370ptp_transaction (PTPParams* params, PTPContainer* ptp,
371 uint16_t flags, unsigned int sendlen, char** data)
372{
373 if ((params==NULL) || (ptp==NULL))
374 return PTP_ERROR_BADPARAM;
375
376 ptp->Transaction_ID=params->transaction_id++;
377 ptp->SessionID=params->session_id;
378 /* send request */
379 CHECK_PTP_RC(params->sendreq_func (params, ptp));
380 /* is there a dataphase? */
381 switch (flags&PTP_DP_DATA_MASK) {
382 case PTP_DP_SENDDATA:
383 CHECK_PTP_RC(params->senddata_func(params, ptp,
384 *data, sendlen));
385 break;
386 case PTP_DP_GETDATA:
387 CHECK_PTP_RC(params->getdata_func(params, ptp,
388 (unsigned char**)data));
389 break;
390 case PTP_DP_NODATA:
391 break;
392 default:
393 return PTP_ERROR_BADPARAM;
394 }
395 /* get response */
396 CHECK_PTP_RC(params->getresp_func(params, ptp));
397 return PTP_RC_OK;
398}
399
400/* Enets handling functions */
401
402/* PTP Events wait for or check mode */
403#define PTP_EVENT_CHECK 0x0000 /* waits for */
404#define PTP_EVENT_CHECK_FAST 0x0001 /* checks */
405
406static inline uint16_t
407ptp_usb_event (PTPParams* params, PTPContainer* event, int wait)
408{
409 uint16_t ret;
410 PTPUSBEventContainer usbevent;
411 PTP_CNT_INIT(usbevent);
412
413 if ((params==NULL) || (event==NULL))
414 return PTP_ERROR_BADPARAM;
415
416 switch(wait) {
417 case PTP_EVENT_CHECK:
418 ret=params->check_int_func((unsigned char*)&usbevent,
419 sizeof(usbevent), params->data);
420 break;
421 case PTP_EVENT_CHECK_FAST:
422 ret=params->check_int_fast_func((unsigned char*)
423 &usbevent, sizeof(usbevent), params->data);
424 break;
425 default:
426 ret=PTP_ERROR_BADPARAM;
427 }
428 if (ret!=PTP_RC_OK) {
429 ret = PTP_ERROR_IO;
430 ptp_error (params,
431 "PTP: reading event an error 0x%04x occured", ret);
432 /* reading event error is nonfatal (for example timeout) */
433 return ret;
434 }
435 /* if we read anything over interrupt endpoint it must be an event */
436 /* build an appropriate PTPContainer */
437 event->Code=dtoh16(usbevent.code);
438 event->SessionID=params->session_id;
439 event->Transaction_ID=dtoh32(usbevent.trans_id);
440 event->Param1=dtoh32(usbevent.param1);
441 event->Param2=dtoh32(usbevent.param2);
442 event->Param3=dtoh32(usbevent.param3);
443
444 return PTP_RC_OK;
445}
446
447uint16_t
448ptp_usb_event_check (PTPParams* params, PTPContainer* event) {
449
450 return ptp_usb_event (params, event, PTP_EVENT_CHECK_FAST);
451}
452
453uint16_t
454ptp_usb_event_wait (PTPParams* params, PTPContainer* event) {
455
456 return ptp_usb_event (params, event, PTP_EVENT_CHECK);
457}
458
459/**
460 * PTP operation functions
461 *
462 * all ptp_ functions should take integer parameters
463 * in host byte order!
464 **/
465
466
467/**
468 * ptp_getdeviceinfo:
469 * params: PTPParams*
470 *
471 * Gets device info dataset and fills deviceinfo structure.
472 *
473 * Return values: Some PTP_RC_* code.
474 **/
475uint16_t
476ptp_getdeviceinfo (PTPParams* params, PTPDeviceInfo* deviceinfo)
477{
478 uint16_t ret;
479 PTPContainer ptp;
480 char* di=NULL;
481
482 PTP_CNT_INIT(ptp);
483 ptp.Code=PTP_OC_GetDeviceInfo;
484 ptp.Nparam=0;
485 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &di);
486 if (ret == PTP_RC_OK) ptp_unpack_DI(params, di, deviceinfo);
487 free(di);
488 return ret;
489}
490
491
492/**
493 * ptp_opensession:
494 * params: PTPParams*
495 * session - session number
496 *
497 * Establishes a new session.
498 *
499 * Return values: Some PTP_RC_* code.
500 **/
501uint16_t
502ptp_opensession (PTPParams* params, uint32_t session)
503{
504 uint16_t ret;
505 PTPContainer ptp;
506
507 ptp_debug(params,"PTP: Opening session");
508
509 /* SessonID field of the operation dataset should always
510 be set to 0 for OpenSession request! */
511 params->session_id=0x00000000;
512 /* TransactionID should be set to 0 also! */
513 params->transaction_id=0x0000000;
514
515 PTP_CNT_INIT(ptp);
516 ptp.Code=PTP_OC_OpenSession;
517 ptp.Param1=session;
518 ptp.Nparam=1;
519 ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
520 /* now set the global session id to current session number */
521 params->session_id=session;
522 return ret;
523}
524
525/**
526 * ptp_closesession:
527 * params: PTPParams*
528 *
529 * Closes session.
530 *
531 * Return values: Some PTP_RC_* code.
532 **/
533uint16_t
534ptp_closesession (PTPParams* params)
535{
536 PTPContainer ptp;
537
538 ptp_debug(params,"PTP: Closing session");
539
540 PTP_CNT_INIT(ptp);
541 ptp.Code=PTP_OC_CloseSession;
542 ptp.Nparam=0;
543 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
544}
545
546/**
547 * ptp_getststorageids:
548 * params: PTPParams*
549 *
550 * Gets array of StorageiDs and fills the storageids structure.
551 *
552 * Return values: Some PTP_RC_* code.
553 **/
554uint16_t
555ptp_getstorageids (PTPParams* params, PTPStorageIDs* storageids)
556{
557 uint16_t ret;
558 PTPContainer ptp;
559 char* sids=NULL;
560
561 PTP_CNT_INIT(ptp);
562 ptp.Code=PTP_OC_GetStorageIDs;
563 ptp.Nparam=0;
564 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &sids);
565 if (ret == PTP_RC_OK) ptp_unpack_SIDs(params, sids, storageids);
566 free(sids);
567 return ret;
568}
569
570/**
571 * ptp_getststorageinfo:
572 * params: PTPParams*
573 * storageid - StorageID
574 *
575 * Gets StorageInfo dataset of desired storage and fills storageinfo
576 * structure.
577 *
578 * Return values: Some PTP_RC_* code.
579 **/
580uint16_t
581ptp_getstorageinfo (PTPParams* params, uint32_t storageid,
582 PTPStorageInfo* storageinfo)
583{
584 uint16_t ret;
585 PTPContainer ptp;
586 char* si=NULL;
587
588 PTP_CNT_INIT(ptp);
589 ptp.Code=PTP_OC_GetStorageInfo;
590 ptp.Param1=storageid;
591 ptp.Nparam=1;
592 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &si);
593 if (ret == PTP_RC_OK) ptp_unpack_SI(params, si, storageinfo);
594 free(si);
595 return ret;
596}
597
598/**
599 * ptp_getobjecthandles:
600 * params: PTPParams*
601 * storage - StorageID
602 * objectformatcode - ObjectFormatCode (optional)
603 * associationOH - ObjectHandle of Association for
604 * wich a list of children is desired
605 * (optional)
606 * objecthandles - pointer to structute
607 *
608 * Fills objecthandles with structure returned by device.
609 *
610 * Return values: Some PTP_RC_* code.
611 **/
612uint16_t
613ptp_getobjecthandles (PTPParams* params, uint32_t storage,
614 uint32_t objectformatcode, uint32_t associationOH,
615 PTPObjectHandles* objecthandles)
616{
617 uint16_t ret;
618 PTPContainer ptp;
619 char* oh=NULL;
620
621 PTP_CNT_INIT(ptp);
622 ptp.Code=PTP_OC_GetObjectHandles;
623 ptp.Param1=storage;
624 ptp.Param2=objectformatcode;
625 ptp.Param3=associationOH;
626 ptp.Nparam=3;
627 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oh);
628 if (ret == PTP_RC_OK) ptp_unpack_OH(params, oh, objecthandles);
629 free(oh);
630 return ret;
631}
632
633uint16_t
634ptp_getobjectinfo (PTPParams* params, uint32_t handle,
635 PTPObjectInfo* objectinfo)
636{
637 uint16_t ret;
638 PTPContainer ptp;
639 char* oi=NULL;
640
641 PTP_CNT_INIT(ptp);
642 ptp.Code=PTP_OC_GetObjectInfo;
643 ptp.Param1=handle;
644 ptp.Nparam=1;
645 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &oi);
646 if (ret == PTP_RC_OK) ptp_unpack_OI(params, oi, objectinfo);
647 free(oi);
648 return ret;
649}
650
651uint16_t
652ptp_getobject (PTPParams* params, uint32_t handle, char** object)
653{
654 PTPContainer ptp;
655
656 PTP_CNT_INIT(ptp);
657 ptp.Code=PTP_OC_GetObject;
658 ptp.Param1=handle;
659 ptp.Nparam=1;
660 return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object);
661}
662
663uint16_t
664ptp_getthumb (PTPParams* params, uint32_t handle, char** object)
665{
666 PTPContainer ptp;
667
668 PTP_CNT_INIT(ptp);
669 ptp.Code=PTP_OC_GetThumb;
670 ptp.Param1=handle;
671 ptp.Nparam=1;
672 return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, object);
673}
674
675/**
676 * ptp_deleteobject:
677 * params: PTPParams*
678 * handle - object handle
679 * ofc - object format code (optional)
680 *
681 * Deletes desired objects.
682 *
683 * Return values: Some PTP_RC_* code.
684 **/
685uint16_t
686ptp_deleteobject (PTPParams* params, uint32_t handle,
687 uint32_t ofc)
688{
689 PTPContainer ptp;
690
691 PTP_CNT_INIT(ptp);
692 ptp.Code=PTP_OC_DeleteObject;
693 ptp.Param1=handle;
694 ptp.Param2=ofc;
695 ptp.Nparam=2;
696 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
697}
698
699/**
700 * ptp_sendobjectinfo:
701 * params: PTPParams*
702 * uint32_t* store - destination StorageID on Responder
703 * uint32_t* parenthandle - Parent ObjectHandle on responder
704 * uint32_t* handle - see Return values
705 * PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
706 *
707 * Sends ObjectInfo of file that is to be sent via SendFileObject.
708 *
709 * Return values: Some PTP_RC_* code.
710 * Upon success : uint32_t* store - Responder StorageID in which
711 * object will be stored
712 * uint32_t* parenthandle- Responder Parent ObjectHandle
713 * in which the object will be stored
714 * uint32_t* handle - Responder's reserved ObjectHandle
715 * for the incoming object
716 **/
717uint16_t
718ptp_sendobjectinfo (PTPParams* params, uint32_t* store,
719 uint32_t* parenthandle, uint32_t* handle,
720 PTPObjectInfo* objectinfo)
721{
722 uint16_t ret;
723 PTPContainer ptp;
724 char* oidata=NULL;
725 uint32_t size;
726
727 PTP_CNT_INIT(ptp);
728 ptp.Code=PTP_OC_SendObjectInfo;
729 ptp.Param1=*store;
730 ptp.Param2=*parenthandle;
731 ptp.Nparam=2;
732
733 size=ptp_pack_OI(params, objectinfo, &oidata);
734 ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata);
735 free(oidata);
736 *store=ptp.Param1;
737 *parenthandle=ptp.Param2;
738 *handle=ptp.Param3;
739 return ret;
740}
741
742/**
743 * ptp_sendobject:
744 * params: PTPParams*
745 * char* object - contains the object that is to be sent
746 * uint32_t size - object size
747 *
748 * Sends object to Responder.
749 *
750 * Return values: Some PTP_RC_* code.
751 *
752 */
753uint16_t
754ptp_sendobject (PTPParams* params, char* object, uint32_t size)
755{
756 PTPContainer ptp;
757
758 PTP_CNT_INIT(ptp);
759 ptp.Code=PTP_OC_SendObject;
760 ptp.Nparam=0;
761
762 return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object);
763}
764
765
766/**
767 * ptp_initiatecapture:
768 * params: PTPParams*
769 * storageid - destination StorageID on Responder
770 * ofc - object format code
771 *
772 * Causes device to initiate the capture of one or more new data objects
773 * according to its current device properties, storing the data into store
774 * indicated by storageid. If storageid is 0x00000000, the object(s) will
775 * be stored in a store that is determined by the capturing device.
776 * The capturing of new data objects is an asynchronous operation.
777 *
778 * Return values: Some PTP_RC_* code.
779 **/
780
781uint16_t
782ptp_initiatecapture (PTPParams* params, uint32_t storageid,
783 uint32_t ofc)
784{
785 PTPContainer ptp;
786
787 PTP_CNT_INIT(ptp);
788 ptp.Code=PTP_OC_InitiateCapture;
789 ptp.Param1=storageid;
790 ptp.Param2=ofc;
791 ptp.Nparam=2;
792 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
793}
794
795uint16_t
796ptp_getdevicepropdesc (PTPParams* params, uint16_t propcode,
797 PTPDevicePropDesc* devicepropertydesc)
798{
799 PTPContainer ptp;
800 uint16_t ret;
801 char* dpd=NULL;
802
803 PTP_CNT_INIT(ptp);
804 ptp.Code=PTP_OC_GetDevicePropDesc;
805 ptp.Param1=propcode;
806 ptp.Nparam=1;
807 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpd);
808 if (ret == PTP_RC_OK) ptp_unpack_DPD(params, dpd, devicepropertydesc);
809 free(dpd);
810 return ret;
811}
812
813uint16_t
814ptp_getdevicepropvalue (PTPParams* params, uint16_t propcode,
815 void** value, uint16_t datatype)
816{
817 PTPContainer ptp;
818 uint16_t ret;
819 char* dpv=NULL;
820
821
822 PTP_CNT_INIT(ptp);
823 ptp.Code=PTP_OC_GetDevicePropValue;
824 ptp.Param1=propcode;
825 ptp.Nparam=1;
826 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &dpv);
827 if (ret == PTP_RC_OK) ptp_unpack_DPV(params, dpv, value, datatype);
828 free(dpv);
829 return ret;
830}
831
832uint16_t
833ptp_setdevicepropvalue (PTPParams* params, uint16_t propcode,
834 void* value, uint16_t datatype)
835{
836 PTPContainer ptp;
837 uint16_t ret;
838 uint32_t size;
839 char* dpv=NULL;
840
841 PTP_CNT_INIT(ptp);
842 ptp.Code=PTP_OC_SetDevicePropValue;
843 ptp.Param1=propcode;
844 ptp.Nparam=1;
845 size=ptp_pack_DPV(params, value, &dpv, datatype);
846 ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &dpv);
847 free(dpv);
848 return ret;
849}
850
851/**
852 * ptp_ek_sendfileobjectinfo:
853 * params: PTPParams*
854 * uint32_t* store - destination StorageID on Responder
855 * uint32_t* parenthandle - Parent ObjectHandle on responder
856 * uint32_t* handle - see Return values
857 * PTPObjectInfo* objectinfo- ObjectInfo that is to be sent
858 *
859 * Sends ObjectInfo of file that is to be sent via SendFileObject.
860 *
861 * Return values: Some PTP_RC_* code.
862 * Upon success : uint32_t* store - Responder StorageID in which
863 * object will be stored
864 * uint32_t* parenthandle- Responder Parent ObjectHandle
865 * in which the object will be stored
866 * uint32_t* handle - Responder's reserved ObjectHandle
867 * for the incoming object
868 **/
869uint16_t
870ptp_ek_sendfileobjectinfo (PTPParams* params, uint32_t* store,
871 uint32_t* parenthandle, uint32_t* handle,
872 PTPObjectInfo* objectinfo)
873{
874 uint16_t ret;
875 PTPContainer ptp;
876 char* oidata=NULL;
877 uint32_t size;
878
879 PTP_CNT_INIT(ptp);
880 ptp.Code=PTP_OC_EK_SendFileObjectInfo;
881 ptp.Param1=*store;
882 ptp.Param2=*parenthandle;
883 ptp.Nparam=2;
884
885 size=ptp_pack_OI(params, objectinfo, &oidata);
886 ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &oidata);
887 free(oidata);
888 *store=ptp.Param1;
889 *parenthandle=ptp.Param2;
890 *handle=ptp.Param3;
891 return ret;
892}
893
894/**
895 * ptp_ek_sendfileobject:
896 * params: PTPParams*
897 * char* object - contains the object that is to be sent
898 * uint32_t size - object size
899 *
900 * Sends object to Responder.
901 *
902 * Return values: Some PTP_RC_* code.
903 *
904 */
905uint16_t
906ptp_ek_sendfileobject (PTPParams* params, char* object, uint32_t size)
907{
908 PTPContainer ptp;
909
910 PTP_CNT_INIT(ptp);
911 ptp.Code=PTP_OC_EK_SendFileObject;
912 ptp.Nparam=0;
913
914 return ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &object);
915}
916
917/*************************************************************************
918 *
919 * Canon PTP extensions support
920 *
921 * (C) Nikolai Kopanygin 2003
922 *
923 *************************************************************************/
924
925
926/**
927 * ptp_canon_getobjectsize:
928 * params: PTPParams*
929 * uint32_t handle - ObjectHandle
930 * uint32_t p2 - Yet unknown parameter,
931 * value 0 works.
932 *
933 * Gets form the responder the size of the specified object.
934 *
935 * Return values: Some PTP_RC_* code.
936 * Upon success : uint32_t* size - The object size
937 * uint32_t rp2 - Yet unknown parameter
938 *
939 **/
940uint16_t
941ptp_canon_getobjectsize (PTPParams* params, uint32_t handle, uint32_t p2,
942 uint32_t* size, uint32_t* rp2)
943{
944 uint16_t ret;
945 PTPContainer ptp;
946
947 PTP_CNT_INIT(ptp);
948 ptp.Code=PTP_OC_CANON_GetObjectSize;
949 ptp.Param1=handle;
950 ptp.Param2=p2;
951 ptp.Nparam=2;
952 ret=ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
953 *size=ptp.Param1;
954 *rp2=ptp.Param2;
955 return ret;
956}
957
958/**
959 * ptp_canon_startshootingmode:
960 * params: PTPParams*
961 *
962 * Starts shooting session. It emits a StorageInfoChanged
963 * event via the interrupt pipe and pushes the StorageInfoChanged
964 * and CANON_CameraModeChange events onto the event stack
965 * (see operation PTP_OC_CANON_CheckEvent).
966 *
967 * Return values: Some PTP_RC_* code.
968 *
969 **/
970uint16_t
971ptp_canon_startshootingmode (PTPParams* params)
972{
973 PTPContainer ptp;
974
975 PTP_CNT_INIT(ptp);
976 ptp.Code=PTP_OC_CANON_StartShootingMode;
977 ptp.Nparam=0;
978 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
979}
980
981/**
982 * ptp_canon_endshootingmode:
983 * params: PTPParams*
984 *
985 * This operation is observed after pressing the Disconnect
986 * button on the Remote Capture app. It emits a StorageInfoChanged
987 * event via the interrupt pipe and pushes the StorageInfoChanged
988 * and CANON_CameraModeChange events onto the event stack
989 * (see operation PTP_OC_CANON_CheckEvent).
990 *
991 * Return values: Some PTP_RC_* code.
992 *
993 **/
994uint16_t
995ptp_canon_endshootingmode (PTPParams* params)
996{
997 PTPContainer ptp;
998
999 PTP_CNT_INIT(ptp);
1000 ptp.Code=PTP_OC_CANON_EndShootingMode;
1001 ptp.Nparam=0;
1002 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
1003}
1004
1005/**
1006 * ptp_canon_viewfinderon:
1007 * params: PTPParams*
1008 *
1009 * Prior to start reading viewfinder images, one must call this operation.
1010 * Supposedly, this operation affects the value of the CANON_ViewfinderMode
1011 * property.
1012 *
1013 * Return values: Some PTP_RC_* code.
1014 *
1015 **/
1016uint16_t
1017ptp_canon_viewfinderon (PTPParams* params)
1018{
1019 PTPContainer ptp;
1020
1021 PTP_CNT_INIT(ptp);
1022 ptp.Code=PTP_OC_CANON_ViewfinderOn;
1023 ptp.Nparam=0;
1024 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
1025}
1026
1027/**
1028 * ptp_canon_viewfinderoff:
1029 * params: PTPParams*
1030 *
1031 * Before changing the shooting mode, or when one doesn't need to read
1032 * viewfinder images any more, one must call this operation.
1033 * Supposedly, this operation affects the value of the CANON_ViewfinderMode
1034 * property.
1035 *
1036 * Return values: Some PTP_RC_* code.
1037 *
1038 **/
1039uint16_t
1040ptp_canon_viewfinderoff (PTPParams* params)
1041{
1042 PTPContainer ptp;
1043
1044 PTP_CNT_INIT(ptp);
1045 ptp.Code=PTP_OC_CANON_ViewfinderOff;
1046 ptp.Nparam=0;
1047 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
1048}
1049
1050/**
1051 * ptp_canon_reflectchanges:
1052 * params: PTPParams*
1053 * uint32_t p1 - Yet unknown parameter,
1054 * value 7 works
1055 *
1056 * Make viewfinder reflect changes.
1057 * There is a button for this operation in the Remote Capture app.
1058 * What it does exactly I don't know. This operation is followed
1059 * by the CANON_GetChanges(?) operation in the log.
1060 *
1061 * Return values: Some PTP_RC_* code.
1062 *
1063 **/
1064uint16_t
1065ptp_canon_reflectchanges (PTPParams* params, uint32_t p1)
1066{
1067 PTPContainer ptp;
1068
1069 PTP_CNT_INIT(ptp);
1070 ptp.Code=PTP_OC_CANON_ReflectChanges;
1071 ptp.Param1=p1;
1072 ptp.Nparam=1;
1073 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
1074}
1075
1076
1077/**
1078 * ptp_canon_checkevent:
1079 * params: PTPParams*
1080 *
1081 * The camera has a FIFO stack, in which it accumulates events.
1082 * Partially these events are communicated also via the USB interrupt pipe
1083 * according to the PTP USB specification, partially not.
1084 * This operation returns from the device a block of data, empty,
1085 * if the event stack is empty, or filled with an event's data otherwise.
1086 * The event is removed from the stack in the latter case.
1087 * The Remote Capture app sends this command to the camera all the time
1088 * of connection, filling with it the gaps between other operations.
1089 *
1090 * Return values: Some PTP_RC_* code.
1091 * Upon success : PTPUSBEventContainer* event - is filled with the event data
1092 * if any
1093 * int *isevent - returns 1 in case of event
1094 * or 0 otherwise
1095 **/
1096uint16_t
1097ptp_canon_checkevent (PTPParams* params, PTPUSBEventContainer* event, int* isevent)
1098{
1099 uint16_t ret;
1100 PTPContainer ptp;
1101 char *evdata = NULL;
1102
1103 *isevent=0;
1104 PTP_CNT_INIT(ptp);
1105 ptp.Code=PTP_OC_CANON_CheckEvent;
1106 ptp.Nparam=0;
1107 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &evdata);
1108 if (evdata!=NULL) {
1109 if (ret == PTP_RC_OK) {
1110 ptp_unpack_EC(params, evdata, event);
1111 *isevent=1;
1112 }
1113 free(evdata);
1114 }
1115 return ret;
1116}
1117
1118
1119/**
1120 * ptp_canon_focuslock:
1121 *
1122 * This operation locks the focus. It is followed by the CANON_GetChanges(?)
1123 * operation in the log.
1124 * It affects the CANON_MacroMode property.
1125 *
1126 * params: PTPParams*
1127 *
1128 * Return values: Some PTP_RC_* code.
1129 *
1130 **/
1131uint16_t
1132ptp_canon_focuslock (PTPParams* params)
1133{
1134 PTPContainer ptp;
1135
1136 PTP_CNT_INIT(ptp);
1137 ptp.Code=PTP_OC_CANON_FocusLock;
1138 ptp.Nparam=0;
1139 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
1140}
1141
1142/**
1143 * ptp_canon_focusunlock:
1144 *
1145 * This operation unlocks the focus. It is followed by the CANON_GetChanges(?)
1146 * operation in the log.
1147 * It sets the CANON_MacroMode property value to 1 (where it occurs in the log).
1148 *
1149 * params: PTPParams*
1150 *
1151 * Return values: Some PTP_RC_* code.
1152 *
1153 **/
1154uint16_t
1155ptp_canon_focusunlock (PTPParams* params)
1156{
1157 PTPContainer ptp;
1158
1159 PTP_CNT_INIT(ptp);
1160 ptp.Code=PTP_OC_CANON_FocusUnlock;
1161 ptp.Nparam=0;
1162 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
1163}
1164
1165/**
1166 * ptp_canon_initiatecaptureinmemory:
1167 *
1168 * This operation starts the image capture according to the current camera
1169 * settings. When the capture has happened, the camera emits a CaptureComplete
1170 * event via the interrupt pipe and pushes the CANON_RequestObjectTransfer,
1171 * CANON_DeviceInfoChanged and CaptureComplete events onto the event stack
1172 * (see operation CANON_CheckEvent). From the CANON_RequestObjectTransfer
1173 * event's parameter one can learn the just captured image's ObjectHandle.
1174 * The image is stored in the camera's own RAM.
1175 * On the next capture the image will be overwritten!
1176 *
1177 * params: PTPParams*
1178 *
1179 * Return values: Some PTP_RC_* code.
1180 *
1181 **/
1182uint16_t
1183ptp_canon_initiatecaptureinmemory (PTPParams* params)
1184{
1185 PTPContainer ptp;
1186
1187 PTP_CNT_INIT(ptp);
1188 ptp.Code=PTP_OC_CANON_InitiateCaptureInMemory;
1189 ptp.Nparam=0;
1190 return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL);
1191}
1192
1193/**
1194 * ptp_canon_getpartialobject:
1195 *
1196 * This operation is used to read from the device a data
1197 * block of an object from a specified offset.
1198 *
1199 * params: PTPParams*
1200 * uint32_t handle - the handle of the requested object
1201 * uint32_t offset - the offset in bytes from the beginning of the object
1202 * uint32_t size - the requested size of data block to read
1203 * uint32_t pos - 1 for the first block, 2 - for a block in the middle,
1204 * 3 - for the last block
1205 *
1206 * Return values: Some PTP_RC_* code.
1207 * char **block - the pointer to the block of data read
1208 * uint32_t* readnum - the number of bytes read
1209 *
1210 **/
1211uint16_t
1212ptp_canon_getpartialobject (PTPParams* params, uint32_t handle,
1213 uint32_t offset, uint32_t size,
1214 uint32_t pos, char** block,
1215 uint32_t* readnum)
1216{
1217 uint16_t ret;
1218 PTPContainer ptp;
1219 char *data=NULL;
1220
1221 PTP_CNT_INIT(ptp);
1222 ptp.Code=PTP_OC_CANON_GetPartialObject;
1223 ptp.Param1=handle;
1224 ptp.Param2=offset;
1225 ptp.Param3=size;
1226 ptp.Param4=pos;
1227 ptp.Nparam=4;
1228 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data);
1229 if (ret==PTP_RC_OK) {
1230 *block=data;
1231 *readnum=ptp.Param1;
1232 }
1233 return ret;
1234}
1235
1236/**
1237 * ptp_canon_getviewfinderimage:
1238 *
1239 * This operation can be used to read the image which is currently
1240 * in the camera's viewfinder. The image size is 320x240, format is JPEG.
1241 * Of course, prior to calling this operation, one must turn the viewfinder
1242 * on with the CANON_ViewfinderOn command.
1243 * Invoking this operation many times, one can get live video from the camera!
1244 *
1245 * params: PTPParams*
1246 *
1247 * Return values: Some PTP_RC_* code.
1248 * char **image - the pointer to the read image
1249 * unit32_t *size - the size of the image in bytes
1250 *
1251 **/
1252uint16_t
1253ptp_canon_getviewfinderimage (PTPParams* params, char** image, uint32_t* size)
1254{
1255 uint16_t ret;
1256 PTPContainer ptp;
1257
1258 PTP_CNT_INIT(ptp);
1259 ptp.Code=PTP_OC_CANON_GetViewfinderImage;
1260 ptp.Nparam=0;
1261 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, image);
1262 if (ret==PTP_RC_OK) *size=ptp.Param1;
1263 return ret;
1264}
1265
1266/**
1267 * ptp_canon_getchanges:
1268 *
1269 * This is an interesting operation, about the effect of which I am not sure.
1270 * This command is called every time when a device property has been changed
1271 * with the SetDevicePropValue operation, and after some other operations.
1272 * This operation reads the array of Device Properties which have been changed
1273 * by the previous operation.
1274 * Probably, this operation is even required to make those changes work.
1275 *
1276 * params: PTPParams*
1277 *
1278 * Return values: Some PTP_RC_* code.
1279 * uint16_t** props - the pointer to the array of changed properties
1280 * uint32_t* propnum - the number of elements in the *props array
1281 *
1282 **/
1283uint16_t
1284ptp_canon_getchanges (PTPParams* params, uint16_t** props, uint32_t* propnum)
1285{
1286 uint16_t ret;
1287 PTPContainer ptp;
1288 char* data=NULL;
1289
1290 PTP_CNT_INIT(ptp);
1291 ptp.Code=PTP_OC_CANON_GetChanges;
1292 ptp.Nparam=0;
1293 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data);
1294 if (ret == PTP_RC_OK)
1295 *propnum=ptp_unpack_uint16_t_array(params,data,0,props);
1296 free(data);
1297 return ret;
1298}
1299
1300/**
1301 * ptp_canon_getfolderentries:
1302 *
1303 * This command reads a specified object's record in a device's filesystem,
1304 * or the records of all objects belonging to a specified folder (association).
1305 *
1306 * params: PTPParams*
1307 * uint32_t store - StorageID,
1308 * uint32_t p2 - Yet unknown (0 value works OK)
1309 * uint32_t parent - Parent Object Handle
1310 * # If Parent Object Handle is 0xffffffff,
1311 * # the Parent Object is the top level folder.
1312 * uint32_t handle - Object Handle
1313 * # If Object Handle is 0, the records of all objects
1314 * # belonging to the Parent Object are read.
1315 * # If Object Handle is not 0, only the record of this
1316 * # Object is read.
1317 *
1318 * Return values: Some PTP_RC_* code.
1319 * PTPCANONFolderEntry** entries - the pointer to the folder entry array
1320 * uint32_t* entnum - the number of elements of the array
1321 *
1322 **/
1323uint16_t
1324ptp_canon_getfolderentries (PTPParams* params, uint32_t store, uint32_t p2,
1325 uint32_t parent, uint32_t handle,
1326 PTPCANONFolderEntry** entries, uint32_t* entnum)
1327{
1328 uint16_t ret;
1329 PTPContainer ptp;
1330 char *data = NULL;
1331
1332 PTP_CNT_INIT(ptp);
1333 ptp.Code=PTP_OC_CANON_GetFolderEntries;
1334 ptp.Param1=store;
1335 ptp.Param2=p2;
1336 ptp.Param3=parent;
1337 ptp.Param4=handle;
1338 ptp.Nparam=4;
1339 ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data);
1340 if (ret == PTP_RC_OK) {
1341 int i;
1342 *entnum=ptp.Param1;
1343 *entries=calloc(*entnum, sizeof(PTPCANONFolderEntry));
1344 if (*entries!=NULL) {
1345 for(i=0; i<(*entnum); i++)
1346 ptp_unpack_Canon_FE(params,
1347 data+i*PTP_CANON_FolderEntryLen,
1348 &((*entries)[i]) );
1349 } else {
1350 ret=PTP_ERROR_IO; /* Cannot allocate memory */
1351 }
1352 }
1353 free(data);
1354 return ret;
1355}
1356
1357
1358/* Non PTP protocol functions */
1359/* devinfo testing functions */
1360
1361int
1362ptp_operation_issupported(PTPParams* params, uint16_t operation)
1363{
1364 int i=0;
1365
1366 for (;i<params->deviceinfo.OperationsSupported_len;i++) {
1367 if (params->deviceinfo.OperationsSupported[i]==operation)
1368 return 1;
1369 }
1370 return 0;
1371}
1372
1373
1374int
1375ptp_property_issupported(PTPParams* params, uint16_t property)
1376{
1377 int i=0;
1378
1379 for (;i<params->deviceinfo.DevicePropertiesSupported_len;i++) {
1380 if (params->deviceinfo.DevicePropertiesSupported[i]==property)
1381 return 1;
1382 }
1383 return 0;
1384}
1385
1386/* ptp structures feeing functions */
1387
1388void
1389ptp_free_devicepropdesc(PTPDevicePropDesc* dpd)
1390{
1391 uint16_t i;
1392
1393 free(dpd->FactoryDefaultValue);
1394 free(dpd->CurrentValue);
1395 switch (dpd->FormFlag) {
1396 case PTP_DPFF_Range:
1397 free (dpd->FORM.Range.MinimumValue);
1398 free (dpd->FORM.Range.MaximumValue);
1399 free (dpd->FORM.Range.StepSize);
1400 break;
1401 case PTP_DPFF_Enumeration:
1402 for (i=0;i<dpd->FORM.Enum.NumberOfValues;i++)
1403 free(dpd->FORM.Enum.SupportedValue[i]);
1404 free(dpd->FORM.Enum.SupportedValue);
1405 }
1406}
1407
1408/* added by RAL 2006-01-01 */
1409
1410void
1411ptp_free_deviceinfo(PTPDeviceInfo* di)
1412{
1413 free(di->VendorExtensionDesc);
1414 free(di->OperationsSupported);
1415 free(di->EventsSupported);
1416 free(di->DevicePropertiesSupported);
1417 free(di->CaptureFormats);
1418 free(di->ImageFormats);
1419 free(di->Manufacturer);
1420 free(di->Model);
1421 free(di->DeviceVersion);
1422 free(di->SerialNumber);
1423}
1424
1425/* report PTP errors */
1426
1427void
1428ptp_perror(PTPParams* params, uint16_t error) {
1429
1430 int i;
1431 /* PTP error descriptions */
1432 static struct {
1433 short error;
1434 const char *txt;
1435 } ptp_errors[] = {
1436 {PTP_RC_Undefined, N_("PTP: Undefined Error")},
1437 {PTP_RC_OK, N_("PTP: OK!")},
1438 {PTP_RC_GeneralError, N_("PTP: General Error")},
1439 {PTP_RC_SessionNotOpen, N_("PTP: Session Not Open")},
1440 {PTP_RC_InvalidTransactionID, N_("PTP: Invalid Transaction ID")},
1441 {PTP_RC_OperationNotSupported, N_("PTP: Operation Not Supported")},
1442 {PTP_RC_ParameterNotSupported, N_("PTP: Parameter Not Supported")},
1443 {PTP_RC_IncompleteTransfer, N_("PTP: Incomplete Transfer")},
1444 {PTP_RC_InvalidStorageId, N_("PTP: Invalid Storage ID")},
1445 {PTP_RC_InvalidObjectHandle, N_("PTP: Invalid Object Handle")},
1446 {PTP_RC_DevicePropNotSupported, N_("PTP: Device Prop Not Supported")},
1447 {PTP_RC_InvalidObjectFormatCode, N_("PTP: Invalid Object Format Code")},
1448 {PTP_RC_StoreFull, N_("PTP: Store Full")},
1449 {PTP_RC_ObjectWriteProtected, N_("PTP: Object Write Protected")},
1450 {PTP_RC_StoreReadOnly, N_("PTP: Store Read Only")},
1451 {PTP_RC_AccessDenied, N_("PTP: Access Denied")},
1452 {PTP_RC_NoThumbnailPresent, N_("PTP: No Thumbnail Present")},
1453 {PTP_RC_SelfTestFailed, N_("PTP: Self Test Failed")},
1454 {PTP_RC_PartialDeletion, N_("PTP: Partial Deletion")},
1455 {PTP_RC_StoreNotAvailable, N_("PTP: Store Not Available")},
1456 {PTP_RC_SpecificationByFormatUnsupported,
1457 N_("PTP: Specification By Format Unsupported")},
1458 {PTP_RC_NoValidObjectInfo, N_("PTP: No Valid Object Info")},
1459 {PTP_RC_InvalidCodeFormat, N_("PTP: Invalid Code Format")},
1460 {PTP_RC_UnknownVendorCode, N_("PTP: Unknown Vendor Code")},
1461 {PTP_RC_CaptureAlreadyTerminated,
1462 N_("PTP: Capture Already Terminated")},
1463 {PTP_RC_DeviceBusy, N_("PTP: Device Bus")},
1464 {PTP_RC_InvalidParentObject, N_("PTP: Invalid Parent Object")},
1465 {PTP_RC_InvalidDevicePropFormat, N_("PTP: Invalid Device Prop Format")},
1466 {PTP_RC_InvalidDevicePropValue, N_("PTP: Invalid Device Prop Value")},
1467 {PTP_RC_InvalidParameter, N_("PTP: Invalid Parameter")},
1468 {PTP_RC_SessionAlreadyOpened, N_("PTP: Session Already Opened")},
1469 {PTP_RC_TransactionCanceled, N_("PTP: Transaction Canceled")},
1470 {PTP_RC_SpecificationOfDestinationUnsupported,
1471 N_("PTP: Specification Of Destination Unsupported")},
1472
1473 {PTP_ERROR_IO, N_("PTP: I/O error")},
1474 {PTP_ERROR_BADPARAM, N_("PTP: Error: bad parameter")},
1475 {PTP_ERROR_DATA_EXPECTED, N_("PTP: Protocol error, data expected")},
1476 {PTP_ERROR_RESP_EXPECTED, N_("PTP: Protocol error, response expected")},
1477 {0, NULL}
1478 };
1479 static struct {
1480 short error;
1481 const char *txt;
1482 } ptp_errors_EK[] = {
1483 {PTP_RC_EK_FilenameRequired, N_("PTP EK: Filename Required")},
1484 {PTP_RC_EK_FilenameConflicts, N_("PTP EK: Filename Conflicts")},
1485 {PTP_RC_EK_FilenameInvalid, N_("PTP EK: Filename Invalid")},
1486 {0, NULL}
1487 };
1488
1489 for (i=0; ptp_errors[i].txt!=NULL; i++)
1490 if (ptp_errors[i].error == error){
1491 ptp_error(params, ptp_errors[i].txt);
1492 return;
1493 }
1494
1495 /*if (error|PTP_RC_EXTENSION_MASK==PTP_RC_EXTENSION)*/
1496 switch (params->deviceinfo.VendorExtensionID) {
1497 case PTP_VENDOR_EASTMAN_KODAK:
1498 for (i=0; ptp_errors_EK[i].txt!=NULL; i++)
1499 if (ptp_errors_EK[i].error==error)
1500 ptp_error(params, ptp_errors_EK[i].txt);
1501 break;
1502 }
1503}
1504
1505/* return ptp operation name */
1506
1507const char*
1508ptp_get_operation_name(PTPParams* params, uint16_t oc)
1509{
1510 int i;
1511 /* Operation Codes */
1512 struct {
1513 uint16_t oc;
1514 const char *txt;
1515 } ptp_operations[] = {
1516 {PTP_OC_Undefined, N_("UndefinedOperation")},
1517 {PTP_OC_GetDeviceInfo, N_("GetDeviceInfo")},
1518 {PTP_OC_OpenSession, N_("OpenSession")},
1519 {PTP_OC_CloseSession, N_("CloseSession")},
1520 {PTP_OC_GetStorageIDs, N_("GetStorageIDs")},
1521 {PTP_OC_GetStorageInfo, N_("GetStorageInfo")},
1522 {PTP_OC_GetNumObjects, N_("GetNumObjects")},
1523 {PTP_OC_GetObjectHandles, N_("GetObjectHandles")},
1524 {PTP_OC_GetObjectInfo, N_("GetObjectInfo")},
1525 {PTP_OC_GetObject, N_("GetObject")},
1526 {PTP_OC_GetThumb, N_("GetThumb")},
1527 {PTP_OC_DeleteObject, N_("DeleteObject")},
1528 {PTP_OC_SendObjectInfo, N_("SendObjectInfo")},
1529 {PTP_OC_SendObject, N_("SendObject")},
1530 {PTP_OC_InitiateCapture, N_("InitiateCapture")},
1531 {PTP_OC_FormatStore, N_("FormatStore")},
1532 {PTP_OC_ResetDevice, N_("ResetDevice")},
1533 {PTP_OC_SelfTest, N_("SelfTest")},
1534 {PTP_OC_SetObjectProtection, N_("SetObjectProtection")},
1535 {PTP_OC_PowerDown, N_("PowerDown")},
1536 {PTP_OC_GetDevicePropDesc, N_("GetDevicePropDesc")},
1537 {PTP_OC_GetDevicePropValue, N_("GetDevicePropValue")},
1538 {PTP_OC_SetDevicePropValue, N_("SetDevicePropValue")},
1539 {PTP_OC_ResetDevicePropValue, N_("ResetDevicePropValue")},
1540 {PTP_OC_TerminateOpenCapture, N_("TerminateOpenCapture")},
1541 {PTP_OC_MoveObject, N_("MoveObject")},
1542 {PTP_OC_CopyObject, N_("CopyObject")},
1543 {PTP_OC_GetPartialObject, N_("GetPartialObject")},
1544 {PTP_OC_InitiateOpenCapture, N_("InitiateOpenCapture")},
1545 {0,NULL}
1546 };
1547 struct {
1548 uint16_t oc;
1549 const char *txt;
1550 } ptp_operations_EK[] = {
1551 {PTP_OC_EK_SendFileObjectInfo, N_("EK SendFileObjectInfo")},
1552 {PTP_OC_EK_SendFileObject, N_("EK SendFileObject")},
1553 {0,NULL}
1554 };
1555 struct {
1556 uint16_t oc;
1557 const char *txt;
1558 } ptp_operations_CANON[] = {
1559 {PTP_OC_CANON_GetObjectSize, N_("CANON GetObjectSize")},
1560 {PTP_OC_CANON_StartShootingMode,N_("CANON StartShootingMode")},
1561 {PTP_OC_CANON_EndShootingMode, N_("CANON EndShootingMode")},
1562 {PTP_OC_CANON_ViewfinderOn, N_("CANON ViewfinderOn")},
1563 {PTP_OC_CANON_ViewfinderOff, N_("CANON ViewfinderOff")},
1564 {PTP_OC_CANON_ReflectChanges, N_("CANON ReflectChanges")},
1565 {PTP_OC_CANON_CheckEvent, N_("CANON CheckEvent")},
1566 {PTP_OC_CANON_FocusLock, N_("CANON FocusLock")},
1567 {PTP_OC_CANON_FocusUnlock, N_("CANON FocusUnlock")},
1568 {PTP_OC_CANON_InitiateCaptureInMemory,
1569 N_("CANON InitiateCaptureInMemory")},
1570 {PTP_OC_CANON_GetPartialObject, N_("CANON GetPartialObject")},
1571 {PTP_OC_CANON_GetViewfinderImage,
1572 N_("CANON GetViewfinderImage")},
1573 {PTP_OC_CANON_GetChanges, N_("CANON GetChanges")},
1574 {PTP_OC_CANON_GetFolderEntries, N_("CANON GetFolderEntries")},
1575 {0,NULL}
1576 };
1577
1578 switch (params->deviceinfo.VendorExtensionID) {
1579 case PTP_VENDOR_EASTMAN_KODAK:
1580 for (i=0; ptp_operations_EK[i].txt!=NULL; i++)
1581 if (ptp_operations_EK[i].oc==oc)
1582 return (ptp_operations_EK[i].txt);
1583 break;
1584
1585 case PTP_VENDOR_CANON:
1586 for (i=0; ptp_operations_CANON[i].txt!=NULL; i++)
1587 if (ptp_operations_CANON[i].oc==oc)
1588 return (ptp_operations_CANON[i].txt);
1589 break;
1590 }
1591 for (i=0; ptp_operations[i].txt!=NULL; i++)
1592 if (ptp_operations[i].oc == oc){
1593 return (ptp_operations[i].txt);
1594 }
1595
1596 return NULL;
1597}
1598
1599/* return ptp property nam */
1600
1601const char*
1602ptp_get_property_name(PTPParams* params, uint16_t dpc)
1603{
1604 int i;
1605 /* Device Property descriptions */
1606 struct {
1607 uint16_t dpc;
1608 const char *txt;
1609 } ptp_device_properties[] = {
1610 {PTP_DPC_Undefined, N_("PTP Undefined Property")},
1611 {PTP_DPC_BatteryLevel, N_("Battery Level")},
1612 {PTP_DPC_FunctionalMode, N_("Functional Mode")},
1613 {PTP_DPC_ImageSize, N_("Image Size")},
1614 {PTP_DPC_CompressionSetting, N_("Compression Setting")},
1615 {PTP_DPC_WhiteBalance, N_("White Balance")},
1616 {PTP_DPC_RGBGain, N_("RGB Gain")},
1617 {PTP_DPC_FNumber, N_("F-Number")},
1618 {PTP_DPC_FocalLength, N_("Focal Length")},
1619 {PTP_DPC_FocusDistance, N_("Focus Distance")},
1620 {PTP_DPC_FocusMode, N_("Focus Mode")},
1621 {PTP_DPC_ExposureMeteringMode, N_("Exposure Metering Mode")},
1622 {PTP_DPC_FlashMode, N_("Flash Mode")},
1623 {PTP_DPC_ExposureTime, N_("Exposure Time")},
1624 {PTP_DPC_ExposureProgramMode, N_("Exposure Program Mode")},
1625 {PTP_DPC_ExposureIndex,
1626 N_("Exposure Index (film speed ISO)")},
1627 {PTP_DPC_ExposureBiasCompensation,
1628 N_("Exposure Bias Compensation")},
1629 {PTP_DPC_DateTime, N_("Date Time")},
1630 {PTP_DPC_CaptureDelay, N_("Pre-Capture Delay")},
1631 {PTP_DPC_StillCaptureMode, N_("Still Capture Mode")},
1632 {PTP_DPC_Contrast, N_("Contrast")},
1633 {PTP_DPC_Sharpness, N_("Sharpness")},
1634 {PTP_DPC_DigitalZoom, N_("Digital Zoom")},
1635 {PTP_DPC_EffectMode, N_("Effect Mode")},
1636 {PTP_DPC_BurstNumber, N_("Burst Number")},
1637 {PTP_DPC_BurstInterval, N_("Burst Interval")},
1638 {PTP_DPC_TimelapseNumber, N_("Timelapse Number")},
1639 {PTP_DPC_TimelapseInterval, N_("Timelapse Interval")},
1640 {PTP_DPC_FocusMeteringMode, N_("Focus Metering Mode")},
1641 {PTP_DPC_UploadURL, N_("Upload URL")},
1642 {PTP_DPC_Artist, N_("Artist")},
1643 {PTP_DPC_CopyrightInfo, N_("Copyright Info")},
1644 {0,NULL}
1645 };
1646 struct {
1647 uint16_t dpc;
1648 const char *txt;
1649 } ptp_device_properties_EK[] = {
1650 {PTP_DPC_EK_ColorTemperature, N_("EK Color Temperature")},
1651 {PTP_DPC_EK_DateTimeStampFormat,
1652 N_("EK Date Time Stamp Format")},
1653 {PTP_DPC_EK_BeepMode, N_("EK Beep Mode")},
1654 {PTP_DPC_EK_VideoOut, N_("EK Video Out")},
1655 {PTP_DPC_EK_PowerSaving, N_("EK Power Saving")},
1656 {PTP_DPC_EK_UI_Language, N_("EK UI Language")},
1657 {0,NULL}
1658 };
1659
1660 struct {
1661 uint16_t dpc;
1662 const char *txt;
1663 } ptp_device_properties_CANON[] = {
1664 {PTP_DPC_CANON_BeepMode, N_("CANON Beep Mode")},
1665 {PTP_DPC_CANON_UnixTime, N_("CANON Time measured in"
1666 " secondssince 01-01-1970")},
1667 {PTP_DPC_CANON_FlashMemory,
1668 N_("CANON Flash Card Capacity")},
1669 {PTP_DPC_CANON_CameraModel, N_("CANON Camera Model")},
1670 {0,NULL}
1671 };
1672/* Nikon Codes added by Corey Manders and Mehreen Chaudary */
1673 struct {
1674 uint16_t dpc;
1675 const char *txt;
1676 } ptp_device_properties_NIKON[] = {
1677 {PTP_DPC_NIKON_ShootingBank, N_("NIKON Shooting Bank")},
1678 {PTP_DPC_NIKON_ShootingBankNameA,
1679 N_("NIKON Shooting Bank Name A")},
1680 {PTP_DPC_NIKON_ShootingBankNameB,
1681 N_("NIKON Shooting Bank Name B")},
1682 {PTP_DPC_NIKON_ShootingBankNameC,
1683 N_("NIKON Shooting Bank Name C")},
1684 {PTP_DPC_NIKON_ShootingBankNameD,
1685 N_("NIKON Shooting Bank Name D")},
1686 {PTP_DPC_NIKON_RawCompression, N_("NIKON Raw Compression")},
1687 {PTP_DPC_NIKON_WhiteBalanceAutoBias,
1688 N_("NIKON White Balance Auto Bias")},
1689 {PTP_DPC_NIKON_WhiteBalanceTungstenBias,
1690 N_("NIKON White Balance Tungsten Bias")},
1691 {PTP_DPC_NIKON_WhiteBalanceFlourescentBias,
1692 N_("NIKON White Balance Flourescent Bias")},
1693 {PTP_DPC_NIKON_WhiteBalanceDaylightBias,
1694 N_("NIKON White Balance Daylight Bias")},
1695 {PTP_DPC_NIKON_WhiteBalanceFlashBias,
1696 N_("NIKON White Balance Flash Bias")},
1697 {PTP_DPC_NIKON_WhiteBalanceCloudyBias,
1698 N_("NIKON White Balance Cloudy Bias")},
1699 {PTP_DPC_NIKON_WhiteBalanceShadeBias,
1700 N_("NIKON White Balance Shade Bias")},
1701 {PTP_DPC_NIKON_WhiteBalanceColourTemperature,
1702 N_("NIKON White Balance Colour Temperature")},
1703 {PTP_DPC_NIKON_ImageSharpening,
1704 N_("NIKON Image Sharpening")},
1705 {PTP_DPC_NIKON_ToneCompensation,
1706 N_("NIKON Tone Compensation")},
1707 {PTP_DPC_NIKON_ColourMode, N_("NIKON Colour Mode")},
1708 {PTP_DPC_NIKON_HueAdjustment, N_("NIKON Hue Adjustment")},
1709 {PTP_DPC_NIKON_NonCPULensDataFocalLength,
1710 N_("NIKON Non CPU Lens Data Focal Length")},
1711 {PTP_DPC_NIKON_NonCPULensDataMaximumAperture,
1712 N_("NIKON Non CPU Lens Data Maximum Aperture")},
1713 {PTP_DPC_NIKON_CSMMenuBankSelect,
1714 N_("NIKON CSM Menu Bank Select")},
1715 {PTP_DPC_NIKON_MenuBankNameA, N_("NIKON Menu Bank Name A")},
1716 {PTP_DPC_NIKON_MenuBankNameB, N_("NIKON Menu Bank Name B")},
1717 {PTP_DPC_NIKON_MenuBankNameC, N_("NIKON Menu Bank Name C")},
1718 {PTP_DPC_NIKON_MenuBankNameD, N_("NIKON Menu Bank Name D")},
1719 {PTP_DPC_NIKON_A1AFCModePriority,
1720 N_("NIKON (A1) AFC Mode Priority")},
1721 {PTP_DPC_NIKON_A2AFSModePriority,
1722 N_("NIKON (A2) AFS Mode Priority")},
1723 {PTP_DPC_NIKON_A3GroupDynamicAF,
1724 N_("NIKON (A3) Group Dynamic AF")},
1725 {PTP_DPC_NIKON_A4AFActivation,
1726 N_("NIKON (A4) AF Activation")},
1727 {PTP_DPC_NIKON_A5FocusAreaIllumManualFocus,
1728 N_("NIKON (A5) Focus Area Illum Manual Focus")},
1729 {PTP_DPC_NIKON_FocusAreaIllumContinuous,
1730 N_("NIKON Focus Area Illum Continuous")},
1731 {PTP_DPC_NIKON_FocusAreaIllumWhenSelected,
1732 N_("NIKON Focus Area Illum When Selected")},
1733 {PTP_DPC_NIKON_A6FocusArea, N_("NIKON (A6) Focus Area")},
1734 {PTP_DPC_NIKON_A7VerticalAFON,
1735 N_("NIKON (A7) Vertical AF ON")},
1736 {PTP_DPC_NIKON_B1ISOAuto, N_("NIKON (B1) ISO Auto")},
1737 {PTP_DPC_NIKON_B2ISOStep, N_("NIKON (B2) ISO Step")},
1738 {PTP_DPC_NIKON_B3EVStep, N_("NIKON (B3) EV Step")},
1739 {PTP_DPC_NIKON_B4ExposureCompEv,
1740 N_("NIKON (B4) Exposure Comp Ev")},
1741 {PTP_DPC_NIKON_B5ExposureComp,
1742 N_("NIKON (B5) Exposure Comp")},
1743 {PTP_DPC_NIKON_B6CenterWeightArea,
1744 N_("NIKON (B6) Center Weight Area")},
1745 {PTP_DPC_NIKON_C1AELock, N_("NIKON (C1) AE Lock")},
1746 {PTP_DPC_NIKON_C2AELAFL, N_("NIKON (C2) AE_L/AF_L")},
1747 {PTP_DPC_NIKON_C3AutoMeterOff,
1748 N_("NIKON (C3) Auto Meter Off")},
1749 {PTP_DPC_NIKON_C4SelfTimer, N_("NIKON (C4) Self Timer")},
1750 {PTP_DPC_NIKON_C5MonitorOff, N_("NIKON (C5) Monitor Off")},
1751 {PTP_DPC_NIKON_D1ShootingSpeed,
1752 N_("NIKON (D1) Shooting Speed")},
1753 {PTP_DPC_NIKON_D2MaximumShots,
1754 N_("NIKON (D2) Maximum Shots")},
1755 {PTP_DPC_NIKON_D3ExpDelayMode, N_("NIKON (D3) ExpDelayMode")},
1756 {PTP_DPC_NIKON_D4LongExposureNoiseReduction,
1757 N_("NIKON (D4) Long Exposure Noise Reduction")},
1758 {PTP_DPC_NIKON_D5FileNumberSequence,
1759 N_("NIKON (D5) File Number Sequence")},
1760 {PTP_DPC_NIKON_D6ControlPanelFinderRearControl,
1761 N_("NIKON (D6) Control Panel Finder Rear Control")},
1762 {PTP_DPC_NIKON_ControlPanelFinderViewfinder,
1763 N_("NIKON Control Panel Finder Viewfinder")},
1764 {PTP_DPC_NIKON_D7Illumination, N_("NIKON (D7) Illumination")},
1765 {PTP_DPC_NIKON_E1FlashSyncSpeed,
1766 N_("NIKON (E1) Flash Sync Speed")},
1767 {PTP_DPC_NIKON_E2FlashShutterSpeed,
1768 N_("NIKON (E2) Flash Shutter Speed")},
1769 {PTP_DPC_NIKON_E3AAFlashMode,
1770 N_("NIKON (E3) AA Flash Mode")},
1771 {PTP_DPC_NIKON_E4ModelingFlash,
1772 N_("NIKON (E4) Modeling Flash")},
1773 {PTP_DPC_NIKON_E5AutoBracketSet,
1774 N_("NIKON (E5) Auto Bracket Set")},
1775 {PTP_DPC_NIKON_E6ManualModeBracketing,
1776 N_("NIKON (E6) Manual Mode Bracketing")},
1777 {PTP_DPC_NIKON_E7AutoBracketOrder,
1778 N_("NIKON (E7) Auto Bracket Order")},
1779 {PTP_DPC_NIKON_E8AutoBracketSelection,
1780 N_("NIKON (E8) Auto Bracket Selection")},
1781 {PTP_DPC_NIKON_F1CenterButtonShootingMode,
1782 N_("NIKON (F1) Center Button Shooting Mode")},
1783 {PTP_DPC_NIKON_CenterButtonPlaybackMode,
1784 N_("NIKON Center Button Playback Mode")},
1785 {PTP_DPC_NIKON_F2Multiselector,
1786 N_("NIKON (F2) Multiselector")},
1787 {PTP_DPC_NIKON_F3PhotoInfoPlayback,
1788 N_("NIKON (F3) PhotoInfoPlayback")},
1789 {PTP_DPC_NIKON_F4AssignFuncButton,
1790 N_("NIKON (F4) Assign Function Button")},
1791 {PTP_DPC_NIKON_F5CustomizeCommDials,
1792 N_("NIKON (F5) Customize Comm Dials")},
1793 {PTP_DPC_NIKON_ChangeMainSub, N_("NIKON Change Main Sub")},
1794 {PTP_DPC_NIKON_ApertureSetting,
1795 N_("NIKON Aperture Setting")},
1796 {PTP_DPC_NIKON_MenusAndPlayback,
1797 N_("NIKON Menus and Playback")},
1798 {PTP_DPC_NIKON_F6ButtonsAndDials,
1799 N_("NIKON (F6) Buttons and Dials")},
1800 {PTP_DPC_NIKON_F7NoCFCard, N_("NIKON (F7) No CF Card")},
1801 {PTP_DPC_NIKON_AutoImageRotation,
1802 N_("NIKON Auto Image Rotation")},
1803 {PTP_DPC_NIKON_ExposureBracketingOnOff,
1804 N_("NIKON Exposure Bracketing On Off")},
1805 {PTP_DPC_NIKON_ExposureBracketingIntervalDist,
1806 N_("NIKON Exposure Bracketing Interval Distance")},
1807 {PTP_DPC_NIKON_ExposureBracketingNumBracketPlace,
1808 N_("NIKON Exposure Bracketing Number Bracket Place")},
1809 {PTP_DPC_NIKON_AutofocusLCDTopMode2,
1810 N_("NIKON Autofocus LCD Top Mode 2")},
1811 {PTP_DPC_NIKON_AutofocusLCDTopMode3AndMode4,
1812 N_("NIKON Autofocus LCD Top Mode 3 and Mode 4")},
1813 {PTP_DPC_NIKON_LightMeter, N_("NIKON Light Meter")},
1814 {PTP_DPC_NIKON_ExposureApertureLock,
1815 N_("NIKON Exposure Aperture Lock")},
1816 {PTP_DPC_NIKON_MaximumShots, N_("NIKON Maximum Shots")},
1817 {PTP_DPC_NIKON_Beep, N_("NIKON AF Beep Mode")},
1818 {PTP_DPC_NIKON_AFC, N_("NIKON ??? AF Related")},
1819 {PTP_DPC_NIKON_AFLampOff, N_("NIKON AF Lamp")},
1820 {PTP_DPC_NIKON_PADVPMode, N_("NIKON Auto ISO P/A/DVP Setting")},
1821 {PTP_DPC_NIKON_ReviewOff, N_("NIKON Image Review")},
1822 {PTP_DPC_NIKON_GridDisplay, N_("NIKON Viewfinder Grid Display")},
1823 {PTP_DPC_NIKON_AFAreaIllumination, N_("NIKON AF Area Illumination")},
1824 {PTP_DPC_NIKON_FlashMode, N_("NIKON Flash Mode")},
1825 {PTP_DPC_NIKON_FlashPower, N_("NIKON Flash Power")},
1826 {PTP_DPC_NIKON_FlashSignOff, N_("NIKON Flash Sign")},
1827 {PTP_DPC_NIKON_FlashExposureCompensation,
1828 N_("NIKON Flash Exposure Compensation")},
1829 {PTP_DPC_NIKON_RemoteTimeout, N_("NIKON Remote Timeout")},
1830 {PTP_DPC_NIKON_ImageCommentString, N_("NIKON Image Comment String")},
1831 {PTP_DPC_NIKON_FlashOpen, N_("NIKON Flash Open")},
1832 {PTP_DPC_NIKON_FlashCharged, N_("NIKON Flash Charged")},
1833 {PTP_DPC_NIKON_LensID, N_("NIKON Lens ID")},
1834 {PTP_DPC_NIKON_FocalLengthMin, N_("NIKON Min. Focal Length")},
1835 {PTP_DPC_NIKON_FocalLengthMax, N_("NIKON Max. Focal Length")},
1836 {PTP_DPC_NIKON_MaxApAtMinFocalLength,
1837 N_("NIKON Max. Aperture at Min. Focal Length")},
1838 {PTP_DPC_NIKON_MaxApAtMaxFocalLength,
1839 N_("NIKON Max. Aperture at Max. Focal Length")},
1840 {PTP_DPC_NIKON_LowLight, N_("NIKON Low Light")},
1841 {PTP_DPC_NIKON_ExtendedCSMMenu, N_("NIKON Extended CSM Menu")},
1842 {PTP_DPC_NIKON_OptimiseImage, N_("NIKON Optimise Image")},
1843 {0,NULL}
1844 };
1845
1846 for (i=0; ptp_device_properties[i].txt!=NULL; i++)
1847 if (ptp_device_properties[i].dpc==dpc)
1848 return (ptp_device_properties[i].txt);
1849
1850 /*if (dpc|PTP_DPC_EXTENSION_MASK==PTP_DPC_EXTENSION)*/
1851 switch (params->deviceinfo.VendorExtensionID) {
1852 case PTP_VENDOR_EASTMAN_KODAK:
1853 for (i=0; ptp_device_properties_EK[i].txt!=NULL; i++)
1854 if (ptp_device_properties_EK[i].dpc==dpc)
1855 return (ptp_device_properties_EK[i].txt);
1856 break;
1857
1858 case PTP_VENDOR_CANON:
1859 for (i=0; ptp_device_properties_CANON[i].txt!=NULL; i++)
1860 if (ptp_device_properties_CANON[i].dpc==dpc)
1861 return (ptp_device_properties_CANON[i].txt);
1862 break;
1863 case PTP_VENDOR_NIKON:
1864 for (i=0; ptp_device_properties_NIKON[i].txt!=NULL; i++)
1865 if (ptp_device_properties_NIKON[i].dpc==dpc)
1866 return (ptp_device_properties_NIKON[i].txt);
1867 break;
1868
1869
1870 }
1871 return NULL;
1872}
1873