Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Unified Diff: src/ptp-pack.c

Issue 2345493002: Uprev libmtp to 1.1.12 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/libmtp@master
Patch Set: Re-upload cl Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ptp.c ('k') | src/util.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ptp-pack.c
diff --git a/src/ptp-pack.c b/src/ptp-pack.c
index 5bf90e095b923c366bcfd36b81ae8c456b091edf..ea6bfc92fba5fef79fd1d628c4b3d324824e6084 100644
--- a/src/ptp-pack.c
+++ b/src/ptp-pack.c
@@ -1,7 +1,7 @@
/* ptp-pack.c
*
* Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
- * Copyright (C) 2003-2012 Marcus Meissner <marcus@jet.franken.de>
+ * Copyright (C) 2003-2014 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>
@@ -18,13 +18,19 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
*/
/* currently this file is included into ptp.c */
-#ifdef HAVE_ICONV
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef UINT_MAX
+# define UINT_MAX 0xFFFFFFFF
+#endif
+#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
#include <iconv.h>
#endif
@@ -146,7 +152,7 @@ ptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8
dest = loclstr;
destlen = sizeof(loclstr)-1;
nconv = (size_t)-1;
-#ifdef HAVE_ICONV
+#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
if (params->cd_ucs2_to_locale != (iconv_t)-1)
nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen, &dest, &destlen);
#endif
@@ -187,7 +193,7 @@ ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t o
/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
memset(ucs2strp, 0, sizeof(ucs2str)); /* XXX: necessary? */
-#ifdef HAVE_ICONV
+#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
if (params->cd_locale_to_ucs2 != (iconv_t)-1) {
size_t nconv;
size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
@@ -200,7 +206,8 @@ ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t o
} else
#endif
{
- int i;
+ unsigned int i;
+
for (i=0;i<convlen;i++) {
ucs2str[i] = string[i];
}
@@ -251,16 +258,31 @@ ptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size
}
static inline uint32_t
-ptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
+ptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint32_t **array)
{
uint32_t n, i=0;
+ if (offset >= datalen)
+ return 0;
+
+ if (offset + sizeof(uint32_t) > datalen)
+ return 0;
+
+ *array = NULL;
n=dtoh32a(&data[offset]);
+ if (n >= UINT_MAX/sizeof(uint32_t))
+ return 0;
+ if (!n)
+ return 0;
+
+ if (offset + sizeof(uint32_t)*(n+1) > datalen) {
+ ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)*(n+1) , datalen);
+ return 0;
+ }
+
*array = malloc (n*sizeof(uint32_t));
- while (n>i) {
+ for (i=0;i<n;i++)
(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
- i++;
- }
return n;
}
@@ -277,16 +299,25 @@ ptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, u
}
static inline uint32_t
-ptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
+ptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint16_t **array)
{
uint32_t n, i=0;
+ *array = NULL;
n=dtoh32a(&data[offset]);
+ if (n >= UINT_MAX/sizeof(uint16_t))
+ return 0;
+ if (!n)
+ return 0;
+ if (offset + sizeof(uint32_t) > datalen)
+ return 0;
+ if (offset + sizeof(uint32_t)+sizeof(uint16_t)*n > datalen) {
+ ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)+n*sizeof(uint16_t) , datalen);
+ return 0;
+ }
*array = malloc (n*sizeof(uint16_t));
- while (n>i) {
+ for (i=0;i<n;i++)
(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
- i++;
- }
return n;
}
@@ -320,23 +351,28 @@ ptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsign
dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
PTP_di_OperationsSupported+totallen,
+ datalen,
&di->OperationsSupported);
totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
PTP_di_OperationsSupported+totallen,
+ datalen,
&di->EventsSupported);
totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
di->DevicePropertiesSupported_len =
ptp_unpack_uint16_t_array(params, data,
PTP_di_OperationsSupported+totallen,
+ datalen,
&di->DevicePropertiesSupported);
totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
PTP_di_OperationsSupported+totallen,
+ datalen,
&di->CaptureFormats);
totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
PTP_di_OperationsSupported+totallen,
+ datalen,
&di->ImageFormats);
totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
di->Manufacturer = ptp_unpack_string(params, data,
@@ -356,44 +392,44 @@ ptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsign
&len);
}
-static void inline
+inline static void
ptp_free_DI (PTPDeviceInfo *di) {
- if (di->SerialNumber) free (di->SerialNumber);
- if (di->DeviceVersion) free (di->DeviceVersion);
- if (di->Model) free (di->Model);
- if (di->Manufacturer) free (di->Manufacturer);
- if (di->ImageFormats) free (di->ImageFormats);
- if (di->CaptureFormats) free (di->CaptureFormats);
- if (di->VendorExtensionDesc) free (di->VendorExtensionDesc);
- if (di->OperationsSupported) free (di->OperationsSupported);
- if (di->EventsSupported) free (di->EventsSupported);
- if (di->DevicePropertiesSupported) free (di->DevicePropertiesSupported);
+ free (di->SerialNumber);
+ free (di->DeviceVersion);
+ free (di->Model);
+ free (di->Manufacturer);
+ free (di->ImageFormats);
+ free (di->CaptureFormats);
+ free (di->VendorExtensionDesc);
+ free (di->OperationsSupported);
+ free (di->EventsSupported);
+ free (di->DevicePropertiesSupported);
}
/* EOS Device Info unpack */
static inline void
ptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
{
- int totallen = 4;
+ unsigned int totallen = 4;
memset (di,0, sizeof(*di));
if (datalen < 8) return;
/* uint32_t struct len - ignore */
di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
- totallen, &di->EventsSupported);
+ totallen, datalen, &di->EventsSupported);
if (!di->EventsSupported) return;
totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
if (totallen >= datalen) return;
di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
- totallen, &di->DevicePropertiesSupported);
+ totallen, datalen, &di->DevicePropertiesSupported);
if (!di->DevicePropertiesSupported) return;
totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
if (totallen >= datalen) return;
di->unk_len = ptp_unpack_uint32_t_array(params, data,
- totallen, &di->unk);
+ totallen, datalen, &di->unk);
if (!di->unk) return;
totallen += di->unk_len*sizeof(uint32_t)+4;
return;
@@ -415,7 +451,7 @@ static inline void
ptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
{
if (len) {
- oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
+ oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, len, &oh->Handler);
} else {
oh->n = 0;
oh->Handler = NULL;
@@ -429,13 +465,12 @@ ptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, uns
static inline void
ptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
{
- if (!data && !len) {
+ if (!data || !len) {
sids->n = 0;
sids->Storage = NULL;
return;
}
- sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
- &sids->Storage);
+ sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids, len, &sids->Storage);
}
/* StorageInfo pack/unpack */
@@ -453,12 +488,15 @@ ptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsig
{
uint8_t storagedescriptionlen;
+ if (len < 26) return;
si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
+
+ /* FIXME: check more lengths here */
si->StorageDescription=ptp_unpack_string(params, data,
PTP_si_StorageDescription, &storagedescriptionlen);
si->VolumeLabel=ptp_unpack_string(params, data,
@@ -604,6 +642,12 @@ ptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsign
uint8_t capturedatelen;
char *capture_date;
+ if (len < PTP_oi_SequenceNumber)
+ return;
+
+ oi->Filename = oi->Keywords = NULL;
+
+ /* FIXME: also handle length with all the strings at the end */
oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
@@ -653,12 +697,14 @@ ptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsign
}
#define RARR(val,member,func) { \
- int n,j; \
+ unsigned int n,j; \
if (total - *offset < sizeof(uint32_t)) \
return 0; \
n = dtoh32a (&data[*offset]); \
*offset += sizeof(uint32_t); \
\
+ if (n >= UINT_MAX/sizeof(val->a.v[0])) \
+ return 0; \
val->a.count = n; \
val->a.v = malloc(sizeof(val->a.v[0])*n); \
if (!val->a.v) return 0; \
@@ -666,9 +712,9 @@ ptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsign
CTVAL(val->a.v[j].member, func); \
}
-static inline int
+static inline unsigned int
ptp_unpack_DPV (
- PTPParams *params, unsigned char* data, int *offset, int total,
+ PTPParams *params, unsigned char* data, unsigned int *offset, unsigned int total,
PTPPropertyValue* value, uint16_t datatype
) {
switch (datatype) {
@@ -750,7 +796,6 @@ ptp_unpack_DPV (
}
/* Device Property pack/unpack */
-
#define PTP_dpd_DevicePropertyCode 0
#define PTP_dpd_DataType 2
#define PTP_dpd_GetSet 4
@@ -759,7 +804,7 @@ ptp_unpack_DPV (
static inline int
ptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
{
- int offset=0, ret;
+ unsigned int offset = 0, ret;
memset (dpd, 0, sizeof(*dpd));
dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
@@ -829,7 +874,163 @@ outofmemory:
return 0;
}
-/* (MTP) Object Property pack/unpack */
+/* Device Property pack/unpack */
+#define PTP_dpd_Sony_DevicePropertyCode 0
+#define PTP_dpd_Sony_DataType 2
+#define PTP_dpd_Sony_GetSet 4
+#define PTP_dpd_Sony_Unknown 5
+#define PTP_dpd_Sony_FactoryDefaultValue 6
+
+static inline int
+ptp_unpack_Sony_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen, unsigned int *poffset)
+{
+ unsigned int ret;
+#if 0
+ unsigned int unk1, unk2;
+#endif
+
+ memset (dpd, 0, sizeof(*dpd));
+ dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_Sony_DevicePropertyCode]);
+ dpd->DataType=dtoh16a(&data[PTP_dpd_Sony_DataType]);
+
+#if 0
+ /* get set ? */
+ unk1 = dtoh8a(&data[PTP_dpd_Sony_GetSet]);
+ unk2 = dtoh8a(&data[PTP_dpd_Sony_Unknown]);
+ ptp_debug (params, "prop 0x%04x, datatype 0x%04x, unk1 %d unk2 %d", dpd->DevicePropertyCode, dpd->DataType, unk1, unk2);
+#endif
+ dpd->GetSet=1;
+
+ dpd->FormFlag=PTP_DPFF_None;
+
+ *poffset = PTP_dpd_Sony_FactoryDefaultValue;
+ ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
+ if (!ret) goto outofmemory;
+ if ((dpd->DataType == PTP_DTC_STR) && (*poffset == dpdlen))
+ return 1;
+ ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->CurrentValue, dpd->DataType);
+ if (!ret) goto outofmemory;
+
+ /* if offset==0 then Data Type format is not supported by this
+ code or the Data Type is a string (with two empty strings as
+ values). In both cases Form Flag should be set to 0x00 and FORM is
+ not present. */
+
+ if (*poffset==PTP_dpd_Sony_FactoryDefaultValue)
+ return 1;
+
+ dpd->FormFlag=dtoh8a(&data[*poffset]);
+ *poffset+=sizeof(uint8_t);
+
+ switch (dpd->FormFlag) {
+ case PTP_DPFF_Range:
+ ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
+ if (!ret) goto outofmemory;
+ ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
+ if (!ret) goto outofmemory;
+ ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
+ if (!ret) goto outofmemory;
+ break;
+ case PTP_DPFF_Enumeration: {
+ int i;
+#define N dpd->FORM.Enum.NumberOfValues
+ N = dtoh16a(&data[*poffset]);
+ *poffset+=sizeof(uint16_t);
+ dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
+ if (!dpd->FORM.Enum.SupportedValue)
+ goto outofmemory;
+
+ memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
+ for (i=0;i<N;i++) {
+ ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
+
+ /* Slightly different handling here. The HP PhotoSmart 120
+ * specifies an enumeration with N in wrong endian
+ * 00 01 instead of 01 00, so we count the enum just until the
+ * the end of the packet.
+ */
+ if (!ret) {
+ if (!i)
+ goto outofmemory;
+ dpd->FORM.Enum.NumberOfValues = i;
+ break;
+ }
+ }
+ }
+ }
+#undef N
+ return 1;
+outofmemory:
+ ptp_free_devicepropdesc(dpd);
+ return 0;
+}
+
+static inline void
+duplicate_PropertyValue (const PTPPropertyValue *src, PTPPropertyValue *dst, uint16_t type) {
+ if (type == PTP_DTC_STR) {
+ if (src->str)
+ dst->str = strdup(src->str);
+ else
+ dst->str = NULL;
+ return;
+ }
+
+ if (type & PTP_DTC_ARRAY_MASK) {
+ unsigned int i;
+
+ dst->a.count = src->a.count;
+ dst->a.v = malloc (sizeof(src->a.v[0])*src->a.count);
+ for (i=0;i<src->a.count;i++)
+ duplicate_PropertyValue (&src->a.v[i], &dst->a.v[i], type & ~PTP_DTC_ARRAY_MASK);
+ return;
+ }
+ switch (type & ~PTP_DTC_ARRAY_MASK) {
+ case PTP_DTC_INT8: dst->i8 = src->i8; break;
+ case PTP_DTC_UINT8: dst->u8 = src->u8; break;
+ case PTP_DTC_INT16: dst->i16 = src->i16; break;
+ case PTP_DTC_UINT16: dst->u16 = src->u16; break;
+ case PTP_DTC_INT32: dst->i32 = src->i32; break;
+ case PTP_DTC_UINT32: dst->u32 = src->u32; break;
+ case PTP_DTC_UINT64: dst->u64 = src->u64; break;
+ case PTP_DTC_INT64: dst->i64 = src->i64; break;
+#if 0
+ case PTP_DTC_INT128: dst->i128 = src->i128; break;
+ case PTP_DTC_UINT128: dst->u128 = src->u128; break;
+#endif
+ default: break;
+ }
+ return;
+}
+
+static inline void
+duplicate_DevicePropDesc(const PTPDevicePropDesc *src, PTPDevicePropDesc *dst) {
+ int i;
+
+ dst->DevicePropertyCode = src->DevicePropertyCode;
+ dst->DataType = src->DataType;
+ dst->GetSet = src->GetSet;
+
+ duplicate_PropertyValue (&src->FactoryDefaultValue, &dst->FactoryDefaultValue, src->DataType);
+ duplicate_PropertyValue (&src->CurrentValue, &dst->CurrentValue, src->DataType);
+
+ dst->FormFlag = src->FormFlag;
+ switch (src->FormFlag) {
+ case PTP_DPFF_Range:
+ duplicate_PropertyValue (&src->FORM.Range.MinimumValue, &dst->FORM.Range.MinimumValue, src->DataType);
+ duplicate_PropertyValue (&src->FORM.Range.MaximumValue, &dst->FORM.Range.MaximumValue, src->DataType);
+ duplicate_PropertyValue (&src->FORM.Range.StepSize, &dst->FORM.Range.StepSize, src->DataType);
+ break;
+ case PTP_DPFF_Enumeration:
+ dst->FORM.Enum.NumberOfValues = src->FORM.Enum.NumberOfValues;
+ dst->FORM.Enum.SupportedValue = malloc (sizeof(dst->FORM.Enum.SupportedValue[0])*src->FORM.Enum.NumberOfValues);
+ for (i = 0; i<src->FORM.Enum.NumberOfValues ; i++)
+ duplicate_PropertyValue (&src->FORM.Enum.SupportedValue[i], &dst->FORM.Enum.SupportedValue[i], src->DataType);
+ break;
+ case PTP_DPFF_None:
+ break;
+ }
+}
+
#define PTP_opd_ObjectPropertyCode 0
#define PTP_opd_DataType 2
#define PTP_opd_GetSet 4
@@ -838,7 +1039,7 @@ outofmemory:
static inline int
ptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
{
- int offset=0, ret;
+ unsigned int offset=0, ret;
memset (opd, 0, sizeof(*opd));
opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
@@ -865,7 +1066,7 @@ ptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd,
if (!ret) goto outofmemory;
break;
case PTP_OPFF_Enumeration: {
- int i;
+ unsigned int i;
#define N opd->FORM.Enum.NumberOfValues
N = dtoh16a(&data[offset]);
offset+=sizeof(uint16_t);
@@ -904,7 +1105,7 @@ ptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr
{
unsigned char* dpv=NULL;
uint32_t size=0;
- int i;
+ unsigned int i;
switch (datatype) {
case PTP_DTC_INT8:
@@ -1085,7 +1286,7 @@ ptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops,
{
uint32_t prop_count = dtoh32a(data);
MTPProperties *props = NULL;
- int offset = 0, i;
+ unsigned int offset = 0, i;
if (prop_count == 0) {
*pprops = NULL;
@@ -1143,13 +1344,18 @@ ptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops,
static inline void
ptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
{
- int length;
+ unsigned int length;
int type;
if (data==NULL)
return;
memset(ec,0,sizeof(*ec));
+
length=dtoh32a(&data[PTP_ec_Length]);
+ if (length > len) {
+ ptp_debug (params, "length %d in container, but data only %d bytes?!", length, len);
+ return;
+ }
type = dtoh16a(&data[PTP_ec_Type]);
ec->Code=dtoh16a(&data[PTP_ec_Code]);
@@ -1240,7 +1446,8 @@ ObjectInfo for 'IMG_0199.JPG':
0014 72 0c 74 92 OID
0018 01 00 02 00 StorageID
001c 01 38 00 00 OFC
-0020 00 00 00 00 00 00 00 00 ?
+0020 00 00 00 00 ??
+0024 21 00 00 00 flags (4 bytes? 1 byte?)
0028 19 d5 21 00 Size
002c 00 00 74 92 ?
0030 70 0c 74 92 OID
@@ -1253,7 +1460,7 @@ ObjectInfo for 'IMG_0199.JPG':
#define PTP_cefe_ObjectHandle 0
#define PTP_cefe_StorageID 4
#define PTP_cefe_ObjectFormatCode 8
-#define PTP_cefe_Flags 12
+#define PTP_cefe_Flags 16
#define PTP_cefe_ObjectSize 20
#define PTP_cefe_Filename 32
#define PTP_cefe_Time 48
@@ -1372,12 +1579,98 @@ ptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value
return s;
}
+/* 00: 32 bit size
+ * 04: 16 bit subsize
+ * 08: 16 bit version (?)
+ * 0c: 16 bit focus_points_in_struct
+ * 10: 16 bit focus_points_in_use
+ * 14: variable arrays:
+ * 16 bit sizex, 16 bit sizey
+ * 16 bit othersizex, 16 bit othersizey
+ * 16 bit array height[focus_points_in_struct]
+ * 16 bit array width[focus_points_in_struct]
+ * 16 bit array offsetheight[focus_points_in_struct] middle is 0
+ * 16 bit array offsetwidth[focus_points_in_struct] middle is ?
+ * bitfield of selected focus points, starting with 0 [size focus_points_in_struct in bits]
+ * unknown stuff , likely which are active
+ * 16 bit 0xffff
+ *
+ * size=NxN,size2=NxN,points={NxNxNxN,NxNxNxN,...},selected={0,1,2}
+ */
+static inline char*
+ptp_unpack_EOS_FocusInfoEx (PTPParams* params, unsigned char** data )
+{
+ uint32_t size = dtoh32a( *data );
+ uint32_t halfsize = dtoh16a( (*data) + 4);
+ uint32_t version = dtoh16a( (*data) + 6);
+ uint32_t focus_points_in_struct = dtoh16a( (*data) + 8);
+ uint32_t focus_points_in_use = dtoh16a( (*data) + 10);
+ uint32_t sizeX = dtoh16a( (*data) + 12);
+ uint32_t sizeY = dtoh16a( (*data) + 14);
+ uint32_t size2X = dtoh16a( (*data) + 16);
+ uint32_t size2Y = dtoh16a( (*data) + 18);
+ uint32_t i;
+ uint32_t maxlen;
+ char *str, *p;
+
+ /* every focuspoint gets 4 (16 bit number and a x) and a ,*/
+ /* inital things around lets say 100 chars at most.
+ * FIXME: check selected when we decode it */
+ maxlen = focus_points_in_use*6*4 + focus_points_in_use + 100;
+ if (halfsize != size-4) {
+ ptp_error(params, "halfsize %d is not expected %d", halfsize, size-4);
+ return "bad size";
+ }
+ if (20 + focus_points_in_struct*8 + (focus_points_in_struct+7)/8 > size) {
+ ptp_error(params, "size %d is too large for fp in struct %d", focus_points_in_struct*8 + 20 + (focus_points_in_struct+7)/8, size);
+ return "bad size 2";
+ }
+#if 0
+ ptp_debug(params,"d1d3 content:");
+ for (i=0;i<size;i+=2)
+ ptp_debug(params,"%d: %02x %02x", i, (*data)[i], (*data)[i+1]);
+#endif
+ ptp_debug(params,"d1d3 version", version);
+ ptp_debug(params,"d1d3 focus points in struct %d, in use %d", focus_points_in_struct, focus_points_in_use);
+
+ str = (char*)malloc( maxlen );
+ if (!str)
+ return NULL;
+ p = str;
+
+ p += sprintf(p,"eosversion=%d,size=%dx%d,size2=%dx%d,points={", version, sizeX, sizeY, size2X, size2Y);
+ for (i=0;i<focus_points_in_use;i++) {
+ int16_t x = dtoh16a((*data) + focus_points_in_struct*4 + 20 + 2*i);
+ int16_t y = dtoh16a((*data) + focus_points_in_struct*6 + 20 + 2*i);
+ int16_t w = dtoh16a((*data) + focus_points_in_struct*2 + 20 + 2*i);
+ int16_t h = dtoh16a((*data) + focus_points_in_struct*0 + 20 + 2*i);
+
+ p += sprintf(p,"{%d,%d,%d,%d}",x,y,w,h);
+
+ if (i<focus_points_in_use-1)
+ p += sprintf(p,",");
+ }
+ p += sprintf(p,"},select={");
+ for (i=0;i<focus_points_in_use;i++) {
+ if ((1<<(i%7)) & ((*data)[focus_points_in_struct*8+20+i/8]))
+ p+=sprintf(p,"%d,", i);
+ }
+
+ p += sprintf(p,"},unknown={");
+ for (i=focus_points_in_struct*8+(focus_points_in_struct+7)/8+20;i<size;i++) {
+ p+=sprintf(p,"%02x", (*data)[i]);
+ }
+ p += sprintf(p,"}");
+ return str;
+}
+
+
static inline char*
ptp_unpack_EOS_CustomFuncEx (PTPParams* params, unsigned char** data )
{
uint32_t s = dtoh32a( *data );
uint32_t n = s/4, i;
- char* str = (char*)malloc( s ); // n is size in uint32, average len(itoa(i)) < 4 -> alloc n chars
+ char* str = (char*)malloc( s*2+s/4+1 ); /* n is size in uint32, maximum %x len is 8 chars and \0*/
if (!str)
return str;
char* p = str;
@@ -1400,7 +1693,7 @@ ptp_pack_EOS_CustomFuncEx (PTPParams* params, unsigned char* data, char* str)
for (i=0; i<n; i++)
{
v = strtoul(str, &str, 16);
- str++; // skip the ',' delimiter
+ str++; /* skip the ',' delimiter */
htod32a(data + i*4, v);
}
@@ -1433,11 +1726,38 @@ ptp_pack_EOS_CustomFuncEx (PTPParams* params, unsigned char* data, char* str)
#define PTP_ece_OA_Parent 0x20
#define PTP_ece_OA_Name 0x28
+static PTPDevicePropDesc*
+_lookup_or_allocate_canon_prop(PTPParams *params, uint16_t proptype)
+{
+ unsigned int j;
+
+ for (j=0;j<params->nrofcanon_props;j++)
+ if (params->canon_props[j].proptype == proptype)
+ break;
+ if (j<params->nrofcanon_props)
+ return &params->canon_props[j].dpd;
+
+ if (j)
+ params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
+ else
+ params->canon_props = malloc(sizeof(params->canon_props[0]));
+ params->canon_props[j].proptype = proptype;
+ params->canon_props[j].size = 0;
+ params->canon_props[j].data = NULL;
+ memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
+ params->canon_props[j].dpd.GetSet = 1;
+ params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
+ params->nrofcanon_props = j+1;
+ return &params->canon_props[j].dpd;
+}
+
+
static inline int
-ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **ce)
+ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **pce)
{
int i = 0, entries = 0;
unsigned char *curdata = data;
+ PTPCanon_changes_entry *ce;
if (data==NULL)
return 0;
@@ -1445,49 +1765,56 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
uint32_t size = dtoh32a(&curdata[PTP_ece_Size]);
uint32_t type = dtoh32a(&curdata[PTP_ece_Type]);
- curdata += size;
if ((size == 8) && (type == 0))
break;
+ if (type == PTP_EC_CANON_EOS_OLCInfoChanged) {
+ unsigned int j;
+
+ for (j=0;j<31;j++)
+ if (dtoh32a(curdata+12) & (1<<j))
+ entries++;
+ }
+ curdata += size;
entries++;
}
- *ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
- if (!*ce) return 0;
+ ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
+ if (!ce) return 0;
curdata = data;
while (curdata - data < datasize) {
uint32_t size = dtoh32a(&curdata[PTP_ece_Size]);
uint32_t type = dtoh32a(&curdata[PTP_ece_Type]);
- (*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
- (*ce)[i].u.info = NULL;
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = NULL;
switch (type) {
case PTP_EC_CANON_EOS_ObjectAddedEx:
- (*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
- (*ce)[i].u.object.oid = dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
- (*ce)[i].u.object.oi.StorageID = dtoh32a(&curdata[PTP_ece_OA_StorageID]);
- (*ce)[i].u.object.oi.ParentObject = dtoh32a(&curdata[PTP_ece_OA_Parent]);
- (*ce)[i].u.object.oi.ObjectFormat = dtoh16a(&curdata[PTP_ece_OA_OFC]);
- (*ce)[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
- (*ce)[i].u.object.oi.Filename = strdup(((char*)&curdata[PTP_ece_OA_Name]));
- ptp_debug (params, "event %d: objectinfo added oid %08lx, parent %08lx, ofc %04x, size %d, filename %s", i, (*ce)[i].u.object.oid, (*ce)[i].u.object.oi.ParentObject, (*ce)[i].u.object.oi.ObjectFormat, (*ce)[i].u.object.oi.ObjectCompressedSize, (*ce)[i].u.object.oi.Filename);
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
+ ce[i].u.object.oid = dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
+ ce[i].u.object.oi.StorageID = dtoh32a(&curdata[PTP_ece_OA_StorageID]);
+ ce[i].u.object.oi.ParentObject = dtoh32a(&curdata[PTP_ece_OA_Parent]);
+ ce[i].u.object.oi.ObjectFormat = dtoh16a(&curdata[PTP_ece_OA_OFC]);
+ ce[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
+ ce[i].u.object.oi.Filename = strdup(((char*)&curdata[PTP_ece_OA_Name]));
+ ptp_debug (params, "event %d: objectinfo added oid %08lx, parent %08lx, ofc %04x, size %d, filename %s", i, ce[i].u.object.oid, ce[i].u.object.oi.ParentObject, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename);
break;
case PTP_EC_CANON_EOS_RequestObjectTransfer:
- (*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
- (*ce)[i].u.object.oid = dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
- (*ce)[i].u.object.oi.StorageID = 0; /* use as marker */
- (*ce)[i].u.object.oi.ObjectFormat = dtoh16a(&curdata[PTP_ece_OI_OFC]);
- (*ce)[i].u.object.oi.ParentObject = 0; /* check, but use as marker */
- (*ce)[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
- (*ce)[i].u.object.oi.Filename = strdup(((char*)&curdata[PTP_ece_OI_Name]));
-
- ptp_debug (params, "event %d: request object transfer oid %08lx, ofc %04x, size %d, filename %s", i, (*ce)[i].u.object.oid, (*ce)[i].u.object.oi.ObjectFormat, (*ce)[i].u.object.oi.ObjectCompressedSize, (*ce)[i].u.object.oi.Filename);
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
+ ce[i].u.object.oid = dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
+ ce[i].u.object.oi.StorageID = 0; /* use as marker */
+ ce[i].u.object.oi.ObjectFormat = dtoh16a(&curdata[PTP_ece_OI_OFC]);
+ ce[i].u.object.oi.ParentObject = 0; /* check, but use as marker */
+ ce[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
+ ce[i].u.object.oi.Filename = strdup(((char*)&curdata[PTP_ece_OI_Name]));
+
+ ptp_debug (params, "event %d: request object transfer oid %08lx, ofc %04x, size %d, filename %p", i, ce[i].u.object.oid, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename);
break;
case PTP_EC_CANON_EOS_AvailListChanged: { /* property desc */
uint32_t proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
uint32_t propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
uint32_t propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
unsigned char *xdata = &curdata[PTP_ece_Prop_Desc_Data];
- int j;
+ unsigned int j;
PTPDevicePropDesc *dpd;
ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype);
@@ -1511,12 +1838,14 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
}
if (! propxcnt)
break;
+ if (propxcnt >= 2<<16) /* buggy or exploit */
+ break;
ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
i, propxtype, proptype, dpd->DataType, propxcnt);
dpd->FormFlag = PTP_DPFF_Enumeration;
dpd->FORM.Enum.NumberOfValues = propxcnt;
- if (dpd->FORM.Enum.SupportedValue) free (dpd->FORM.Enum.SupportedValue);
+ free (dpd->FORM.Enum.SupportedValue);
dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
switch (proptype) {
@@ -1527,7 +1856,7 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
/* special handling of ImageFormat properties */
for (j=0;j<propxcnt;j++) {
dpd->FORM.Enum.SupportedValue[j].u16 =
- dtoh16( ptp_unpack_EOS_ImageFormat( params, &xdata ) );
+ ptp_unpack_EOS_ImageFormat( params, &xdata );
ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
}
break;
@@ -1558,7 +1887,7 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
}
case PTP_EC_CANON_EOS_PropValueChanged:
if (size >= 0xc) { /* property info */
- int j;
+ unsigned int j;
uint32_t proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
unsigned char *xdata = &curdata[PTP_ece_Prop_Val_Data];
PTPDevicePropDesc *dpd;
@@ -1578,7 +1907,6 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
else
params->canon_props = malloc(sizeof(params->canon_props[0]));
- params->canon_props[j].type = type;
params->canon_props[j].proptype = proptype;
params->canon_props[j].size = size;
params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
@@ -1590,8 +1918,8 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
}
dpd = &params->canon_props[j].dpd;
- (*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
- (*ce)[i].u.propid = proptype;
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
+ ce[i].u.propid = proptype;
/* fix GetSet value */
switch (proptype) {
@@ -1632,6 +1960,8 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
/* set DataType */
switch (proptype) {
case PTP_DPC_CANON_EOS_CameraTime:
+ case PTP_DPC_CANON_EOS_UTCTime:
+ case PTP_DPC_CANON_EOS_Summertime: /* basical the DST flag */
case PTP_DPC_CANON_EOS_AvailableShots:
case PTP_DPC_CANON_EOS_CaptureDestination:
case PTP_DPC_CANON_EOS_WhiteBalanceXA:
@@ -1642,6 +1972,8 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
case PTP_DPC_CANON_EOS_ModelID:
case PTP_DPC_CANON_EOS_LensID:
case PTP_DPC_CANON_EOS_StroboFiring:
+ case PTP_DPC_CANON_EOS_AFSelectFocusArea:
+ case PTP_DPC_CANON_EOS_ContinousAFMode:
dpd->DataType = PTP_DTC_UINT32;
break;
/* enumeration for AEM is never provided, but is available to set */
@@ -1664,12 +1996,14 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
case PTP_DPC_CANON_EOS_QuickReviewTime:
case PTP_DPC_CANON_EOS_EVFMode:
case PTP_DPC_CANON_EOS_EVFOutputDevice:
+ case PTP_DPC_CANON_EOS_AutoPowerOff:
+ case PTP_DPC_CANON_EOS_EVFRecordStatus:
dpd->DataType = PTP_DTC_UINT16;
break;
case PTP_DPC_CANON_EOS_PictureStyle:
case PTP_DPC_CANON_EOS_WhiteBalance:
case PTP_DPC_CANON_EOS_MeteringMode:
- case PTP_DPC_CANON_EOS_ExpCompensation: /* actually int8 if you calculate */
+ case PTP_DPC_CANON_EOS_ExpCompensation:
dpd->DataType = PTP_DTC_UINT8;
break;
case PTP_DPC_CANON_EOS_Owner:
@@ -1684,7 +2018,6 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
dpd->DataType = PTP_DTC_INT16;
break;
/* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
- case 0xd114:
case PTP_DPC_CANON_EOS_DPOFVersion:
dpd->DataType = PTP_DTC_UINT16;
ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
@@ -1721,18 +2054,19 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
case PTP_DPC_CANON_EOS_EVFWBMode:
case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
case PTP_DPC_CANON_EOS_EVFColorTemp:
- case PTP_DPC_CANON_EOS_EVFRecordStatus:
case PTP_DPC_CANON_EOS_ExposureSimMode:
case PTP_DPC_CANON_EOS_LvAfSystem:
case PTP_DPC_CANON_EOS_MovSize:
case PTP_DPC_CANON_EOS_DepthOfField:
case PTP_DPC_CANON_EOS_LvViewTypeSelect:
+ case PTP_DPC_CANON_EOS_AloMode:
+ case PTP_DPC_CANON_EOS_Brightness:
dpd->DataType = PTP_DTC_UINT32;
ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
- ptp_debug (params, " %d: 0x%8x", j, ((uint32_t*)xdata)[j]);
+ ptp_debug (params, " %d: 0x%8x", j, dtoh32a(xdata+j*4));
break;
/* ImageFormat properties have to be ignored here, see special handling below */
case PTP_DPC_CANON_EOS_ImageFormat:
@@ -1740,6 +2074,7 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
case PTP_DPC_CANON_EOS_ImageFormatSD:
case PTP_DPC_CANON_EOS_ImageFormatExtHD:
case PTP_DPC_CANON_EOS_CustomFuncEx:
+ case PTP_DPC_CANON_EOS_FocusInfoEx:
break;
default:
ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
@@ -1753,6 +2088,11 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
dpd->CurrentValue.u32 = dtoh32a(xdata);
ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
break;
+ case PTP_DTC_INT16:
+ dpd->FactoryDefaultValue.i16 = dtoh16a(xdata);
+ dpd->CurrentValue.i16 = dtoh16a(xdata);
+ ptp_debug (params,"event %d: currentvalue of %x is %d", i, proptype, dpd->CurrentValue.i16);
+ break;
case PTP_DTC_UINT16:
dpd->FactoryDefaultValue.u16 = dtoh16a(xdata);
dpd->CurrentValue.u16 = dtoh16a(xdata);
@@ -1763,16 +2103,21 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
dpd->CurrentValue.u8 = dtoh8a(xdata);
ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
break;
+ case PTP_DTC_INT8:
+ dpd->FactoryDefaultValue.i8 = dtoh8a(xdata);
+ dpd->CurrentValue.i8 = dtoh8a(xdata);
+ ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.i8);
+ break;
case PTP_DTC_STR: {
#if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
uint8_t len = 0;
dpd->FactoryDefaultValue.str = ptp_unpack_string(params, data, 0, &len);
dpd->CurrentValue.str = ptp_unpack_string(params, data, 0, &len);
#else
- if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
+ free (dpd->FactoryDefaultValue.str);
dpd->FactoryDefaultValue.str = strdup( (char*)xdata );
- if (dpd->CurrentValue.str) free (dpd->CurrentValue.str);
+ free (dpd->CurrentValue.str);
dpd->CurrentValue.str = strdup( (char*)xdata );
#endif
ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
@@ -1796,20 +2141,233 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
break;
case PTP_DPC_CANON_EOS_CustomFuncEx:
dpd->DataType = PTP_DTC_STR;
- if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
- if (dpd->CurrentValue.str) free (dpd->CurrentValue.str);
- dpd->FactoryDefaultValue.str = ptp_unpack_EOS_CustomFuncEx( params, &data );
+ free (dpd->FactoryDefaultValue.str);
+ free (dpd->CurrentValue.str);
+ dpd->FactoryDefaultValue.str = ptp_unpack_EOS_CustomFuncEx( params, &xdata );
dpd->CurrentValue.str = strdup( (char*)dpd->FactoryDefaultValue.str );
ptp_debug (params,"event %d: decoded custom function, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
break;
+ case PTP_DPC_CANON_EOS_FocusInfoEx:
+ dpd->DataType = PTP_DTC_STR;
+ free (dpd->FactoryDefaultValue.str);
+ free (dpd->CurrentValue.str);
+ dpd->FactoryDefaultValue.str = ptp_unpack_EOS_FocusInfoEx( params, &xdata );
+ dpd->CurrentValue.str = strdup( (char*)dpd->FactoryDefaultValue.str );
+ ptp_debug (params,"event %d: decoded focus info, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
+ break;
}
break;
}
+ /* one more information record handed to us */
+ case PTP_EC_CANON_EOS_OLCInfoChanged: {
+ uint32_t len, curoff;
+ uint16_t mask,proptype;
+ PTPDevicePropDesc *dpd;
+
+ /* unclear what OLC stands for */
+ ptp_debug (params, "event %d: EOS event OLCInfoChanged (size %d)", i, size);
+ if (size >= 0x8) { /* event info */
+ unsigned int k;
+ for (k=8;k<size;k++)
+ ptp_debug (params, " %d: %02x", k-8, curdata[k]);
+ }
+ len = dtoh32a(curdata+8);
+ if (len != size-8) {
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ptp_debug (params, "event %d: size %d, len %d", i, size, len);
+ break;
+ }
+ mask = dtoh16a(curdata+8+4);
+ curoff = 8+4+4;
+ if (mask & CANON_EOS_OLC_BUTTON) {
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("Button 1234567"));
+ sprintf(ce[i].u.info, "Button %d", dtoh16a(curdata+curoff));
+ i++;
+ curoff += 2;
+ }
+
+ if (mask & CANON_EOS_OLC_SHUTTERSPEED) {
+ /* 6 bytes: 01 01 98 10 00 60 */
+ /* this seesm to be the shutter speed record */
+ proptype = PTP_DPC_CANON_EOS_ShutterSpeed;
+ dpd = _lookup_or_allocate_canon_prop(params, proptype);
+ dpd->CurrentValue.u16 = curdata[curoff+5]; /* just use last byte */
+
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
+ ce[i].u.propid = proptype;
+ curoff += 6;
+ i++;
+ }
+ if (mask & CANON_EOS_OLC_APERTURE) {
+ /* 5 bytes: 01 01 5b 30 30 */
+ /* this seesm to be the aperture record */
+ proptype = PTP_DPC_CANON_EOS_Aperture;
+ dpd = _lookup_or_allocate_canon_prop(params, proptype);
+ dpd->CurrentValue.u16 = curdata[curoff+4]; /* just use last byte */
+
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
+ ce[i].u.propid = proptype;
+ curoff += 5;
+ i++;
+ }
+ if (mask & CANON_EOS_OLC_ISO) {
+ /* 5 bytes: 01 01 00 78 */
+ /* this seesm to be the aperture record */
+ proptype = PTP_DPC_CANON_EOS_ISOSpeed;
+ dpd = _lookup_or_allocate_canon_prop(params, proptype);
+ dpd->CurrentValue.u16 = curdata[curoff+3]; /* just use last byte */
+
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
+ ce[i].u.propid = proptype;
+ curoff += 4;
+ i++;
+ }
+ if (mask & 0x0010) {
+ /* mask 0x0010: 4 bytes, 04 00 00 00 observed */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("OLCInfo event 0x0010 content 01234567")+1);
+ sprintf(ce[i].u.info,"OLCInfo event 0x0010 content %02x%02x%02x%02x",
+ curdata[curoff],
+ curdata[curoff+1],
+ curdata[curoff+2],
+ curdata[curoff+3]
+ );
+ curoff += 4;
+ i++;
+ }
+ if (mask & 0x0020) {
+ /* mask 0x0020: 6 bytes, 00 00 00 00 00 00 observed */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("OLCInfo event 0x0020 content 0123456789ab")+1);
+ sprintf(ce[i].u.info,"OLCInfo event 0x0020 content %02x%02x%02x%02x%02x%02x",
+ curdata[curoff],
+ curdata[curoff+1],
+ curdata[curoff+2],
+ curdata[curoff+3],
+ curdata[curoff+4],
+ curdata[curoff+5]
+ );
+ curoff += 6;
+ i++;
+ }
+ if (mask & 0x0040) {
+ int value = (signed char)curdata[curoff+2];
+ /* mask 0x0040: 7 bytes, 01 01 00 00 00 00 00 observed */
+ /* exposure indicator */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("OLCInfo exposure indicator 012345678901234567890123456789abcd")+1);
+ sprintf(ce[i].u.info,"OLCInfo exposure indicator %d,%d,%d.%d (%02x%02x%02x%02x)",
+ curdata[curoff],
+ curdata[curoff+1],
+ value/10,abs(value)%10,
+ curdata[curoff+3],
+ curdata[curoff+4],
+ curdata[curoff+5],
+ curdata[curoff+6]
+ );
+ curoff += 7;
+ i++;
+ }
+ if (mask & 0x0080) {
+ /* mask 0x0080: 4 bytes, 00 00 00 00 observed */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("OLCInfo event 0x0080 content 01234567")+1);
+ sprintf(ce[i].u.info,"OLCInfo event 0x0080 content %02x%02x%02x%02x",
+ curdata[curoff],
+ curdata[curoff+1],
+ curdata[curoff+2],
+ curdata[curoff+3]
+ );
+ curoff += 4;
+ i++;
+ }
+ if (mask & 0x0100) {
+ /* mask 0x0100: 6 bytes, 00 00 00 00 00 00 (before focus) and 00 00 00 00 01 00 (on focus) observed */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSINFO;
+ ce[i].u.info = malloc(strlen("0123456789ab")+1);
+ sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x",
+ curdata[curoff],
+ curdata[curoff+1],
+ curdata[curoff+2],
+ curdata[curoff+3],
+ curdata[curoff+4],
+ curdata[curoff+5]
+ );
+ curoff += 6;
+ i++;
+ }
+ if (mask & 0x0200) {
+ /* mask 0x0200: 7 bytes, 00 00 00 00 00 00 00 observed */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSMASK;
+ ce[i].u.info = malloc(strlen("0123456789abcd0123456789abcdef")+1);
+ sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x%02x",
+ curdata[curoff],
+ curdata[curoff+1],
+ curdata[curoff+2],
+ curdata[curoff+3],
+ curdata[curoff+4],
+ curdata[curoff+5],
+ curdata[curoff+6]
+ );
+ curoff += 7;
+ i++;
+ }
+ if (mask & 0x0400) {
+ /* mask 0x0400: 7 bytes, 00 00 00 00 00 00 00 observed */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("OLCInfo event 0x0400 content 0123456789abcd")+1);
+ sprintf(ce[i].u.info,"OLCInfo event 0x0400 content %02x%02x%02x%02x%02x%02x%02x",
+ curdata[curoff],
+ curdata[curoff+1],
+ curdata[curoff+2],
+ curdata[curoff+3],
+ curdata[curoff+4],
+ curdata[curoff+5],
+ curdata[curoff+6]
+ );
+ curoff += 7;
+ i++;
+ }
+ if (mask & 0x0800) {
+ /* mask 0x0800: 8 bytes, 00 00 00 00 00 00 00 00 and 19 01 00 00 00 00 00 00 and others observed */
+ /* might be mask of focus points selected */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("OLCInfo event 0x0800 content 0123456789abcdef")+1);
+ sprintf(ce[i].u.info,"OLCInfo event 0x0800 content %02x%02x%02x%02x%02x%02x%02x%02x",
+ curdata[curoff],
+ curdata[curoff+1],
+ curdata[curoff+2],
+ curdata[curoff+3],
+ curdata[curoff+4],
+ curdata[curoff+5],
+ curdata[curoff+6],
+ curdata[curoff+7]
+ );
+ curoff += 8;
+ i++;
+ }
+ if (mask & 0x1000) {
+ /* mask 0x1000: 1 byte, 00 observed */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("OLCInfo event 0x1000 content 01")+1);
+ sprintf(ce[i].u.info,"OLCInfo event 0x1000 content %02x",
+ curdata[curoff]
+ );
+ curoff += 1;
+ i++;
+ }
+ /* handle more masks */
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("OLCInfo event mask 0123456789")+1);
+ sprintf(ce[i].u.info, "OLCInfo event mask=%x", mask);
+ break;
+ }
case PTP_EC_CANON_EOS_CameraStatusChanged:
- ptp_debug (params, "event %d: EOS event CameraStatusChanged (size %d)", i, size);
- (*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS;
- (*ce)[i].u.status = dtoh32a(curdata+8);
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS;
+ ce[i].u.status = dtoh32a(curdata+8);
+ ptp_debug (params, "event %d: EOS event CameraStatusChanged (size %d) = %d", i, size, dtoh32a(curdata+8));
params->eos_camerastatus = dtoh32a(curdata+8);
break;
case 0: /* end marker */
@@ -1818,19 +2376,22 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
break;
case PTP_EC_CANON_EOS_BulbExposureTime:
- (*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
- (*ce)[i].u.info = malloc(strlen("BulbExposureTime 123456789"));
- sprintf ((*ce)[i].u.info, "BulbExposureTime %d", dtoh32a(curdata+8));
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].u.info = malloc(strlen("BulbExposureTime 123456789"));
+ sprintf (ce[i].u.info, "BulbExposureTime %d", dtoh32a(curdata+8));
+ break;
+ case PTP_EC_CANON_EOS_ObjectRemoved:
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTREMOVED;
+ ce[i].u.object.oid = dtoh32a(curdata+8);
break;
default:
switch (type) {
#define XX(x) case PTP_EC_CANON_EOS_##x: \
ptp_debug (params, "event %d: unhandled EOS event "#x" (size %d)", i, size); \
- (*ce)[i].u.info = malloc(strlen("unhandled EOS event "#x" (size 123456789)")); \
- sprintf ((*ce)[i].u.info, "unhandled EOS event "#x" (size %d)", size); \
+ ce[i].u.info = malloc(strlen("unhandled EOS event "#x" (size 123456789)")); \
+ sprintf (ce[i].u.info, "unhandled EOS event "#x" (size %d)", size); \
break;
XX(RequestGetEvent)
- XX(ObjectRemoved)
XX(RequestGetObjectInfoEx)
XX(StorageStatusChanged)
XX(StorageInfoChanged)
@@ -1853,23 +2414,24 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
break;
}
if (size >= 0x8) { /* event info */
- int j;
+ unsigned int j;
for (j=8;j<size;j++)
ptp_debug (params, " %d: %02x", j, curdata[j]);
}
- (*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
+ ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
break;
}
curdata += size;
- i++;
if ((size == 8) && (type == 0))
break;
+ i++;
}
- if (!entries) {
- free (*ce);
- *ce = NULL;
+ if (!i) {
+ free (ce);
+ ce = NULL;
}
- return entries;
+ *pce = ce;
+ return i;
}
/*
@@ -1880,9 +2442,9 @@ ptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize,
#define PTP_nikon_ec_Param1 4
#define PTP_nikon_ec_Size 6
static inline void
-ptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, int *cnt)
+ptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, unsigned int *cnt)
{
- int i;
+ unsigned int i;
*ec = NULL;
if (data == NULL)
@@ -1986,11 +2548,11 @@ ptp_unpack_canon_directory (
for (i=0;i<cnt;i++)
if (ISOBJECT(dir+i*0x4c)) nrofobs++;
handles->n = nrofobs;
- handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs);
+ handles->Handler = calloc(nrofobs,sizeof(handles->Handler[0]));
if (!handles->Handler) return PTP_RC_GeneralError;
- *oinfos = calloc(sizeof((*oinfos)[0]),nrofobs);
+ *oinfos = calloc(nrofobs,sizeof((*oinfos)[0]));
if (!*oinfos) return PTP_RC_GeneralError;
- *flags = calloc(sizeof((*flags)[0]),nrofobs);
+ *flags = calloc(nrofobs,sizeof((*flags)[0]));
if (!*flags) return PTP_RC_GeneralError;
/* Migrate data into objects ids, handles into
@@ -2031,7 +2593,7 @@ ptp_unpack_canon_directory (
}
/* Walk over all objects and distribute the storage ids */
while (1) {
- int changed = 0;
+ unsigned int changed = 0;
for (i=0;i<cnt;i++) {
unsigned char *cur = dir+i*0x4c;
uint32_t oid = dtoh32a(cur + ptp_canon_dir_objectid);
« no previous file with comments | « src/ptp.c ('k') | src/util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698