diff options
Diffstat (limited to 'src/ptp.c')
-rw-r--r-- | src/ptp.c | 858 |
1 files changed, 807 insertions, 51 deletions
@@ -1,7 +1,7 @@ /* ptp.c * * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl> - * Copyright (C) 2003-2017 Marcus Meissner <marcus@jet.franken.de> + * Copyright (C) 2003-2018 Marcus Meissner <marcus@jet.franken.de> * Copyright (C) 2006-2008 Linus Walleij <triad@df.lth.se> * Copyright (C) 2007 Tero Saarni <tero.saarni@gmail.com> * Copyright (C) 2009 Axel Waggershauser <awagger@web.de> @@ -170,6 +170,7 @@ ptp_transaction_new (PTPParams* params, PTPContainer* ptp, ptp->SessionID=params->session_id; /* send request */ CHECK_PTP_RC(params->sendreq_func (params, ptp, flags)); + /* is there a dataphase? */ switch (flags&PTP_DP_DATA_MASK) { case PTP_DP_SENDDATA: @@ -182,10 +183,7 @@ ptp_transaction_new (PTPParams* params, PTPContainer* ptp, break; case PTP_DP_GETDATA: { - uint16_t ret = params->getdata_func(params, ptp, handler); - if (ret == PTP_ERROR_CANCEL) - CHECK_PTP_RC(params->cancelreq_func(params, params->transaction_id-1)); - CHECK_PTP_RC(ret); + CHECK_PTP_RC(params->getdata_func(params, ptp, handler)); } break; case PTP_DP_NODATA: @@ -463,7 +461,7 @@ uint16_t ptp_getdeviceinfo (PTPParams* params, PTPDeviceInfo* deviceinfo) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; int ret; @@ -481,7 +479,7 @@ uint16_t ptp_canon_eos_getdeviceinfo (PTPParams* params, PTPCanonEOSDeviceInfo*di) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; int ret; @@ -843,7 +841,228 @@ parse_9301_tree (PTPParams *params, xmlNodePtr node, PTPDeviceInfo *di) /*traverse_tree (0, node);*/ return PTP_RC_OK; } +#endif + +uint16_t +ptp_olympus_omd_capture (PTPParams* params) +{ + PTPContainer ptp; + uint16_t ret; + unsigned int size = 0; + unsigned char *buffer = NULL; + +/* these two trigger the capture ... one might be "shutter down", the other "shutter up"? */ + PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OMD_Capture, 0x3); // initiate capture + ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); + PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OMD_Capture, 0x6); // initiate capture + ret = ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); + + usleep(500); + +/* this only fetches changed props */ + PTP_CNT_INIT(ptp, 0x9486); /* query changed properties */ + ret = ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &buffer, &size); + free (buffer); + return ret; +} + +uint16_t +ptp_panasonic_liveview_image (PTPParams* params, unsigned char **data, unsigned int *size) +{ + PTPContainer ptp; + + PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_LiveviewImage); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); +} + +uint16_t +ptp_olympus_init_pc_mode (PTPParams* params) +{ + uint16_t ret; + PTPPropertyValue propval; + PTPContainer event; + int i; + + ptp_debug (params,"PTP: (Olympus Init) switching to PC mode..."); + + propval.u16 = 1; + ret = ptp_setdevicepropvalue (params, 0xD052, &propval, PTP_DTC_UINT16); + usleep(100000); + + for(i = 0; i < 2; i++) { + ptp_debug (params,"PTP: (Olympus Init) checking events..."); + /* Just busy loop until the camera is ready again. */ + ptp_check_event (params); + if (ptp_get_one_event(params, &event)) break; + usleep(100000); + } + +/* + * 9489 code: sends a list of PTP device properties supported apparently? on E-M1. + * F4 00 00 00 count +02 D0 03 D0 04 D0 05 D0 06 D0 07 D0 08 D0 09 D0 0C D0 0D D0 0E D0 0F D0 10 D0 11 D0 13 D0 14 D0 18 D0 1A D0 1B D0 1C D0 1D D0 1E D0 1F D0 20 D0 21 D0 22 D0 23 D0 24 D0 25 D0 26 D0 27 D0 28 D0 29 D0 2A D0 2B D0 2C D0 2D D0 2E D0 2F D0 30 D0 31 D0 32 D0 33 D0 34 D0 35 D0 36 D0 37 D0 38 D0 39 D0 3A D0 3B D0 3C D0 3D D0 3E D0 3F D0 40 D0 41 D0 42 D0 43 D0 44 D0 45 D0 46 D0 47 D0 48 D0 49 D0 4A D0 4B D0 4C D0 4D D0 4E D0 4F D0 50 D0 51 D0 52 D0 58 D0 59 D0 5F D0 60 D0 61 D0 62 D0 64 D0 65 D0 66 D0 68 D0 69 D0 70 D0 73 D0 67 D0 5A D0 5B D0 63 D0 6A D0 6B D0 6C D0 71 D0 72 D0 7A D0 7B D0 7C D0 7D D0 7F D0 80 D0 81 D0 82 D0 86 D0 87 D0 8B D0 8C D0 8E D0 8F D0 97 D0 9F D0 C4 D0 C5 D0 A2 D0 A3 D0 A4 D0 A6 D0 A7 D0 A8 D0 A9 D0 AA D0 AB D0 AC D0 AD D0 AE D0 B2 D0 B3 D0 B4 D0 B5 D0 B6 D0 B7 D0 B8 D0 B9 D0 BA D0 BC D0 BD D0 BE D0 BF D0 C0 D0 C6 D0 C7 D0 C8 D0 C9 D0 CB D0 CC D0 CD D0 CE D0 CF D0 D0 D0 D1 D0 D2 D0 D3 D0 D4 D0 D5 D0 D6 D0 D7 D0 D8 D0 D9 D0 DA D0 DB D0 DC D0 DD D0 DE D0 E2 D0 E3 D0 E4 D0 E5 D0 E6 D0 E7 D0 E8 D0 E9 D0 EA D0 EC D0 EF D0 F0 D0 F1 D0 F2 D0 F3 D0 F4 D0 F5 D0 F6 D0 F7 D0 F8 D0 F9 D0 FA D0 FB D0 FC D0 FD D0 FE D0 FF D0 00 D1 01 D1 02 D1 03 D1 04 D1 05 D1 06 D1 07 D1 08 D1 09 D1 0A D1 0B D1 0C D1 0D D1 0E D1 0F D1 10 D1 11 D1 12 D1 13 D1 14 D1 15 D1 16 D1 17 D1 18 D1 19 D1 1A D1 1B D1 1C D1 1D D1 1E D1 1F D1 20 D1 51 D1 52 D1 5A D1 24 D1 25 D1 26 D1 27 D1 28 D1 2D D1 2E D1 2F D1 30 D1 31 D1 34 D1 35 D1 36 D1 37 D1 38 D1 39 D1 3A D1 + * + * 9486: queries something. gets 00 00 00 00 ... or list of devicepropdesc in standard ptp propdesc format. + * could be some form of "properties changed" query perhaps? (32bit count in front) + * might only monitor/return properties set by 9489? + * + * 948a: seems also be some kind of polling function, returns 32bit 0 if nothing is there. similar to above? + * returns properties sent by 94b8. + * + * 948b: also sends a list of ptp devprops: + * 11 00 00 00 53 D0 54 D0 55 D0 56 D0 57 D0 6D D0 5C D0 5D D0 5E D0 74 D0 75 D0 83 D0 84 D0 85 D0 ED D0 79 D0 E1 D0 + * Events: c008: 21 D1 00 00 0F 00 00 00 01 00 00 00 + */ + //ptp_debug (params,"PTP: (Olympus Init) getting response..."); + //gp_port_set_timeout (camera->port, timeout); + //ret=ptp_transaction(params, &ptp, PTP_DP_RESPONSEONLY, size, &data, NULL); + //if(data) free(data); + return ret; +} + +uint16_t +ptp_olympus_liveview_image (PTPParams* params, unsigned char **data, unsigned int *size) +{ + PTPContainer ptp; + uint32_t param1 = 1; + + PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_GetLiveViewImage, param1); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); +} + +uint16_t +ptp_olympus_sdram_image (PTPParams* params, unsigned char **data, unsigned int *size) +{ + PTPContainer ptp; + + PTP_CNT_INIT(ptp, PTP_OC_OLYMPUS_OMD_GetImage); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, size); +} + +uint16_t +ptp_panasonic_setdeviceproperty (PTPParams* params, uint32_t propcode, + unsigned char *value, uint16_t valuesize) +{ + PTPContainer ptp; + uint16_t ret; + unsigned char *data; + uint32_t size = 4 + 4 + valuesize; + + data = calloc(size, sizeof(unsigned char)); + + htod32a(data, propcode); /* memcpy(data, &propcode, 4); */ + htod16a(&data[4], valuesize); /* memcpy(&data[4], &valuesize, 2); */ + + memcpy(&data[8], value, valuesize); /* perhaps check if one of the DPV packagers work? */ + + PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_SetProperty, propcode); + ret = ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size, &data, NULL); + free(data); + return ret; +} + +uint16_t +ptp_panasonic_getdevicepropertysize (PTPParams *params, uint32_t propcode) +{ + PTPContainer ptp; + unsigned char *data = NULL; + unsigned int size = 0; + + PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_9107, propcode, 0, 0); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + if (!data) return PTP_RC_GeneralError; + + if (size < 4) return PTP_RC_GeneralError; + uint32_t headerLength = dtoh32a( (data) + 4 ); + if (size < 4 + 6 * 4) return PTP_RC_GeneralError; + uint32_t propertyCode = dtoh32a( (data) + 4 + 6 * 4 ); + if (size < headerLength * 4 + 2 * 4) return PTP_RC_GeneralError; + + ptp_debug(params, "header: %lu, code: %lu\n", headerLength, propertyCode); + + return PTP_RC_OK; +} + +uint16_t +ptp_panasonic_getdevicepropertydesc (PTPParams *params, uint32_t propcode, uint16_t valuesize, uint32_t *currentValue, uint32_t **propertyValueList, uint32_t *propertyValueListLength) +{ + PTPContainer ptp; + unsigned char *data = NULL; + unsigned int size = 0; + uint16_t ret = 0; + + PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_ListProperty, propcode, 0, 0); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + if (!data) return PTP_RC_GeneralError; + + if (size < 4) return PTP_RC_GeneralError; + uint32_t headerLength = dtoh32a( (data) + 4 ); + if (size < 4 + 6 * 4) return PTP_RC_GeneralError; + uint32_t propertyCode = dtoh32a( (data) + 4 + 6 * 4 ); + if (size < headerLength * 4 + 2 * 4) return PTP_RC_GeneralError; + + if(valuesize == 2) { + *currentValue = (uint32_t) dtoh16a( (data) + headerLength * 4 + 2 * 4 ); + } else if(valuesize == 4) { + *currentValue = dtoh32a( (data) + headerLength * 4 + 2 * 4 ); + } else { + return PTP_RC_GeneralError; + } + if (size < headerLength * 4 + 2 * 4 + valuesize) return PTP_RC_GeneralError; + *propertyValueListLength = dtoh32a( (data) + headerLength * 4 + 2 * 4 + valuesize); + + ptp_debug(params, "header: %lu, code: 0x%lx, value: %lu, count: %lu", headerLength, propertyCode, *currentValue, *propertyValueListLength); + + if (size < headerLength * 4 + 3 * 4 + valuesize + (*propertyValueListLength) * valuesize) return PTP_RC_GeneralError; + + *propertyValueList = calloc(*propertyValueListLength, sizeof(uint32_t)); + + uint16_t i; + for(i = 0; i < *propertyValueListLength; i++) { + if(valuesize == 2) { + (*propertyValueList)[i] = (uint32_t) dtoh16a( (data) + headerLength * 4 + 3 * 4 + valuesize + i * valuesize); + } else if(valuesize == 4) { + (*propertyValueList)[i] = dtoh32a( (data) + headerLength * 4 + 3 * 4 + valuesize + i * valuesize); + } + //printf("Property: %lu\n", (*propertyValueList)[i]); + } + + free (data); + return ret; +} + + +uint16_t +ptp_panasonic_getdeviceproperty (PTPParams *params, uint32_t propcode, uint16_t *valuesize, uint32_t *currentValue) +{ + PTPContainer ptp; + unsigned char *data = NULL; + unsigned int size = 0; + uint16_t ret = PTP_RC_OK; + + PTP_CNT_INIT(ptp, PTP_OC_PANASONIC_GetProperty, propcode); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + if (!data) return PTP_RC_GeneralError; + + if(size < 8) return PTP_RC_GeneralError; + *valuesize = dtoh32a( (data + 4) ); + + if(size < 8 + (*valuesize)) return PTP_RC_GeneralError; + if(*valuesize == 4) { + *currentValue = dtoh32a( (data + 8) ); + } else if(*valuesize == 2) { + *currentValue = (uint32_t) dtoh16a( (data + 8) ); + } else { + return PTP_RC_GeneralError; + } + //printf("ptp_panasonic_getdeviceproperty: size: %lu, valuesize: %d, currentValue: %lu\n", size, *valuesize, *currentValue); + + free (data); + return ret; +} + +#ifdef HAVE_LIBXML2 static uint16_t ptp_olympus_parse_output_xml(PTPParams* params, char*data, int len, xmlNodePtr *code) { @@ -916,7 +1135,7 @@ ptp_olympus_getdeviceinfo (PTPParams* params, PTPDeviceInfo *di) #ifdef HAVE_LIBXML2 PTPContainer ptp; uint16_t ret; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; xmlNodePtr code; @@ -1156,7 +1375,7 @@ uint16_t ptp_getstorageids (PTPParams* params, PTPStorageIDs* storageids) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_GetStorageIDs); @@ -1181,7 +1400,7 @@ ptp_getstorageinfo (PTPParams* params, uint32_t storageid, PTPStorageInfo* storageinfo) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_GetStorageInfo, storageid); @@ -1218,7 +1437,7 @@ ptp_getobjecthandles (PTPParams* params, uint32_t storage, { PTPContainer ptp; uint16_t ret; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; objecthandles->Handler = NULL; @@ -1247,13 +1466,19 @@ ptp_getobjecthandles (PTPParams* params, uint32_t storage, uint16_t ptp_getfilesystemmanifest (PTPParams* params, uint32_t storage, - uint32_t objectformatcode, uint32_t associationOH, - unsigned char** data) -{ - PTPContainer ptp; + uint32_t objectformatcode, uint32_t associationOH, + uint64_t *numoifs, PTPObjectFilesystemInfo **oifs +) { + PTPContainer ptp; + unsigned int size = 0; + unsigned char *data = NULL; + *oifs = NULL; + *numoifs = 0; PTP_CNT_INIT(ptp, PTP_OC_GetFilesystemManifest, storage, objectformatcode, associationOH); - return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, NULL); + CHECK_PTP_RC (ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ptp_unpack_ptp11_manifest (params, data, size, numoifs, oifs); + return PTP_RC_OK; } /** @@ -1365,7 +1590,7 @@ ptp_getobjectinfo (PTPParams* params, uint32_t handle, PTPObjectInfo* objectinfo) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_GetObjectInfo, handle); @@ -1552,6 +1777,53 @@ ptp_deleteobject (PTPParams* params, uint32_t handle, uint32_t ofc) } /** + * ptp_moveobject: + * params: PTPParams* + * handle - source ObjectHandle + * storage - destination StorageID + * parent - destination parent ObjectHandle + * + * Move an object to a new location under the specified parent. + * Note that unlike most calls, 0 must be passed for the parent if the destination + * is the Storage root. + * + * Return values: Some PTP_RC_* code. + **/ +uint16_t +ptp_moveobject (PTPParams* params, uint32_t handle, uint32_t storage, uint32_t parent) +{ + PTPContainer ptp; + + PTP_CNT_INIT(ptp, PTP_OC_MoveObject, handle, storage, parent); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL)); + /* If the object is cached and could be removed, cleanse cache. */ + ptp_remove_object_from_cache(params, handle); + return PTP_RC_OK; +} + +/** + * ptp_copyobject: + * params: PTPParams* + * handle - source ObjectHandle + * storage - destination StorageID + * parent - destination parent ObjectHandle + * + * Copy an object to a new location under the specified parent. + * Note that unlike most calls, 0 must be passed for the parent if the destination + * is the Storage root. + * + * Return values: Some PTP_RC_* code. + **/ +uint16_t +ptp_copyobject (PTPParams* params, uint32_t handle, uint32_t storage, uint32_t parent) +{ + PTPContainer ptp; + + PTP_CNT_INIT(ptp, PTP_OC_CopyObject, handle, storage, parent); + return ptp_transaction(params, &ptp, PTP_DP_NODATA, 0, NULL, NULL); +} + +/** * ptp_sendobjectinfo: * params: PTPParams* * uint32_t* store - destination StorageID on Responder @@ -1663,7 +1935,7 @@ ptp_getdevicepropdesc (PTPParams* params, uint16_t propcode, { PTPContainer ptp; uint16_t ret = PTP_RC_OK; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_GetDevicePropDesc, propcode); @@ -1711,7 +1983,7 @@ ptp_getdevicepropvalue (PTPParams* params, uint16_t propcode, PTPPropertyValue* value, uint16_t datatype) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size, offset = 0; uint16_t ret; @@ -1997,7 +2269,7 @@ ptp_canon_get_directory (PTPParams* params, uint32_t **flags /* size(handles->n) */ ) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; uint16_t ret; PTP_CNT_INIT(ptp, PTP_OC_CANON_GetDirectory); @@ -2068,7 +2340,7 @@ ptp_canon_gettreesize (PTPParams* params, { PTPContainer ptp; uint16_t ret = PTP_RC_OK; - unsigned char *data, *cur; + unsigned char *data = NULL, *cur; unsigned int size, i; PTP_CNT_INIT(ptp, PTP_OC_CANON_GetTreeSize); @@ -2114,7 +2386,7 @@ uint16_t ptp_canon_checkevent (PTPParams* params, PTPContainer* event, int* isevent) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_CANON_CheckEvent); @@ -2137,6 +2409,304 @@ ptp_add_event (PTPParams *params, PTPContainer *evt) return PTP_RC_OK; } +/* CANON EOS fast directory mode */ +/* FIXME: incomplete ... needs storage mode retrieval support too (storage == 0xffffffff) */ +static uint16_t +ptp_list_folder_eos (PTPParams *params, uint32_t storage, uint32_t handle) { + unsigned int k, i, j, last, changed; + PTPCANONFolderEntry *tmp = NULL; + unsigned int nroftmp = 0; + uint16_t ret; + PTPStorageIDs storageids; + PTPObject *ob; + + if ((handle != 0xffffffff) && (handle != 0)) { + ret = ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED, &ob); + if ((ret == PTP_RC_OK) && (ob->flags & PTPOBJECT_DIRECTORY_LOADED)) + return PTP_RC_OK; + } + + if (storage == 0xffffffff) { + if (handle != 0xffffffff) + handle = 0xffffffff; + ret = ptp_getstorageids(params, &storageids); + if (ret != PTP_RC_OK) + return ret; + } else { + storageids.n = 1; + storageids.Storage = malloc(sizeof(storageids.Storage[0])); + storageids.Storage[0] = storage; + } + last = changed = 0; + + for (k=0;k<storageids.n;k++) { + if ((storageids.Storage[k] & 0xffff) == 0) { + ptp_debug (params, "reading directory, storage 0x%08x skipped (invalid)", storageids.Storage[k]); + continue; + } + ptp_debug (params, "reading handle %08x directory of 0x%08x", storageids.Storage[k], handle); + tmp = NULL; + ret = ptp_canon_eos_getobjectinfoex ( + params, storageids.Storage[k], handle ? handle : 0xffffffff, 0x100000, &tmp, &nroftmp); + if (ret != PTP_RC_OK) { + ptp_error (params, "error 0x%04x", ret); + free (storageids.Storage); + return ret; + } + /* convert read entries into objectinfos */ + for (i=0;i<nroftmp;i++) { + PTPObject *newobs; + + ob = NULL; + for (j=0;j<params->nrofobjects;j++) { + if (params->objects[(last+j)%params->nrofobjects].oid == tmp[i].ObjectHandle) { + ob = ¶ms->objects[(last+j)%params->nrofobjects]; + break; + } + } + if (j == params->nrofobjects) { + ptp_debug (params, "adding new objectid 0x%08x (nrofobs=%d,j=%d)", tmp[i].ObjectHandle, params->nrofobjects,j); + newobs = realloc (params->objects,sizeof(PTPObject)*(params->nrofobjects+1)); + if (!newobs) { + free (tmp); + return PTP_RC_GeneralError; + } + params->objects = newobs; + memset (¶ms->objects[params->nrofobjects],0,sizeof(params->objects[params->nrofobjects])); + params->objects[params->nrofobjects].oid = tmp[i].ObjectHandle; + params->objects[params->nrofobjects].flags = 0; + + params->objects[params->nrofobjects].oi.StorageID = storageids.Storage[k]; + params->objects[params->nrofobjects].flags |= PTPOBJECT_STORAGEID_LOADED; + if (handle == 0xffffffff) + params->objects[params->nrofobjects].oi.ParentObject = 0; + else + params->objects[params->nrofobjects].oi.ParentObject = handle; + params->objects[params->nrofobjects].flags |= PTPOBJECT_PARENTOBJECT_LOADED; + params->objects[params->nrofobjects].oi.Filename = strdup(tmp[i].Filename); + params->objects[params->nrofobjects].oi.ObjectFormat = tmp[i].ObjectFormatCode; + + ptp_debug (params, " flags %x", tmp[i].Flags); + if (tmp[i].Flags & 0x1) + params->objects[params->nrofobjects].oi.ProtectionStatus = PTP_PS_ReadOnly; + else + params->objects[params->nrofobjects].oi.ProtectionStatus = PTP_PS_NoProtection; + params->objects[params->nrofobjects].canon_flags = tmp[i].Flags; + params->objects[params->nrofobjects].oi.ObjectCompressedSize = tmp[i].ObjectSize; + params->objects[params->nrofobjects].oi.CaptureDate = tmp[i].Time; + params->objects[params->nrofobjects].oi.ModificationDate = tmp[i].Time; + params->objects[params->nrofobjects].flags |= PTPOBJECT_OBJECTINFO_LOADED; + + /*debug_objectinfo(params, tmp[i].ObjectHandle, ¶ms->objects[params->nrofobjects].oi);*/ + last = params->nrofobjects; + params->nrofobjects++; + changed = 1; + } else { + ptp_debug (params, "adding old objectid 0x%08x (nrofobs=%d,j=%d)", tmp[i].ObjectHandle, params->nrofobjects,j); + ob = ¶ms->objects[(last+j)%params->nrofobjects]; + /* for speeding up search */ + last = (last+j)%params->nrofobjects; + if (handle != PTP_HANDLER_SPECIAL) { + ob->oi.ParentObject = handle; + ob->flags |= PTPOBJECT_PARENTOBJECT_LOADED; + } + if (storageids.Storage[k] != PTP_HANDLER_SPECIAL) { + ob->oi.StorageID = storageids.Storage[k]; + ob->flags |= PTPOBJECT_STORAGEID_LOADED; + } + } + } + free (tmp); + } + if (changed) ptp_objects_sort (params); + + /* Do not cache ob, it might be reallocated and have a new address */ + if (handle != 0xffffffff) { + ret = ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED, &ob); + if (ret == PTP_RC_OK) + ob->flags |= PTPOBJECT_DIRECTORY_LOADED; + } + free (storageids.Storage); + return PTP_RC_OK; +} + +uint16_t +ptp_list_folder (PTPParams *params, uint32_t storage, uint32_t handle) { + unsigned int i, changed, last; + uint16_t ret; + uint32_t xhandle = handle; + PTPObject *newobs; + PTPObjectHandles handles; + + ptp_debug (params, "(storage=0x%08x, handle=0x%08x)", storage, handle); + /* handle=0 is only not read when there is no object in the list yet + * and we do the initial read. */ + if (!handle && params->nrofobjects) + return PTP_RC_OK; + /* but we can override this to read 0 object of storages */ + if (handle == PTP_HANDLER_SPECIAL) + handle = 0; + + /* Canon EOS Fast directory strategy */ + if ((params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) && + ptp_operation_issupported(params, PTP_OC_CANON_EOS_GetObjectInfoEx)) { + ret = ptp_list_folder_eos (params, storage, handle); + if (ret == PTP_RC_OK) + return ret; + } + + if (handle) { /* 0 is the virtual root */ + PTPObject *ob; + /* first check if object itself is loaded, and get its objectinfo. */ + ret = ptp_object_want (params, handle, PTPOBJECT_OBJECTINFO_LOADED, &ob); + if (ret != PTP_RC_OK) + return ret; + if (ob->oi.ObjectFormat != PTP_OFC_Association) + return PTP_RC_GeneralError; + if (ob->flags & PTPOBJECT_DIRECTORY_LOADED) return PTP_RC_OK; + ob->flags |= PTPOBJECT_DIRECTORY_LOADED; + /*debug_objectinfo(params, handle, &ob->oi);*/ + } + + if (ptp_operation_issupported(params, PTP_OC_GetFilesystemManifest)) { + uint64_t numoifs = 0; + PTPObjectFilesystemInfo *oifs = NULL; + + if (storage == PTP_HANDLER_SPECIAL) storage = 0; + ret = ptp_getfilesystemmanifest (params, storage, 0, handle, &numoifs, &oifs); + if (ret != PTP_RC_OK || !numoifs) + goto fallback; + + last = changed = 0; + for (i=0;i<numoifs;i++) { + PTPObject *ob; + unsigned int j; + + ob = NULL; + for (j=0;j<params->nrofobjects;j++) { + if (params->objects[(last+j)%params->nrofobjects].oid == oifs[i].ObjectHandle) { + ob = ¶ms->objects[(last+j)%params->nrofobjects]; + break; + } + } + if (j == params->nrofobjects) { + ptp_debug (params, "adding new objectid 0x%08x (nrofobs=%d,j=%d)", oifs[i].ObjectHandle, params->nrofobjects,j); + newobs = realloc (params->objects,sizeof(PTPObject)*(params->nrofobjects+1)); + if (!newobs) { + free (oifs); + return PTP_RC_GeneralError; + } + params->objects = newobs; + memset (¶ms->objects[params->nrofobjects],0,sizeof(params->objects[params->nrofobjects])); + params->objects[params->nrofobjects].oid = oifs[i].ObjectHandle; + params->objects[params->nrofobjects].flags = 0; + ob = ¶ms->objects[params->nrofobjects]; + params->nrofobjects++; + changed = 1; + } else { + ptp_debug (params, "adding old objectid 0x%08x (nrofobs=%d,j=%d)", oifs[i].ObjectHandle, params->nrofobjects,j); + ob = ¶ms->objects[(last+j)%params->nrofobjects]; + /* for speeding up search */ + last = (last+j)%params->nrofobjects; + } + + ob->oi.StorageID = oifs[i].StorageID; + ob->oi.ObjectFormat = oifs[i].ObjectFormat; + ob->oi.ProtectionStatus = oifs[i].ProtectionStatus; + ob->oi.ObjectCompressedSize = oifs[i].ObjectCompressedSize64; + ob->oi.ParentObject = oifs[i].ParentObject; + + /* bad iOS, returns StorageID instead of 0x0 */ + if (ob->oi.ParentObject == oifs[i].StorageID) { + ptp_debug (params, "objectid 0x%08x aka %s has parent %08x, rewriting to 0", oifs[i].ObjectHandle, oifs[i].Filename, oifs[i].ParentObject); + ob->oi.ParentObject = 0; + } + + ob->oi.AssociationType = oifs[i].AssociationType; + ob->oi.AssociationDesc = oifs[i].AssociationDesc; + ob->oi.SequenceNumber = oifs[i].SequenceNumber; + ob->oi.Filename = oifs[i].Filename; /* hand over memory ownership */ + ob->oi.ModificationDate = oifs[i].ModificationDate; + /* FIXME: most of it ... but not the image sizes */ + ob->flags |= PTPOBJECT_OBJECTINFO_LOADED|PTPOBJECT_STORAGEID_LOADED|PTPOBJECT_PARENTOBJECT_LOADED; + } + free (oifs); + if (changed) ptp_objects_sort (params); + return PTP_RC_OK; + } +fallback: + ptp_debug (params, "Listing ... "); + if (handle == 0) xhandle = PTP_HANDLER_SPECIAL; /* 0 would mean all */ + ret = ptp_getobjecthandles (params, storage, 0, xhandle, &handles); + if (ret == PTP_RC_ParameterNotSupported) {/* try without storage */ + storage = PTP_HANDLER_SPECIAL; + ret = ptp_getobjecthandles (params, PTP_HANDLER_SPECIAL, 0, xhandle, &handles); + } + if (ret == PTP_RC_ParameterNotSupported) { /* fall back to always supported method */ + xhandle = PTP_HANDLER_SPECIAL; + handle = PTP_HANDLER_SPECIAL; + ret = ptp_getobjecthandles (params, PTP_HANDLER_SPECIAL, 0, 0, &handles); + } + if (ret != PTP_RC_OK) + return ret; + last = changed = 0; + for (i=0;i<handles.n;i++) { + PTPObject *ob; + unsigned int j; + + ob = NULL; + for (j=0;j<params->nrofobjects;j++) { + if (params->objects[(last+j)%params->nrofobjects].oid == handles.Handler[i]) { + ob = ¶ms->objects[(last+j)%params->nrofobjects]; + break; + } + } + if (j == params->nrofobjects) { + ptp_debug (params, "adding new objectid 0x%08x (nrofobs=%d,j=%d)", handles.Handler[i], params->nrofobjects,j); + newobs = realloc (params->objects,sizeof(PTPObject)*(params->nrofobjects+1)); + if (!newobs) return PTP_RC_GeneralError; + params->objects = newobs; + memset (¶ms->objects[params->nrofobjects],0,sizeof(params->objects[params->nrofobjects])); + params->objects[params->nrofobjects].oid = handles.Handler[i]; + params->objects[params->nrofobjects].flags = 0; + /* root directory list files might return all files, so avoid tagging it */ + if (handle != PTP_HANDLER_SPECIAL && handle) { + ptp_debug (params, " parenthandle 0x%08x", handle); + if (handles.Handler[i] == handle) { /* EOS bug where oid == parent(oid) */ + params->objects[params->nrofobjects].oi.ParentObject = 0; + } else { + params->objects[params->nrofobjects].oi.ParentObject = handle; + } + params->objects[params->nrofobjects].flags |= PTPOBJECT_PARENTOBJECT_LOADED; + } + if (storage != PTP_HANDLER_SPECIAL) { + ptp_debug (params, " storage 0x%08x", storage); + params->objects[params->nrofobjects].oi.StorageID = storage; + params->objects[params->nrofobjects].flags |= PTPOBJECT_STORAGEID_LOADED; + } + params->nrofobjects++; + changed = 1; + } else { + ptp_debug (params, "adding old objectid 0x%08x (nrofobs=%d,j=%d)", handles.Handler[i], params->nrofobjects,j); + ob = ¶ms->objects[(last+j)%params->nrofobjects]; + /* for speeding up search */ + last = (last+j)%params->nrofobjects; + if (handle != PTP_HANDLER_SPECIAL) { + ob->oi.ParentObject = handle; + ob->flags |= PTPOBJECT_PARENTOBJECT_LOADED; + } + if (storage != PTP_HANDLER_SPECIAL) { + ob->oi.StorageID = storage; + ob->flags |= PTPOBJECT_STORAGEID_LOADED; + } + } + } + free (handles.Handler); + if (changed) ptp_objects_sort (params); + return PTP_RC_OK; +} + + static void handle_event_internal (PTPParams *params, PTPContainer *event) { @@ -2157,6 +2727,8 @@ handle_event_internal (PTPParams *params, PTPContainer *event) case PTP_EC_StoreRemoved: { int i; + /* FIXME: if we just remove 1 out of many storages, we do not need to invalidate/reload the entire tree? */ + /* refetch storage IDs and also invalidate whole object tree */ free (params->storageids.Storage); params->storageids.Storage = NULL; @@ -2172,6 +2744,20 @@ handle_event_internal (PTPParams *params, PTPContainer *event) params->nrofobjects = 0; params->storagechanged = 1; + /* mirror what we do in camera_init, fetch root directory entries. */ + if (params->deviceinfo.VendorExtensionID != PTP_VENDOR_SONY) + ptp_list_folder (params, PTP_HANDLER_SPECIAL, PTP_HANDLER_SPECIAL); + + { + unsigned int k; + + for (k=0;k<params->storageids.n;k++) { + if (!(params->storageids.Storage[k] & 0xffff)) continue; + if (params->storageids.Storage[k] == 0x80000001) continue; + ptp_list_folder (params, params->storageids.Storage[k], PTP_HANDLER_SPECIAL); + } + } + break; } default: /* check if we should handle it internally too */ @@ -2225,9 +2811,9 @@ ptp_check_event (PTPParams *params) params->events = realloc(params->events, sizeof(PTPContainer)*(evtcnt+params->nrofevents)); memcpy (¶ms->events[params->nrofevents],xevent,evtcnt*sizeof(PTPContainer)); params->nrofevents += evtcnt; - free (xevent); params->event90c7works = 1; } + free (xevent); if (params->event90c7works) return PTP_RC_OK; /* fall through to generic event handling */ @@ -2330,7 +2916,7 @@ uint16_t ptp_canon_eos_getevent (PTPParams* params, PTPCanon_changes_entry **entries, int *nrofentries) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetEvent); @@ -2420,7 +3006,7 @@ uint16_t ptp_canon_eos_getstorageids (PTPParams* params, PTPStorageIDs* storageids) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetStorageIDs); @@ -2447,7 +3033,7 @@ ptp_canon_eos_getobjectinfoex ( ) { PTPContainer ptp; uint16_t ret = PTP_RC_OK; - unsigned char *data, *xdata; + unsigned char *data = NULL, *xdata; unsigned int size, i; PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetObjectInfoEx, storageid, oid, unk); @@ -2476,16 +3062,35 @@ ptp_canon_eos_getobjectinfoex ( xdata = data+sizeof(uint32_t); for (i=0;i<*nrofentries;i++) { - if ((dtoh32a(xdata) + (xdata-data)) > size) { - ptp_debug (params, "reading canon FEs run over read data size?\n"); + unsigned int entrysize; + + if (4 + (xdata - data) > size) { + ptp_debug (params, "reading canon FEs run over read data size? (1)\n"); + free (*entries); + *entries = NULL; + *nrofentries = 0; + ret = PTP_RC_GeneralError; + goto exit; + } + entrysize = dtoh32a(xdata); + if ((entrysize + (xdata-data)) > size) { + ptp_debug (params, "reading canon FEs run over read data size? (2)\n"); + free (*entries); + *entries = NULL; + *nrofentries = 0; + ret = PTP_RC_GeneralError; + goto exit; + } + if (entrysize < 4 + 48 + 4) { + ptp_debug (params, "%d entry size %d does not match expected 56\n", i, entrysize); free (*entries); *entries = NULL; *nrofentries = 0; ret = PTP_RC_GeneralError; goto exit; } - ptp_unpack_Canon_EOS_FE (params, &xdata[4], &((*entries)[i])); - xdata += dtoh32a(xdata); + ptp_unpack_Canon_EOS_FE (params, &xdata[4], entrysize - 4, &((*entries)[i])); + xdata += entrysize; } exit: free (data); @@ -2517,6 +3122,33 @@ ptp_canon_eos_getpartialobject (PTPParams* params, uint32_t oid, uint32_t offset return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, NULL); } +/** + * ptp_canon_eos_getpartialobjectex: + * + * This retrieves a part of an PTP object which you specify as object id. + * The id originates from 0x9116 call. + * After finishing it, we seem to need to call ptp_canon_eos_enddirecttransfer. + * + * params: PTPParams* + * oid Object ID + * offset The offset where to start the data transfer + * xsize Size in bytes of the transfer to do + * data Pointer that receives the malloc()ed memory of the transfer. + * + * Return values: Some PTP_RC_* code. + * + */ +uint16_t +ptp_canon_eos_getpartialobjectex (PTPParams* params, uint32_t oid, uint32_t offset, uint32_t xsize, unsigned char**data) +{ + PTPContainer ptp; + +/* 5bf19091 00008001 00001000 00000000 */ +/* objectid offset size ? 64bit part ? */ + PTP_CNT_INIT(ptp, PTP_OC_CANON_EOS_GetPartialObjectEx, oid, offset, xsize, 0); + return ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, data, NULL); +} + uint16_t ptp_canon_eos_setdevicepropvalueex (PTPParams* params, unsigned char* data, unsigned int size) { @@ -2635,7 +3267,7 @@ ptp_canon_getpartialobject (PTPParams* params, uint32_t handle, { PTPContainer ptp; uint16_t ret; - unsigned char *data; + unsigned char *data = NULL; PTP_CNT_INIT(ptp, PTP_OC_CANON_GetPartialObjectEx, handle, offset, size, pos); ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL); @@ -2697,7 +3329,7 @@ uint16_t ptp_canon_getchanges (PTPParams* params, uint16_t** props, uint32_t* propnum) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_CANON_GetChanges); @@ -2737,7 +3369,7 @@ ptp_canon_getobjectinfo (PTPParams* params, uint32_t store, uint32_t p2, { PTPContainer ptp; uint16_t ret; - unsigned char *data; + unsigned char *data = NULL; unsigned int i, size; *entnum = 0; @@ -2858,7 +3490,7 @@ uint16_t ptp_sony_sdioconnect (PTPParams* params, uint32_t p1, uint32_t p2, uint32_t p3) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; PTP_CNT_INIT(ptp, PTP_OC_SONY_SDIOConnect, p1, p2, p3); CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, NULL)); @@ -2920,7 +3552,7 @@ uint16_t ptp_sony_getdevicepropdesc (PTPParams* params, uint16_t propcode, PTPDevicePropDesc *dpd) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size, len = 0; uint16_t ret; @@ -2937,7 +3569,7 @@ uint16_t ptp_sony_getalldevicepropdesc (PTPParams* params) { PTPContainer ptp; - unsigned char *data, *dpddata; + unsigned char *data = NULL, *dpddata; unsigned int size, readlen; PTPDevicePropDesc dpd; @@ -3351,7 +3983,7 @@ uint16_t ptp_nikon_check_event (PTPParams* params, PTPContainer** event, unsigned int* evtcnt) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_NIKON_CheckEvent); @@ -3398,7 +4030,7 @@ ptp_nikon_getwifiprofilelist (PTPParams* params) { PTPContainer ptp; uint16_t ret; - unsigned char *data; + unsigned char *data = NULL; unsigned int size, pos, profn, n; char *buffer; uint8_t len; @@ -3629,7 +4261,7 @@ ptp_mtp_getobjectpropdesc ( PTPParams* params, uint16_t opc, uint16_t ofc, PTPObjectPropDesc *opd ) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectPropDesc, opc, ofc); @@ -3658,7 +4290,7 @@ ptp_mtp_getobjectpropvalue ( ) { PTPContainer ptp; uint16_t ret = PTP_RC_OK; - unsigned char *data; + unsigned char *data = NULL; unsigned int size, offset = 0; PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectPropValue, oid, opc); @@ -3704,7 +4336,7 @@ uint16_t ptp_mtp_getobjectreferences (PTPParams* params, uint32_t handle, uint32_t** ohArray, uint32_t* arraylen) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjectReferences, handle); @@ -3740,7 +4372,7 @@ uint16_t ptp_mtp_getobjectproplist (PTPParams* params, uint32_t handle, MTPProperties **props, int *nrofprops) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjPropList, handle, @@ -3759,7 +4391,7 @@ uint16_t ptp_mtp_getobjectproplist_single (PTPParams* params, uint32_t handle, MTPProperties **props, int *nrofprops) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; unsigned int size; PTP_CNT_INIT(ptp, PTP_OC_MTP_GetObjPropList, handle, @@ -4017,7 +4649,7 @@ uint16_t ptp_chdk_read_script_msg(PTPParams* params, ptp_chdk_script_msg **msg) { PTPContainer ptp; - unsigned char *data; + unsigned char *data = NULL; PTP_CNT_INIT(ptp, PTP_OC_CHDK, PTP_CHDK_ReadScriptMsg); @@ -4066,7 +4698,29 @@ ptp_chdk_call_function(PTPParams* params, int *args, int size, int *ret) return PTP_RC_OK; } +uint16_t +ptp_chdk_parse_live_data (PTPParams* params, unsigned char *data, unsigned int data_size, + lv_data_header *header, + lv_framebuffer_desc *vpd, lv_framebuffer_desc *bmd +) { + int byte_w; + if (data_size < sizeof (*header)) + return PTP_ERROR_IO; + ptp_unpack_chdk_lv_data_header (params, data, header); + if (data_size < (header->vp_desc_start + sizeof (*vpd)) || data_size < (header->bm_desc_start + sizeof (*bmd))) + return PTP_ERROR_IO; + ptp_unpack_chdk_lv_framebuffer_desc (params, data+header->vp_desc_start, vpd); + ptp_unpack_chdk_lv_framebuffer_desc (params, data+header->vp_desc_start, bmd); + + /* The buffer_width field corresponds to the number of Y values in a row, + * so the actual number of bytes would be either one and a half times + * or (for Digic 6 cameras) twice so large */ + byte_w = (vpd->fb_type == LV_FB_YUV8) ? vpd->buffer_width * 1.5 : vpd->buffer_width * 2; + if (data_size < (vpd->data_start + (byte_w * vpd->visible_height))) + return PTP_ERROR_IO; + return PTP_RC_OK; +} /** @@ -4122,6 +4776,41 @@ ptp_android_sendpartialobject (PTPParams* params, uint32_t handle, uint64_t offs return ret; } +uint16_t +ptp_fuji_getevents (PTPParams* params, uint16_t** events, uint16_t* count) +{ + PTPContainer ptp; + unsigned char *data = NULL; + unsigned int size = 0; + + PTP_CNT_INIT(ptp, PTP_OC_GetDevicePropValue, 0xd212); + CHECK_PTP_RC(ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &data, &size)); + ptp_debug(params, "ptp_fuji_getevents"); + *count = 0; + if(size >= 2) + { + *count = dtoh16a(data); + ptp_debug(params, "event count: %d", *count); + *events = calloc(*count, sizeof(uint16_t)); + if(size >= 2 + *count * 6) + { + uint16_t param; + uint32_t value; + int i; + + for(i = 0; i < *count; i++) + { + param = dtoh16a(&data[2 + 6 * i]); + value = dtoh32a(&data[2 + 6 * i + 2]); + *events[i] = param; + ptp_debug(params, "param: %02x, value: %d ", param, value); + } + } + } + free(data); + return PTP_RC_OK; +} + /* Non PTP protocol functions */ /* devinfo testing functions */ @@ -4235,6 +4924,7 @@ static struct { {PTP_RC_CANON_BATTERY_LOW, PTP_VENDOR_CANON, N_("Battery Low")}, {PTP_RC_CANON_NOT_READY, PTP_VENDOR_CANON, N_("Camera Not Ready")}, + {PTP_ERROR_NODEVICE, 0, N_("PTP No Device")}, {PTP_ERROR_TIMEOUT, 0, N_("PTP Timeout")}, {PTP_ERROR_CANCEL, 0, N_("PTP Cancel Request")}, {PTP_ERROR_BADPARAM, 0, N_("PTP Invalid Parameter")}, @@ -5013,7 +5703,8 @@ ptp_get_property_description(PTPParams* params, uint16_t dpc) return (ptp_device_properties[i].txt); if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_MICROSOFT - || params->deviceinfo.VendorExtensionID==PTP_VENDOR_MTP) + || params->deviceinfo.VendorExtensionID==PTP_VENDOR_MTP + || params->deviceinfo.VendorExtensionID==PTP_VENDOR_PANASONIC) for (i=0; ptp_device_properties_MTP[i].txt!=NULL; i++) if (ptp_device_properties_MTP[i].dpc==dpc) return (ptp_device_properties_MTP[i].txt); @@ -5731,7 +6422,8 @@ ptp_render_property_value(PTPParams* params, uint16_t dpc, } } if (params->deviceinfo.VendorExtensionID==PTP_VENDOR_MICROSOFT - || params->deviceinfo.VendorExtensionID==PTP_VENDOR_MTP) { + || params->deviceinfo.VendorExtensionID==PTP_VENDOR_MTP + || params->deviceinfo.VendorExtensionID==PTP_VENDOR_PANASONIC) { switch (dpc) { case PTP_DPC_MTP_SynchronizationPartner: case PTP_DPC_MTP_DeviceFriendlyName: @@ -6204,6 +6896,26 @@ ptp_opcode_trans_t ptp_opcode_canon_trans[] = { {PTP_OC_CANON_EOS_CancelTransfer2,"PTP_OC_CANON_EOS_CancelTransfer2"}, {PTP_OC_CANON_EOS_FAPIMessageTX,"PTP_OC_CANON_EOS_FAPIMessageTX"}, {PTP_OC_CANON_EOS_FAPIMessageRX,"PTP_OC_CANON_EOS_FAPIMessageRX"}, + {PTP_OC_CANON_EOS_SetImageRecoveryData,"PTP_OC_CANON_EOS_SetImageRecoveryData"}, + {PTP_OC_CANON_EOS_GetImageRecoveryList,"PTP_OC_CANON_EOS_GetImageRecoveryList"}, + {PTP_OC_CANON_EOS_FormatImageRecoveryData,"PTP_OC_CANON_EOS_FormatImageRecoveryData"}, + {PTP_OC_CANON_EOS_GetPresetLensAdjustParam,"PTP_OC_CANON_EOS_GetPresetLensAdjustParam"}, + {PTP_OC_CANON_EOS_GetRawDispImage,"PTP_OC_CANON_EOS_GetRawDispImage"}, + {PTP_OC_CANON_EOS_SaveImageRecoveryData,"PTP_OC_CANON_EOS_SaveImageRecoveryData"}, + {PTP_OC_CANON_EOS_RequestBLE,"PTP_OC_CANON_EOS_RequestBLE"}, + {PTP_OC_CANON_EOS_DrivePowerZoom,"PTP_OC_CANON_EOS_DrivePowerZoom"}, + {PTP_OC_CANON_EOS_GetIptcData,"PTP_OC_CANON_EOS_GetIptcData"}, + {PTP_OC_CANON_EOS_SetIptcData,"PTP_OC_CANON_EOS_SetIptcData"}, + {PTP_OC_CANON_EOS_GetObjectInfo64,"PTP_OC_CANON_EOS_GetObjectInfo64"}, + {PTP_OC_CANON_EOS_GetObject64,"PTP_OC_CANON_EOS_GetObject64"}, + {PTP_OC_CANON_EOS_GetPartialObject64,"PTP_OC_CANON_EOS_GetPartialObject64"}, + {PTP_OC_CANON_EOS_GetObjectInfoEx64,"PTP_OC_CANON_EOS_GetObjectInfoEx64"}, + {PTP_OC_CANON_EOS_GetPartialObjectEX64,"PTP_OC_CANON_EOS_GetPartialObjectEX64"}, + {PTP_OC_CANON_EOS_CreateHandle64,"PTP_OC_CANON_EOS_CreateHandle64"}, + {PTP_OC_CANON_EOS_NotifyEstimateNumberofImport,"PTP_OC_CANON_EOS_NotifyEstimateNumberofImport"}, + {PTP_OC_CANON_EOS_NotifyNumberofImported,"PTP_OC_CANON_EOS_NotifyNumberofImported"}, + {PTP_OC_CANON_EOS_NotifySizeOfPartialDataTransfer,"PTP_OC_CANON_EOS_NotifySizeOfPartialDataTransfer"}, + {PTP_OC_CANON_EOS_NotifyFinish,"PTP_OC_CANON_EOS_NotifyFinish"}, }; ptp_opcode_trans_t ptp_opcode_sony_trans[] = { @@ -6251,6 +6963,7 @@ ptp_get_opcode_name(PTPParams* params, uint16_t opcode) switch (params->deviceinfo.VendorExtensionID) { case PTP_VENDOR_MICROSOFT: + case PTP_VENDOR_PANASONIC: case PTP_VENDOR_MTP: RETURN_NAME_FROM_TABLE(ptp_opcode_mtp_trans, opcode); case PTP_VENDOR_NIKON: RETURN_NAME_FROM_TABLE(ptp_opcode_nikon_trans, opcode); case PTP_VENDOR_CANON: RETURN_NAME_FROM_TABLE(ptp_opcode_canon_trans, opcode); @@ -6266,6 +6979,43 @@ ptp_get_opcode_name(PTPParams* params, uint16_t opcode) struct { + uint16_t code; + const char *name; +} ptp_event_codes[] = { + {PTP_EC_Undefined, "Undefined"}, + {PTP_EC_CancelTransaction, "CancelTransaction"}, + {PTP_EC_ObjectAdded, "ObjectAdded"}, + {PTP_EC_ObjectRemoved, "ObjectRemoved"}, + {PTP_EC_StoreAdded, "StoreAdded"}, + {PTP_EC_StoreRemoved, "StoreRemoved"}, + {PTP_EC_DevicePropChanged, "DevicePropChanged"}, + {PTP_EC_ObjectInfoChanged, "ObjectInfoChanged"}, + {PTP_EC_DeviceInfoChanged, "DeviceInfoChanged"}, + {PTP_EC_RequestObjectTransfer, "RequestObjectTransfer"}, + {PTP_EC_StoreFull, "StoreFull"}, + {PTP_EC_DeviceReset, "DeviceReset"}, + {PTP_EC_StorageInfoChanged, "StorageInfoChanged"}, + {PTP_EC_CaptureComplete, "CaptureComplete"}, + {PTP_EC_UnreportedStatus, "UnreportedStatus"}, + + {PTP_EC_MTP_ObjectPropChanged, "ObjectPropChanged"}, + {PTP_EC_MTP_ObjectPropDescChanged, "ObjectPropDescChanged"}, + {PTP_EC_MTP_ObjectReferencesChanged, "ObjectReferencesChanged"}, +}; + + +const char* +ptp_get_event_code_name(PTPParams* params, uint16_t event_code) +{ + unsigned int i; + for (i=0; i<sizeof(ptp_event_codes)/sizeof(ptp_event_codes[0]); i++) + if (event_code == ptp_event_codes[i].code) + return _(ptp_event_codes[i].name); + return _("Unknown Event"); +} + + +struct { uint16_t id; const char *name; } ptp_opc_trans[] = { @@ -6674,13 +7424,22 @@ ptp_object_want (PTPParams *params, uint32_t handle, unsigned int want, PTPObjec return ret; } if (!ob->oi.Filename) ob->oi.Filename=strdup("<none>"); - if (ob->flags & PTPOBJECT_PARENTOBJECT_LOADED) + if (ob->flags & PTPOBJECT_PARENTOBJECT_LOADED) { + if (ob->oi.ParentObject != saveparent) + ptp_debug (params, "saved parent %08x is not the same as read via getobjectinfo %08x", ob->oi.ParentObject, saveparent); ob->oi.ParentObject = saveparent; + } /* Second EOS issue, 0x20000000 has 0x20000000 as parent */ if (ob->oi.ParentObject == handle) ob->oi.ParentObject = 0; + /* Apple iOS X does that for the root folder. */ + if (ob->oi.ParentObject == ob->oi.StorageID) { + ptp_debug (params, "parent %08x of %s has same id as storage id. rewriting to 0.", ob->oi.ParentObject, ob->oi.Filename); + ob->oi.ParentObject = 0; + } + /* Read out the canon special flags */ if ((params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) && ptp_operation_issupported(params,PTP_OC_CANON_GetObjectInfoEx)) { @@ -6745,10 +7504,7 @@ ptp_object_want (PTPParams *params, uint32_t handle, unsigned int want, PTPObjec break; case PTP_OPC_ObjectSize: if (prop->datatype == PTP_DTC_UINT64) { - if (prop->propval.u64 > 0xFFFFFFFFU) - ob->oi.ObjectCompressedSize = 0xFFFFFFFFU; - else - ob->oi.ObjectCompressedSize = (uint32_t)prop->propval.u64; + ob->oi.ObjectCompressedSize = prop->propval.u64; } else if (prop->datatype == PTP_DTC_UINT32) { ob->oi.ObjectCompressedSize = prop->propval.u32; } |