Linus Walleij | eb8c6fe | 2006-02-03 09:46:22 +0000 | [diff] [blame^] | 1 | /* 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 */ |
| 51 | Progress_Callback* globalCallback; |
| 52 | |
| 53 | static void |
| 54 | ptp_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 | |
| 70 | static void |
| 71 | ptp_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 | |
| 89 | uint16_t |
| 90 | ptp_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 | |
| 134 | uint16_t |
| 135 | ptp_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 | |
| 228 | uint16_t |
| 229 | ptp_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 | |
| 301 | uint16_t |
| 302 | ptp_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 | **/ |
| 369 | uint16_t |
| 370 | ptp_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 | |
| 406 | static inline uint16_t |
| 407 | ptp_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 | |
| 447 | uint16_t |
| 448 | ptp_usb_event_check (PTPParams* params, PTPContainer* event) { |
| 449 | |
| 450 | return ptp_usb_event (params, event, PTP_EVENT_CHECK_FAST); |
| 451 | } |
| 452 | |
| 453 | uint16_t |
| 454 | ptp_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 | **/ |
| 475 | uint16_t |
| 476 | ptp_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 | **/ |
| 501 | uint16_t |
| 502 | ptp_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 | **/ |
| 533 | uint16_t |
| 534 | ptp_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 | **/ |
| 554 | uint16_t |
| 555 | ptp_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 | **/ |
| 580 | uint16_t |
| 581 | ptp_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 | **/ |
| 612 | uint16_t |
| 613 | ptp_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 | |
| 633 | uint16_t |
| 634 | ptp_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 | |
| 651 | uint16_t |
| 652 | ptp_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 | |
| 663 | uint16_t |
| 664 | ptp_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 | **/ |
| 685 | uint16_t |
| 686 | ptp_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 | **/ |
| 717 | uint16_t |
| 718 | ptp_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 | */ |
| 753 | uint16_t |
| 754 | ptp_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 | |
| 781 | uint16_t |
| 782 | ptp_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 | |
| 795 | uint16_t |
| 796 | ptp_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 | |
| 813 | uint16_t |
| 814 | ptp_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 | |
| 832 | uint16_t |
| 833 | ptp_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 | **/ |
| 869 | uint16_t |
| 870 | ptp_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 | */ |
| 905 | uint16_t |
| 906 | ptp_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 | **/ |
| 940 | uint16_t |
| 941 | ptp_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 | **/ |
| 970 | uint16_t |
| 971 | ptp_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 | **/ |
| 994 | uint16_t |
| 995 | ptp_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 | **/ |
| 1016 | uint16_t |
| 1017 | ptp_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 | **/ |
| 1039 | uint16_t |
| 1040 | ptp_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 | **/ |
| 1064 | uint16_t |
| 1065 | ptp_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 | **/ |
| 1096 | uint16_t |
| 1097 | ptp_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 | **/ |
| 1131 | uint16_t |
| 1132 | ptp_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 | **/ |
| 1154 | uint16_t |
| 1155 | ptp_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 | **/ |
| 1182 | uint16_t |
| 1183 | ptp_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 | **/ |
| 1211 | uint16_t |
| 1212 | ptp_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 | **/ |
| 1252 | uint16_t |
| 1253 | ptp_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 | **/ |
| 1283 | uint16_t |
| 1284 | ptp_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 | **/ |
| 1323 | uint16_t |
| 1324 | ptp_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 | |
| 1361 | int |
| 1362 | ptp_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 | |
| 1374 | int |
| 1375 | ptp_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 | |
| 1388 | void |
| 1389 | ptp_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 | |
| 1410 | void |
| 1411 | ptp_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 | |
| 1427 | void |
| 1428 | ptp_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 | |
| 1507 | const char* |
| 1508 | ptp_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 | |
| 1601 | const char* |
| 1602 | ptp_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 | |