aboutsummaryrefslogtreecommitdiff
path: root/src/ptp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ptp.c')
-rw-r--r--src/ptp.c858
1 files changed, 807 insertions, 51 deletions
diff --git a/src/ptp.c b/src/ptp.c
index 536160d..d66c8f2 100644
--- a/src/ptp.c
+++ b/src/ptp.c
@@ -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 = &params->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 (&params->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, &params->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 = &params->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 = &params->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 (&params->objects[params->nrofobjects],0,sizeof(params->objects[params->nrofobjects]));
+ params->objects[params->nrofobjects].oid = oifs[i].ObjectHandle;
+ params->objects[params->nrofobjects].flags = 0;
+ ob = &params->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 = &params->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 = &params->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 (&params->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 = &params->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 (&params->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;
}