summaryrefslogtreecommitdiff
path: root/src/ptp-pack.c
diff options
context:
space:
mode:
authorLinus Walleij <triad@df.lth.se>2006-04-25 08:05:09 +0000
committerLinus Walleij <triad@df.lth.se>2006-04-25 08:05:09 +0000
commitb02a066363ab3c9b4f8f48b227c9b7b71cf7705e (patch)
treee86753c8d3f4a8ca41382299abddce1a3c8cc7fa /src/ptp-pack.c
parent902c0b91c1d37f39ee7b5f0a47bf22fd7cc19212 (diff)
downloadlibmtp-b02a066363ab3c9b4f8f48b227c9b7b71cf7705e.tar.gz
Totally rebased on libgphoto2 sources.
Diffstat (limited to 'src/ptp-pack.c')
-rw-r--r--src/ptp-pack.c898
1 files changed, 447 insertions, 451 deletions
diff --git a/src/ptp-pack.c b/src/ptp-pack.c
index 49ef8b8..a1aa5ec 100644
--- a/src/ptp-pack.c
+++ b/src/ptp-pack.c
@@ -1,74 +1,91 @@
-/*
- * ptp-pack.c
- *
- */
-
-#include "ptp.h"
-#include "ptp-pack.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
+/* currently this file is included into ptp.c */
-inline uint16_t
+static inline uint16_t
htod16p (PTPParams *params, uint16_t var)
{
return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
}
-inline uint32_t
+static inline uint32_t
htod32p (PTPParams *params, uint32_t var)
{
return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
}
-inline void
+static inline void
htod16ap (PTPParams *params, unsigned char *a, uint16_t val)
{
if (params->byteorder==PTP_DL_LE)
- htole16a(a,val); else
+ htole16a(a,val);
+ else
htobe16a(a,val);
}
-inline void
+static inline void
htod32ap (PTPParams *params, unsigned char *a, uint32_t val)
{
if (params->byteorder==PTP_DL_LE)
- htole32a(a,val); else
+ htole32a(a,val);
+ else
htobe32a(a,val);
}
-inline uint16_t
+static inline uint16_t
dtoh16p (PTPParams *params, uint16_t var)
{
return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
}
-inline uint32_t
+static inline uint32_t
dtoh32p (PTPParams *params, uint32_t var)
{
return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
}
-inline uint16_t
+static inline uint16_t
dtoh16ap (PTPParams *params, unsigned char *a)
{
return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
}
-inline uint32_t
+static inline uint32_t
dtoh32ap (PTPParams *params, unsigned char *a)
{
return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
}
-inline uint64_t
+static inline uint64_t
dtoh64ap (PTPParams *params, unsigned char *a)
{
- return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a));
+ uint64_t tmp = 0;
+ int i;
+
+ if (params->byteorder==PTP_DL_LE) {
+ for (i=0;i<8;i++)
+ tmp |= (((uint64_t)a[i]) << (8*i));
+ } else {
+ for (i=0;i<8;i++)
+ tmp |= (((uint64_t)a[i]) << (8*(7-i)));
+ }
+ return tmp;
}
-inline char*
-ptp_unpack_string(PTPParams *params, char* data, uint16_t offset, uint8_t *len)
+#define htod8a(a,x) *(uint8_t*)(a) = x
+#define htod16a(a,x) htod16ap(params,a,x)
+#define htod32a(a,x) htod32ap(params,a,x)
+#define htod16(x) htod16p(params,x)
+#define htod32(x) htod32p(params,x)
+
+#define dtoh8a(x) (*(uint8_t*)(x))
+#define dtoh16a(a) dtoh16ap(params,a)
+#define dtoh32a(a) dtoh32ap(params,a)
+#define dtoh64a(a) dtoh64ap(params,a)
+#define dtoh16(x) dtoh16p(params,x)
+#define dtoh32(x) dtoh32p(params,x)
+
+
+static inline char*
+ptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
{
int i;
char *string=NULL;
@@ -86,8 +103,8 @@ ptp_unpack_string(PTPParams *params, char* data, uint16_t offset, uint8_t *len)
return (string);
}
-inline void
-ptp_pack_string(PTPParams *params, char *string, char* data, uint16_t offset, uint8_t *len)
+static inline void
+ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
{
int i;
*len = (uint8_t)strlen(string);
@@ -99,8 +116,8 @@ ptp_pack_string(PTPParams *params, char *string, char* data, uint16_t offset, ui
}
}
-inline uint32_t
-ptp_unpack_uint32_t_array(PTPParams *params, char* data, uint16_t offset, uint32_t **array)
+static inline uint32_t
+ptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
{
uint32_t n, i=0;
@@ -113,8 +130,8 @@ ptp_unpack_uint32_t_array(PTPParams *params, char* data, uint16_t offset, uint32
return n;
}
-inline uint32_t
-ptp_unpack_uint16_t_array(PTPParams *params, char* data, uint16_t offset, uint16_t **array)
+static inline uint32_t
+ptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
{
uint32_t n, i=0;
@@ -136,8 +153,8 @@ ptp_unpack_uint16_t_array(PTPParams *params, char* data, uint16_t offset, uint16
#define PTP_di_FunctionalMode 8
#define PTP_di_OperationsSupported 10
-inline void
-ptp_unpack_DI (PTPParams *params, char* data, PTPDeviceInfo *di)
+static inline void
+ptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
{
uint8_t len;
unsigned int totallen;
@@ -195,8 +212,8 @@ ptp_unpack_DI (PTPParams *params, char* data, PTPDeviceInfo *di)
#define PTP_oh 0
-inline void
-ptp_unpack_OH (PTPParams *params, char* data, PTPObjectHandles *oh)
+static inline void
+ptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
{
oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
}
@@ -205,8 +222,8 @@ ptp_unpack_OH (PTPParams *params, char* data, PTPObjectHandles *oh)
#define PTP_sids 0
-inline void
-ptp_unpack_SIDs (PTPParams *params, char* data, PTPStorageIDs *sids)
+static inline void
+ptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
{
sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
&sids->Storage);
@@ -222,15 +239,14 @@ ptp_unpack_SIDs (PTPParams *params, char* data, PTPStorageIDs *sids)
#define PTP_si_FreeSpaceInImages 22
#define PTP_si_StorageDescription 26
-inline void
-ptp_unpack_SI (PTPParams *params, char* data, PTPStorageInfo *si)
+static inline void
+ptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
{
uint8_t storagedescriptionlen;
si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
- /* next two added by RAL 2005-12-23 */
si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
@@ -261,10 +277,10 @@ ptp_unpack_SI (PTPParams *params, char* data, PTPStorageInfo *si)
#define PTP_oi_filenamelen 52
#define PTP_oi_Filename 53
-inline uint32_t
-ptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, char** oidataptr)
+static inline uint32_t
+ptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
{
- char* oidata;
+ unsigned char* oidata;
uint8_t filenamelen;
uint8_t capturedatelen=0;
/* let's allocate some memory first; XXX i'm sure it's wrong */
@@ -323,8 +339,8 @@ ptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, char** oidataptr)
return (PTP_oi_Filename+(filenamelen+1)*2+(capturedatelen+1)*4);
}
-inline void
-ptp_unpack_OI (PTPParams *params, char* data, PTPObjectInfo *oi)
+static inline void
+ptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
{
uint8_t filenamelen;
uint8_t capturedatelen;
@@ -410,87 +426,103 @@ ptp_unpack_OI (PTPParams *params, char* data, PTPObjectInfo *oi)
}
/* Custom Type Value Assignement (without Length) macro frequently used below */
-#define CTVAL(type,func,target) { \
- *target = malloc(sizeof(type)); \
- **(type **)target = \
- func(data);\
+#define CTVAL(target,func) { \
+ if (total - *offset < sizeof(target)) \
+ return 0; \
+ target = func(&data[*offset]); \
+ *offset += sizeof(target); \
}
-/* modified by RAL 2005-12-26 to return value size */
-uint32_t
-ptp_unpack_DPV (PTPParams *params, char* data, void** value, uint16_t datatype)
-{
- int i=0;
+#define RARR(val,member,func) { \
+ int n,j; \
+ if (total - *offset < sizeof(uint32_t)) \
+ return 0; \
+ n = dtoh32a (&data[*offset]); \
+ *offset += sizeof(uint32_t); \
+ \
+ val->a.count = n; \
+ val->a.v = malloc(sizeof(val->a.v[0])*n); \
+ if (!val->a.v) return 0; \
+ for (j=0;j<n;j++) \
+ CTVAL(val->a.v[j].member, func); \
+}
+static inline int
+ptp_unpack_DPV (
+ PTPParams *params, unsigned char* data, int *offset, int total,
+ PTPPropertyValue* value, uint16_t datatype
+) {
switch (datatype) {
- case PTP_DTC_INT8:
- CTVAL(int8_t,dtoh8a,value);
- return sizeof(int8_t);
- break;
- case PTP_DTC_UINT8:
- CTVAL(uint8_t,dtoh8a,value);
- return sizeof(uint8_t);
- break;
- case PTP_DTC_INT16:
- CTVAL(int16_t,dtoh16a,value);
- return sizeof(int16_t);
- break;
- case PTP_DTC_UINT16:
- CTVAL(uint16_t,dtoh16a,value);
- return sizeof(uint16_t);
- break;
- case PTP_DTC_INT32:
- CTVAL(int32_t,dtoh32a,value);
- return sizeof(int32_t);
- break;
- case PTP_DTC_UINT32:
- CTVAL(uint32_t,dtoh32a,value);
- return sizeof(uint32_t);
- break;
- case PTP_DTC_UINT64:
- CTVAL(uint64_t,dtoh64a,value);
- return sizeof(uint64_t);
- break;
- /* XXX: other int types are unimplemented */
- /* XXX: int arrays are unimplemented also */
- case PTP_DTC_STR:
- {
- uint8_t len;
- (*value)=ptp_unpack_string(params,data,0,&len);
- return 2*len+1;
- break;
- }
- case PTP_DTC_UNISTR:
- {
- /* this length includes the null character */
- uint8_t len=dtoh8a(&data[0]);
- if (len==0)
- {
- *value=malloc(2);
- ((uint16_t *)*value)[0]=0;
- }
- else
- {
- *value=malloc(len*2);
- for (i=0;i<len;i++)
- {
- ((uint16_t *)*value)[i]=dtoh16a(&data[i*2+1]);
- }
- /* just to be sure... */
- ((uint16_t *)*value)[len-1]=0;
- }
-
- return 2*len+1;
-
- break;
- }
- default:
- printf("data type 0x%.04x not supported by ptp_unpack_DPV\n", datatype);
+ case PTP_DTC_INT8:
+ CTVAL(value->i8,dtoh8a);
+ break;
+ case PTP_DTC_UINT8:
+ CTVAL(value->u8,dtoh8a);
+ break;
+ case PTP_DTC_INT16:
+ CTVAL(value->i16,dtoh16a);
+ break;
+ case PTP_DTC_UINT16:
+ CTVAL(value->u16,dtoh16a);
+ break;
+ case PTP_DTC_INT32:
+ CTVAL(value->i32,dtoh32a);
+ break;
+ case PTP_DTC_UINT32:
+ CTVAL(value->u32,dtoh32a);
+ break;
+ case PTP_DTC_AINT8:
+ RARR(value,i8,dtoh8a);
+ break;
+ case PTP_DTC_AUINT8:
+ RARR(value,u8,dtoh8a);
+ break;
+ case PTP_DTC_AUINT16:
+ RARR(value,u16,dtoh16a);
+ break;
+ case PTP_DTC_AINT16:
+ RARR(value,i16,dtoh16a);
+ break;
+ case PTP_DTC_AUINT32:
+ RARR(value,u32,dtoh32a);
+ break;
+ case PTP_DTC_AINT32:
+ RARR(value,i32,dtoh32a);
+ break;
+ /* XXX: other int types are unimplemented */
+ /* XXX: other int arrays are unimplemented also */
+ case PTP_DTC_STR: {
+ uint8_t len;
+ /* XXX: max size */
+ value->str = ptp_unpack_string(params,data,*offset,&len);
+ *offset += len*2+1;
+ if (!value->str)
return 0;
+ break;
}
+ case PTP_DTC_UNISTR: {
+ /* this length includes the null character */
+ const int unicsize = sizeof(uint16_t);
+ uint8_t len=dtoh8a(&data[0]);
+ if (len==0) {
+ value->unistr = malloc(unicsize);
+ value->unistr[0]=0;
+ } else {
+ int i;
+ value->unistr = malloc(len*unicsize);
+ for (i=0;i<len;i++) {
+ value->unistr[i]=dtoh16a(&data[i*unicsize+1]);
+ }
+ /* just to be sure... */
+ value->unistr[len-1]=0;
+ }
+ return 2*len+1;
+ break;
+ }
+ }
+ return 1;
}
-
/* Device Property pack/unpack */
#define PTP_dpd_DevicePropertyCode 0
@@ -498,369 +530,263 @@ ptp_unpack_DPV (PTPParams *params, char* data, void** value, uint16_t datatype)
#define PTP_dpd_GetSet 4
#define PTP_dpd_FactoryDefaultValue 5
-/* Custom Type Value Assignement macro frequently used below */
-#define CTVA(type,func,target) { \
- target = malloc(sizeof(type)); \
- *(type *)target = \
- func(&data[PTP_dpd_FactoryDefaultValue+totallen]);\
- totallen+=sizeof(type); \
-}
-
-/* Many Custom Types Vale Assignement macro frequently used below */
-
-#define MCTVA(type,func,target,n) { \
- uint16_t i; \
- for (i=0;i<n;i++) { \
- target[i] = malloc(sizeof(type)); \
- *(type *)target[i] = \
- func(&data[PTP_dpd_FactoryDefaultValue+totallen]);\
- totallen+=sizeof(type); \
- } \
-}
-
-inline void
-ptp_unpack_DPD (PTPParams *params, char* data, PTPDevicePropDesc *dpd)
+static inline int
+ptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
{
- uint8_t len;
- int totallen=0;
+ int offset=0, ret;
+ memset (dpd, 0, sizeof(*dpd));
dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
- dpd->FactoryDefaultValue = NULL;
- dpd->CurrentValue = NULL;
- switch (dpd->DataType) {
- case PTP_DTC_INT8:
- CTVA(int8_t,dtoh8a,dpd->FactoryDefaultValue);
- CTVA(int8_t,dtoh8a,dpd->CurrentValue);
- break;
- case PTP_DTC_UINT8:
- CTVA(uint8_t,dtoh8a,dpd->FactoryDefaultValue);
- CTVA(uint8_t,dtoh8a,dpd->CurrentValue);
- break;
- case PTP_DTC_INT16:
- CTVA(int16_t,dtoh16a,dpd->FactoryDefaultValue);
- CTVA(int16_t,dtoh16a,dpd->CurrentValue);
- break;
- case PTP_DTC_UINT16:
- CTVA(uint16_t,dtoh16a,dpd->FactoryDefaultValue);
- CTVA(uint16_t,dtoh16a,dpd->CurrentValue);
- break;
- case PTP_DTC_INT32:
- CTVA(int32_t,dtoh32a,dpd->FactoryDefaultValue);
- CTVA(int32_t,dtoh32a,dpd->CurrentValue);
- break;
- case PTP_DTC_UINT32:
- CTVA(uint32_t,dtoh32a,dpd->FactoryDefaultValue);
- CTVA(uint32_t,dtoh32a,dpd->CurrentValue);
- break;
- /* XXX: other int types are unimplemented */
- /* XXX: int arrays are unimplemented also */
- case PTP_DTC_STR:
- dpd->FactoryDefaultValue = ptp_unpack_string
- (params,data,PTP_dpd_FactoryDefaultValue,&len);
- totallen=len*2+1;
- dpd->CurrentValue = ptp_unpack_string
- (params, data, PTP_dpd_FactoryDefaultValue +
- totallen, &len);
- totallen+=len*2+1;
- break;
- }
- /* if totallen==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. */
+
+ offset = PTP_dpd_FactoryDefaultValue;
+ ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
+ if (!ret) goto outofmemory;
+ ret = ptp_unpack_DPV (params, data, &offset, 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. */
+
dpd->FormFlag=PTP_DPFF_None;
- if (totallen==0) return;
+ if (offset==PTP_dpd_FactoryDefaultValue)
+ return 1;
+
+ dpd->FormFlag=dtoh8a(&data[offset]);
+ offset+=sizeof(uint8_t);
- dpd->FormFlag=dtoh8a(&data[PTP_dpd_FactoryDefaultValue+totallen]);
- totallen+=sizeof(uint8_t);
switch (dpd->FormFlag) {
- case PTP_DPFF_Range:
- switch (dpd->DataType) {
- case PTP_DTC_INT8:
- CTVA(int8_t,dtoh8a,dpd->FORM.Range.MinimumValue);
- CTVA(int8_t,dtoh8a,dpd->FORM.Range.MaximumValue);
- CTVA(int8_t,dtoh8a,dpd->FORM.Range.StepSize);
- break;
- case PTP_DTC_UINT8:
- CTVA(uint8_t,dtoh8a,dpd->FORM.Range.MinimumValue);
- CTVA(uint8_t,dtoh8a,dpd->FORM.Range.MaximumValue);
- CTVA(uint8_t,dtoh8a,dpd->FORM.Range.StepSize);
- break;
- case PTP_DTC_INT16:
- CTVA(int16_t,dtoh16a,dpd->FORM.Range.MinimumValue);
- CTVA(int16_t,dtoh16a,dpd->FORM.Range.MaximumValue);
- CTVA(int16_t,dtoh16a,dpd->FORM.Range.StepSize);
- break;
- case PTP_DTC_UINT16:
- CTVA(uint16_t,dtoh16a,dpd->FORM.Range.MinimumValue);
- CTVA(uint16_t,dtoh16a,dpd->FORM.Range.MaximumValue);
- CTVA(uint16_t,dtoh16a,dpd->FORM.Range.StepSize);
- break;
- case PTP_DTC_INT32:
- CTVA(int32_t,dtoh32a,dpd->FORM.Range.MinimumValue);
- CTVA(int32_t,dtoh32a,dpd->FORM.Range.MaximumValue);
- CTVA(int32_t,dtoh32a,dpd->FORM.Range.StepSize);
- break;
- case PTP_DTC_UINT32:
- CTVA(uint32_t,dtoh32a,dpd->FORM.Range.MinimumValue);
- CTVA(uint32_t,dtoh32a,dpd->FORM.Range.MaximumValue);
- CTVA(uint32_t,dtoh32a,dpd->FORM.Range.StepSize);
- break;
- /* XXX: other int types are unimplemented */
- /* XXX: int arrays are unimplemented also */
- /* XXX: does it make any sense: "a range of strings"? */
- }
+ case PTP_DPFF_Range:
+ ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
+ if (!ret) goto outofmemory;
+ ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
+ if (!ret) goto outofmemory;
+ ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
+ if (!ret) goto outofmemory;
break;
- case PTP_DPFF_Enumeration:
+ case PTP_DPFF_Enumeration: {
+ int i;
#define N dpd->FORM.Enum.NumberOfValues
- N = dtoh16a(&data[PTP_dpd_FactoryDefaultValue+totallen]);
- totallen+=sizeof(uint16_t);
- dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(void *));
- switch (dpd->DataType) {
- case PTP_DTC_INT8:
- MCTVA(int8_t,dtoh8a,dpd->FORM.Enum.SupportedValue,N);
- break;
- case PTP_DTC_UINT8:
- MCTVA(uint8_t,dtoh8a,dpd->FORM.Enum.SupportedValue,N);
- break;
- case PTP_DTC_INT16:
- MCTVA(int16_t,dtoh16a,dpd->FORM.Enum.SupportedValue,N);
- break;
- case PTP_DTC_UINT16:
- MCTVA(uint16_t,dtoh16a,dpd->FORM.Enum.SupportedValue,N);
- break;
- case PTP_DTC_INT32:
- MCTVA(int32_t,dtoh16a,dpd->FORM.Enum.SupportedValue,N);
- break;
- case PTP_DTC_UINT32:
- MCTVA(uint32_t,dtoh16a,dpd->FORM.Enum.SupportedValue,N);
- break;
- case PTP_DTC_STR:
- {
- int i;
- for(i=0;i<N;i++)
- {
- dpd->FORM.Enum.SupportedValue[i]=
- ptp_unpack_string
- (params,data,PTP_dpd_FactoryDefaultValue
- +totallen,&len);
- totallen+=len*2+1;
- }
+ N = dtoh16a(&data[offset]);
+ offset+=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, &offset, 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;
}
- break;
+ }
}
}
+#undef N
+ return 1;
+outofmemory:
+ ptp_free_devicepropdesc(dpd);
+ return 0;
}
-#define PACK_ARRAY(type,func) { \
- size=sizeof(uint32_t)+sizeof(type)*arraylen; \
- dpv=malloc(size); \
- htod32a(dpv,arraylen); \
- for (i=0; i<arraylen; i++) \
- func(&(dpv[sizeof(uint32_t)+i*sizeof(type)]),((type*)value)[i]); \
- }
+/* (MTP) Object Property pack/unpack */
+#define PTP_opd_ObjectPropertyCode 0
+#define PTP_opd_DataType 2
+#define PTP_opd_GetSet 4
+#define PTP_opd_FactoryDefaultValue 5
-inline uint32_t
-ptp_pack_array (PTPParams *params, void* value, char** dpvptr, uint16_t datatype, uint32_t arraylen)
+static inline int
+ptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
{
- char* dpv=NULL;
- uint32_t size=0;
- int i=0;
-
- switch (datatype) {
- case PTP_DTC_AINT8:
- PACK_ARRAY(int8_t,htod8a);
- break;
- case PTP_DTC_AUINT8:
- PACK_ARRAY(uint8_t,htod8a);
- break;
- case PTP_DTC_AINT16:
- PACK_ARRAY(int16_t,htod16a);
- break;
- case PTP_DTC_AUINT16:
- PACK_ARRAY(uint16_t,htod16a);
- break;
- case PTP_DTC_AINT32:
- PACK_ARRAY(int32_t,htod32a);
- break;
- case PTP_DTC_AUINT32:
- PACK_ARRAY(uint32_t,htod32a);
- break;
- /*case PTP_DTC_AINT64:
- PACK_ARRAY(int64_t,htod64a);
- break;
- case PTP_DTC_AUINT64:
- PACK_ARRAY(uint64_t,htod64a);
- break;
- case PTP_DTC_AINT128:
- PACK_ARRAY(int128_t,htod128a);
- break;
- case PTP_DTC_AUINT128:
- PACK_ARRAY(uint128_t,htod128a);
- break;*/
- default:
- printf("data type 0x%.04x not supported by ptp_pack_array\n", datatype);
- return 0;
+ int offset=0, ret;
+
+ memset (opd, 0, sizeof(*opd));
+ opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
+ opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
+ opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
+
+ offset = PTP_opd_FactoryDefaultValue;
+ ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
+ if (!ret) goto outofmemory;
+
+ opd->GroupCode=dtoh32a(&data[offset]);
+ offset+=sizeof(uint32_t);
+
+ opd->FormFlag=dtoh8a(&data[offset]);
+ offset+=sizeof(uint8_t);
+
+ switch (opd->FormFlag) {
+ case PTP_OPFF_Range:
+ ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
+ if (!ret) goto outofmemory;
+ ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
+ if (!ret) goto outofmemory;
+ ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
+ if (!ret) goto outofmemory;
+ break;
+ case PTP_OPFF_Enumeration: {
+ int i;
+#define N opd->FORM.Enum.NumberOfValues
+ N = dtoh16a(&data[offset]);
+ offset+=sizeof(uint16_t);
+ opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
+ if (!opd->FORM.Enum.SupportedValue)
+ goto outofmemory;
+
+ memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
+ for (i=0;i<N;i++) {
+ ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->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;
+ opd->FORM.Enum.NumberOfValues = i;
+ break;
+ }
+ }
+#undef N
+ }
}
- *dpvptr=dpv;
- return size;
+ return 1;
+outofmemory:
+ ptp_free_objectpropdesc(opd);
+ return 0;
}
-#define UNPACK_ARRAY(type,func) { \
- int i=0; \
- *arraylen=dtoh32a(&data[0]); \
- *value=malloc(sizeof(type)*(*arraylen)); \
- for (i=0; i<*arraylen; i++) \
- ((type*)(*value))[i]=func(&data[sizeof(uint32_t)+i*sizeof(type)]); \
- return *arraylen*sizeof(type); \
- }
-
-inline uint32_t
-ptp_unpack_array (PTPParams *params, char* data, void** value, uint16_t datatype, uint32_t* arraylen)
-{
- switch (datatype) {
- case PTP_DTC_AINT8:
- UNPACK_ARRAY(int8_t,dtoh8a);
- break;
- case PTP_DTC_AUINT8:
- UNPACK_ARRAY(uint8_t,dtoh8a);
- break;
- case PTP_DTC_AINT16:
- UNPACK_ARRAY(int16_t,dtoh16a);
- break;
- case PTP_DTC_AUINT16:
- UNPACK_ARRAY(uint16_t,dtoh16a);
- break;
- case PTP_DTC_AINT32:
- UNPACK_ARRAY(int32_t,dtoh32a);
- break;
- case PTP_DTC_AUINT32:
- UNPACK_ARRAY(uint32_t,dtoh32a);
- break;
- case PTP_DTC_AINT64:
- UNPACK_ARRAY(int64_t,dtoh64a);
- break;
- case PTP_DTC_AUINT64:
- UNPACK_ARRAY(uint64_t,dtoh64a);
- break;
- /*case PTP_DTC_AINT128:
- UNPACK_ARRAY(int128_t,dtoh128a);
- break;
- case PTP_DTC_AUINT128:
- UNPACK_ARRAY(uint128_t,dtoh128a);
- break;*/
- default:
- printf("data type 0x%.04x not supported by ptp_unpack_array\n", datatype);
- return 0;
- }
-}
-inline uint32_t
-ptp_pack_DPV (PTPParams *params, void* value, char** dpvptr, uint16_t datatype)
+static inline uint32_t
+ptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
{
- char* dpv=NULL;
+ unsigned char* dpv=NULL;
uint32_t size=0;
- int i=0;
+ int i;
switch (datatype) {
- case PTP_DTC_INT8:
- size=sizeof(int8_t);
- dpv=malloc(size);
- htod8a(dpv,*(int8_t*)value);
- break;
- case PTP_DTC_UINT8:
- size=sizeof(uint8_t);
- dpv=malloc(size);
- htod8a(dpv,*(uint8_t*)value);
- break;
- case PTP_DTC_INT16:
- size=sizeof(int16_t);
- dpv=malloc(size);
- htod16a(dpv,*(int16_t*)value);
- break;
- case PTP_DTC_UINT16:
- size=sizeof(uint16_t);
- dpv=malloc(size);
- htod16a(dpv,*(uint16_t*)value);
- break;
- case PTP_DTC_INT32:
- size=sizeof(int32_t);
- dpv=malloc(size);
- htod32a(dpv,*(int32_t*)value);
- break;
- case PTP_DTC_UINT32:
- size=sizeof(uint32_t);
- dpv=malloc(size);
- htod32a(dpv,*(uint32_t*)value);
- break;
- /*case PTP_DTC_INT64:
- size=sizeof(int64_t);
- dpv=malloc(size);
- htod64a(dpv,*(int64_t*)value);
- break;
- case PTP_DTC_UINT64:
- size=sizeof(uint64_t);
- dpv=malloc(size);
- htod64a(dpv,*(uint64_t*)value);
- break;
- case PTP_DTC_INT128:
- size=sizeof(int128_t);
- dpv=malloc(size);
- htod128a(dpv,*(int128_t*)value);
- break;
- case PTP_DTC_UINT128:
- size=sizeof(uint128_t);
+ case PTP_DTC_INT8:
+ size=sizeof(int8_t);
+ dpv=malloc(size);
+ htod8a(dpv,value->i8);
+ break;
+ case PTP_DTC_UINT8:
+ size=sizeof(uint8_t);
+ dpv=malloc(size);
+ htod8a(dpv,value->u8);
+ break;
+ case PTP_DTC_INT16:
+ size=sizeof(int16_t);
+ dpv=malloc(size);
+ htod16a(dpv,value->i16);
+ break;
+ case PTP_DTC_UINT16:
+ size=sizeof(uint16_t);
+ dpv=malloc(size);
+ htod16a(dpv,value->u16);
+ break;
+ case PTP_DTC_INT32:
+ size=sizeof(int32_t);
+ dpv=malloc(size);
+ htod32a(dpv,value->i32);
+ break;
+ case PTP_DTC_UINT32:
+ size=sizeof(uint32_t);
+ dpv=malloc(size);
+ htod32a(dpv,value->u32);
+ break;
+ case PTP_DTC_AUINT8:
+ size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
+ dpv=malloc(size);
+ htod32a(dpv,value->a.count);
+ for (i=0;i<value->a.count;i++)
+ htod8a(&dpv[4+i],value->a.v[i].u8);
+ break;
+ case PTP_DTC_AINT8:
+ size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
+ dpv=malloc(size);
+ htod32a(dpv,value->a.count);
+ for (i=0;i<value->a.count;i++)
+ htod8a(&dpv[4+i],value->a.v[i].i8);
+ break;
+ case PTP_DTC_AUINT16:
+ size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
+ dpv=malloc(size);
+ htod32a(dpv,value->a.count);
+ for (i=0;i<value->a.count;i++)
+ htod16a(&dpv[4+i],value->a.v[i].u16);
+ break;
+ case PTP_DTC_AINT16:
+ size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
+ dpv=malloc(size);
+ htod32a(dpv,value->a.count);
+ for (i=0;i<value->a.count;i++)
+ htod16a(&dpv[4+i],value->a.v[i].i16);
+ break;
+ case PTP_DTC_AUINT32:
+ size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
+ dpv=malloc(size);
+ htod32a(dpv,value->a.count);
+ for (i=0;i<value->a.count;i++)
+ htod32a(&dpv[4+i],value->a.v[i].u32);
+ break;
+ case PTP_DTC_AINT32:
+ size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
+ dpv=malloc(size);
+ htod32a(dpv,value->a.count);
+ for (i=0;i<value->a.count;i++)
+ htod32a(&dpv[4+i],value->a.v[i].i32);
+ break;
+ /* XXX: other int types are unimplemented */
+ case PTP_DTC_STR: {
+ uint8_t len;
+
+ size=strlen(value->str)*2+3;
+ dpv=malloc(size);
+ memset(dpv,0,size);
+ ptp_pack_string(params, value->str, dpv, 0, &len);
+ break;
+ }
+ case PTP_DTC_UNISTR: {
+ uint8_t len = 0;
+ /* note PTP_MAXSTRLEN includes the null terminator */
+ while (((uint16_t *)value)[len] != 0 && len != PTP_MAXSTRLEN-1)
+ len++;
+ if (len==0) {
+ size=1;
dpv=malloc(size);
- htod128a(dpv,*(uint128_t*)value);
- break;*/
- case PTP_DTC_STR:
- {
- uint8_t len;
- size=strlen((char*)value)*2+3;
+ *dpv=0;
+ } else {
+ /* 2 extra bytes for the terminator, 1 for the length at the beginning */
+ size=len*2+3;
dpv=malloc(size);
memset(dpv,0,size);
- ptp_pack_string(params, (char *)value, dpv, 0, &len);
+ htod8a(&dpv[0],len+1);
+ for (i = 0; i < len; i++)
+ htod16a(&dpv[i*2+1],((uint16_t *)value)[i]);
+ /* terminator is done by memset above */
}
break;
- case PTP_DTC_UNISTR:
- {
- uint8_t len = 0;
- /* note PTP_MAXSTRLEN includes the null terminator */
- while (((uint16_t *)value)[len] != 0 && len != PTP_MAXSTRLEN-1)
- len++;
- if (len==0)
- {
- size=1;
- dpv=malloc(size);
- *dpv=0;
- }
- else
- {
- /* 2 extra bytes for the terminator, 1 for the length at the beginning */
- size=len*2+3;
- dpv=malloc(size);
- memset(dpv,0,size);
- htod8a(&dpv[0],len+1);
- for (i = 0; i < len; i++)
- htod16a(&dpv[i*2+1],((uint16_t *)value)[i]);
- /* terminator is done by memset above */
- /*for (i = 0; i < size; i++)
- printf("dpv[%d] = %d, ", i, dpv[i]);
- printf("\n");*/
- }
- break;
- }
- default:
- printf("data type 0x%.04x not supported by ptp_pack_DPV\n", datatype);
- return 0;
+ }
}
*dpvptr=dpv;
return size;
}
-
/*
PTP USB Event container unpack
Copyright (c) 2003 Nikolai Kopanygin
@@ -874,8 +800,8 @@ ptp_pack_DPV (PTPParams *params, void* value, char** dpvptr, uint16_t datatype)
#define PTP_ec_Param2 16
#define PTP_ec_Param3 20
-inline void
-ptp_unpack_EC (PTPParams *params, char* data, PTPUSBEventContainer *ec)
+static inline void
+ptp_unpack_EC (PTPParams *params, unsigned char* data, PTPUSBEventContainer *ec, unsigned int len)
{
if (data==NULL)
return;
@@ -883,6 +809,7 @@ ptp_unpack_EC (PTPParams *params, char* data, PTPUSBEventContainer *ec)
ec->type=dtoh16a(&data[PTP_ec_Type]);
ec->code=dtoh16a(&data[PTP_ec_Code]);
ec->trans_id=dtoh32a(&data[PTP_ec_TransId]);
+
if (ec->length>=(PTP_ec_Param1+4))
ec->param1=dtoh32a(&data[PTP_ec_Param1]);
else
@@ -908,8 +835,8 @@ ptp_unpack_EC (PTPParams *params, char* data, PTPUSBEventContainer *ec)
#define PTP_cfe_Time 11
#define PTP_cfe_Filename 15
-inline void
-ptp_unpack_Canon_FE (PTPParams *params, char* data, PTPCANONFolderEntry *fe)
+static inline void
+ptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
{
int i;
if (data==NULL)
@@ -917,10 +844,79 @@ ptp_unpack_Canon_FE (PTPParams *params, char* data, PTPCANONFolderEntry *fe)
fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
- fe->ObjectSize=dtoh32a(&data[PTP_cfe_ObjectSize]);
+ fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
- fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
+ fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
+}
+
+/*
+ PTP USB Event container unpack for Nikon events.
+*/
+#define PTP_nikon_ec_Length 0
+#define PTP_nikon_ec_Code 2
+#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, PTPUSBEventContainer **ec, int *cnt)
+{
+ int i;
+
+ *ec = NULL;
+ if (data == NULL)
+ return;
+ if (len < PTP_nikon_ec_Code)
+ return;
+ *cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
+ if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
+ return;
+ *ec = malloc(sizeof(PTPUSBEventContainer)*(*cnt));
+
+ for (i=0;i<*cnt;i++) {
+ memset(&(*ec)[i],0,sizeof(PTPUSBEventContainer));
+ (*ec)[i].code = dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
+ (*ec)[i].param1 = dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
+ }
}
+static inline uint32_t
+ptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
+ int i, len = 0;
+ uint8_t retlen;
+ unsigned char *curdata;
+
+ len = 2*(strlen(text->title)+1)+1+
+ 2*(strlen(text->line[0])+1)+1+
+ 2*(strlen(text->line[1])+1)+1+
+ 2*(strlen(text->line[2])+1)+1+
+ 2*(strlen(text->line[3])+1)+1+
+ 2*(strlen(text->line[4])+1)+1+
+ 4*2+2*4+2+4+2+5*4*2;
+ *data = malloc(len);
+ if (!*data) return 0;
+
+ curdata = *data;
+ htod16a(curdata,100);curdata+=2;
+ htod16a(curdata,1);curdata+=2;
+ htod16a(curdata,0);curdata+=2;
+ htod16a(curdata,1000);curdata+=2;
+
+ htod32a(curdata,0);curdata+=4;
+ htod32a(curdata,0);curdata+=4;
+
+ htod16a(curdata,6);curdata+=2;
+ htod32a(curdata,0);curdata+=4;
+
+ ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
+ htod16a(curdata,0x10);curdata+=2;
+
+ for (i=0;i<5;i++) {
+ ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
+ htod16a(curdata,0x10);curdata+=2;
+ htod16a(curdata,0x01);curdata+=2;
+ htod16a(curdata,0x02);curdata+=2;
+ htod16a(curdata,0x06);curdata+=2;
+ }
+ return len;
+}