13aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* currently this file is included into ptp.c */
23aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef HAVE_ICONV
43aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <iconv.h>
53aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
63aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
73aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevextern void
83aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_debug (PTPParams *params, const char *format, ...);
93aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint16_t
113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevhtod16p (PTPParams *params, uint16_t var)
123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevhtod32p (PTPParams *params, uint32_t var)
183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevhtod16ap (PTPParams *params, unsigned char *a, uint16_t val)
243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (params->byteorder==PTP_DL_LE)
263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htole16a(a,val);
273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	else
283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htobe16a(a,val);
293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevhtod32ap (PTPParams *params, unsigned char *a, uint32_t val)
333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (params->byteorder==PTP_DL_LE)
353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htole32a(a,val);
363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	else
373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htobe32a(a,val);
383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevhtod64ap (PTPParams *params, unsigned char *a, uint64_t val)
423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (params->byteorder==PTP_DL_LE)
443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htole64a(a,val);
453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	else
463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htobe64a(a,val);
473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint16_t
503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevdtoh16p (PTPParams *params, uint16_t var)
513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevdtoh32p (PTPParams *params, uint32_t var)
573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint64_t
623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevdtoh64p (PTPParams *params, uint64_t var)
633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return ((params->byteorder==PTP_DL_LE)?le64toh(var):be64toh(var));
653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint16_t
683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevdtoh16ap (PTPParams *params, const unsigned char *a)
693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevdtoh32ap (PTPParams *params, const unsigned char *a)
753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint64_t
803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevdtoh64ap (PTPParams *params, const unsigned char *a)
813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a));
833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define htod8a(a,x)	*(uint8_t*)(a) = x
863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define htod16a(a,x)	htod16ap(params,a,x)
873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define htod32a(a,x)	htod32ap(params,a,x)
883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define htod64a(a,x)	htod64ap(params,a,x)
893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define htod16(x)	htod16p(params,x)
903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define htod32(x)	htod32p(params,x)
913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define htod64(x)	htod64p(params,x)
923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define dtoh8a(x)	(*(uint8_t*)(x))
943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define dtoh16a(a)	dtoh16ap(params,a)
953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define dtoh32a(a)	dtoh32ap(params,a)
963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define dtoh64a(a)	dtoh64ap(params,a)
973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define dtoh16(x)	dtoh16p(params,x)
983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define dtoh32(x)	dtoh32p(params,x)
993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define dtoh64(x)	dtoh64p(params,x)
1003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline char*
1033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
1043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
1053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint8_t length;
1063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint16_t string[PTP_MAXSTRLEN+1];
1073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* allow for UTF-8: max of 3 bytes per UCS-2 char, plus final null */
1083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	char loclstr[PTP_MAXSTRLEN*3+1];
1093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	size_t nconv, srclen, destlen;
1103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	char *src, *dest;
1113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	length = dtoh8a(&data[offset]);	/* PTP_MAXSTRLEN == 255, 8 bit len */
1133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*len = length;
1143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (length == 0)		/* nothing to do? */
1153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return(NULL);
1163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* copy to string[] to ensure correct alignment for iconv(3) */
1183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	memcpy(string, &data[offset+1], length * sizeof(string[0]));
1193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	string[length] = 0x0000U;   /* be paranoid!  add a terminator. */
1203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	loclstr[0] = '\0';
1213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* convert from camera UCS-2 to our locale */
1233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	src = (char *)string;
1243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	srclen = length * sizeof(string[0]);
1253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	dest = loclstr;
1263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	destlen = sizeof(loclstr)-1;
1273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	nconv = (size_t)-1;
1283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef HAVE_ICONV
1293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen,
1303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			&dest, &destlen);
1313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
1323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (nconv == (size_t) -1) { /* do it the hard way */
1333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		int i;
1343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/* try the old way, in case iconv is broken */
1353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<length;i++) {
1363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (dtoh16a(&data[offset+1+2*i])>127)
1373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				loclstr[i] = '?';
1383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			else
1393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				loclstr[i] = dtoh16a(&data[offset+1+2*i]);
1403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
1413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dest = loclstr+length;
1423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
1433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*dest = '\0';
1443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	loclstr[sizeof(loclstr)-1] = '\0';   /* be safe? */
1453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return(strdup(loclstr));
1463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
1473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline int
1493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevucs2strlen(uint16_t const * const unicstr)
1503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
1513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int length;
1523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* Unicode strings are terminated with 2 * 0x00 */
1543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for(length = 0; unicstr[length] != 0x0000U; length ++);
1553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return length;
1563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
1573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
1603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
1613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
1623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int packedlen;
1633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint16_t ucs2str[PTP_MAXSTRLEN+1];
1643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	char *ucs2strp = (char *) ucs2str;
1653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	size_t convlen = strlen(string);
1663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
1683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	memset(ucs2strp, 0, sizeof(ucs2str));  /* XXX: necessary? */
1693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef HAVE_ICONV
1703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	{
1713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size_t nconv;
1723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
1733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		char *stringp = string;
1743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
1763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			&ucs2strp, &convmax);
1773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (nconv == (size_t) -1)
1783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ucs2str[0] = 0x0000U;
1793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
1803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
1813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	{
1823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		int i;
1833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<convlen;i++) {
1843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ucs2str[i] = string[i];
1853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
1863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ucs2str[convlen] = 0;
1873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
1883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
1893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/*
1903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
1913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 *      why do we need ucs2strlen()?
1923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 */
1933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	packedlen = ucs2strlen(ucs2str);
1943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (packedlen > PTP_MAXSTRLEN-1) {
1953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		*len=0;
1963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return;
1973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
1983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* number of characters including terminating 0 (PTP standard confirmed) */
2003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod8a(&data[offset],packedlen+1);
2013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
2023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
2033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* The returned length is in number of characters */
2053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*len = (uint8_t) packedlen+1;
2063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
2073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline unsigned char *
2093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
2103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
2113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint8_t packed[PTP_MAXSTRLEN*2+3], len;
2123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	size_t plen;
2133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned char *retcopy = NULL;
2143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (string == NULL)
2163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
2173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	else
2183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
2193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* returned length is in characters, then one byte for string length */
2213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	plen = len*2 + 1;
2223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	retcopy = malloc(plen);
2243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!retcopy) {
2253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		*packed_size = 0;
2263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return NULL;
2273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
2283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	memcpy(retcopy, packed, plen);
2293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*packed_size = plen;
2303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return (retcopy);
2313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
2323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
2343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
2353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
2363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t n, i=0;
2373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	n=dtoh32a(&data[offset]);
2393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*array = malloc (n*sizeof(uint32_t));
2403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	while (n>i) {
2413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
2423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		i++;
2433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
2443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return n;
2453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
2463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
2483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
2493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
2503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t i=0;
2513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*data = malloc ((arraylen+1)*sizeof(uint32_t));
2533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&(*data)[0],arraylen);
2543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<arraylen;i++)
2553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
2563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return (arraylen+1)*sizeof(uint32_t);
2573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
2583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
2603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
2613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
2623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t n, i=0;
2633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	n=dtoh32a(&data[offset]);
2653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*array = malloc (n*sizeof(uint16_t));
2663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	while (n>i) {
2673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
2683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		i++;
2693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
2703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return n;
2713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
2723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* DeviceInfo pack/unpack */
2743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_di_StandardVersion		 0
2763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_di_VendorExtensionID	 2
2773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_di_VendorExtensionVersion	 6
2783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_di_VendorExtensionDesc	 8
2793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_di_FunctionalMode		 8
2803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_di_OperationsSupported	10
2813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
2833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
2843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
2853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint8_t len;
2863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned int totallen;
2873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!data) return;
2893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (datalen < 12) return;
2903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
2913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->VendorExtensionID =
2923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dtoh32a(&data[PTP_di_VendorExtensionID]);
2933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->VendorExtensionVersion =
2943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
2953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->VendorExtensionDesc =
2963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ptp_unpack_string(params, data,
2973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_VendorExtensionDesc, &len);
2983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen=len*2+1;
2993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->FunctionalMode =
3003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
3013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
3023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_OperationsSupported+totallen,
3033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&di->OperationsSupported);
3043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
3053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
3063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_OperationsSupported+totallen,
3073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&di->EventsSupported);
3083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
3093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->DevicePropertiesSupported_len =
3103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ptp_unpack_uint16_t_array(params, data,
3113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_OperationsSupported+totallen,
3123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&di->DevicePropertiesSupported);
3133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
3143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
3153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_OperationsSupported+totallen,
3163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&di->CaptureFormats);
3173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
3183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
3193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_OperationsSupported+totallen,
3203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&di->ImageFormats);
3213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
3223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->Manufacturer = ptp_unpack_string(params, data,
3233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_OperationsSupported+totallen,
3243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&len);
3253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen+=len*2+1;
3263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->Model = ptp_unpack_string(params, data,
3273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_OperationsSupported+totallen,
3283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&len);
3293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen+=len*2+1;
3303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->DeviceVersion = ptp_unpack_string(params, data,
3313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_OperationsSupported+totallen,
3323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&len);
3333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen+=len*2+1;
3343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->SerialNumber = ptp_unpack_string(params, data,
3353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_di_OperationsSupported+totallen,
3363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&len);
3373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
3383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void
3403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_free_DI (PTPDeviceInfo *di) {
3413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->SerialNumber) free (di->SerialNumber);
3423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->DeviceVersion) free (di->DeviceVersion);
3433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->Model) free (di->Model);
3443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->Manufacturer) free (di->Manufacturer);
3453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->ImageFormats) free (di->ImageFormats);
3463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->CaptureFormats) free (di->CaptureFormats);
3473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->VendorExtensionDesc) free (di->VendorExtensionDesc);
3483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->OperationsSupported) free (di->OperationsSupported);
3493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->EventsSupported) free (di->EventsSupported);
3503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (di->DevicePropertiesSupported) free (di->DevicePropertiesSupported);
3513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
3523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* EOS Device Info unpack */
3543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
3553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
3563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
3573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int totallen = 4;
3583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (datalen < 8) return;
3593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* uint32_t struct len - ignore */
3613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
3623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		totallen, &di->EventsSupported);
3633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!di->EventsSupported) return;
3643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
3653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (totallen >= datalen) return;
3663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
3683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		totallen, &di->DevicePropertiesSupported);
3693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!di->DevicePropertiesSupported) return;
3703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
3713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (totallen >= datalen) return;
3723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	di->unk_len = ptp_unpack_uint32_t_array(params, data,
3743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		totallen, &di->unk);
3753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!di->unk) return;
3763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totallen += di->unk_len*sizeof(uint32_t)+4;
3773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return;
3783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
3793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* ObjectHandles array pack/unpack */
3813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oh				 0
3833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
3853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
3863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
3873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (len) {
3883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
3893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	} else {
3903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oh->n = 0;
3913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oh->Handler = NULL;
3923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
3933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
3943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* StoreIDs array pack/unpack */
3963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_sids			 0
3983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
4003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
4013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
4023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
4033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	&sids->Storage);
4043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
4053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* StorageInfo pack/unpack */
4073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_si_StorageType		 0
4093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_si_FilesystemType		 2
4103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_si_AccessCapability		 4
4113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_si_MaxCapability		 6
4123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_si_FreeSpaceInBytes		14
4133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_si_FreeSpaceInImages	22
4143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_si_StorageDescription	26
4153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
4173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
4183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
4193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint8_t storagedescriptionlen;
4203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
4223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
4233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
4243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
4253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
4263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
4273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	si->StorageDescription=ptp_unpack_string(params, data,
4283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_si_StorageDescription, &storagedescriptionlen);
4293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	si->VolumeLabel=ptp_unpack_string(params, data,
4303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_si_StorageDescription+storagedescriptionlen*2+1,
4313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		&storagedescriptionlen);
4323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
4333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* ObjectInfo pack/unpack */
4353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_StorageID		 0
4373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ObjectFormat		 4
4383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ProtectionStatus		 6
4393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ObjectCompressedSize	 8
4403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ThumbFormat		12
4413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ThumbCompressedSize	14
4423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ThumbPixWidth		18
4433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ThumbPixHeight		22
4443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ImagePixWidth		26
4453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ImagePixHeight		30
4463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ImageBitDepth		34
4473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_ParentObject		38
4483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_AssociationType		42
4493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_AssociationDesc		44
4503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_SequenceNumber		48
4513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_filenamelen		52
4523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_Filename			53
4533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* the max length assuming zero length dates. We have need 3 */
4553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* bytes for these. */
4563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
4573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
4593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
4603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
4613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned char* oidata;
4623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint8_t filenamelen;
4633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint8_t capturedatelen=0;
4643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* let's allocate some memory first; correct assuming zero length dates */
4653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oidata=malloc(PTP_oi_MaxLen);
4663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* the caller should free it after use! */
4673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#if 0
4683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	char *capture_date="20020101T010101"; /* XXX Fake date */
4693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
4703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	memset (oidata, 0, PTP_oi_MaxLen);
4713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
4723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
4733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
4743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
4753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
4763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
4773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
4783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
4793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
4803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
4813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
4823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
4833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
4843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
4853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
4863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
4883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/*
4893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	filenamelen=(uint8_t)strlen(oi->Filename);
4903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
4913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
4923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
4933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
4943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev*/
4953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/*
4963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 *XXX Fake date.
4973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 * for example Kodak sets Capture date on the basis of EXIF data.
4983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 * Spec says that this field is from perspective of Initiator.
4993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 */
5003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
5013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	capturedatelen=strlen(capture_date);
5023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
5033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		capturedatelen+1);
5043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
5053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
5063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
5073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
5083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		capturedatelen+1);
5093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
5103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
5113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  capture_date[i];
5123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
5133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
5143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* XXX this function should return dataset length */
5153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*oidataptr=oidata;
5173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3);
5183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
5193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic time_t
5213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_PTPTIME (const char *str) {
5223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	char ptpdate[40];
5233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	char tmp[5];
5243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int  ptpdatelen;
5253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	struct tm tm;
5263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!str)
5283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;
5293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ptpdatelen = strlen(str);
5303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (ptpdatelen >= sizeof (ptpdate)) {
5313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
5323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;
5333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
5343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	strcpy (ptpdate, str);
5353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (ptpdatelen<15) {
5363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
5373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;
5383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
5393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	memset(&tm,0,sizeof(tm));
5413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	strncpy (tmp, ptpdate, 4);
5423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tmp[4] = 0;
5433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tm.tm_year=atoi (tmp) - 1900;
5443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	strncpy (tmp, ptpdate + 4, 2);
5453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tmp[2] = 0;
5463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tm.tm_mon = atoi (tmp) - 1;
5473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	strncpy (tmp, ptpdate + 6, 2);
5483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tmp[2] = 0;
5493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tm.tm_mday = atoi (tmp);
5503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	strncpy (tmp, ptpdate + 9, 2);
5513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tmp[2] = 0;
5523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tm.tm_hour = atoi (tmp);
5533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	strncpy (tmp, ptpdate + 11, 2);
5543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tmp[2] = 0;
5553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tm.tm_min = atoi (tmp);
5563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	strncpy (tmp, ptpdate + 13, 2);
5573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tmp[2] = 0;
5583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tm.tm_sec = atoi (tmp);
5593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	tm.tm_isdst = -1;
5613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return mktime (&tm);
5633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
5643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
5663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
5673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
5683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint8_t filenamelen;
5693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint8_t capturedatelen;
5703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	char *capture_date;
5713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
5733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
5743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
5753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
5763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
5773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
5783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
5793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
5803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
5813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
5823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
5833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
5843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
5853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
5863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
5873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
5883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	capture_date = ptp_unpack_string(params, data,
5903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
5913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* subset of ISO 8601, without '.s' tenths of second and
5923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 * time zone
5933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 */
5943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
5953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	free(capture_date);
5963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* now the modification date ... */
5983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	capture_date = ptp_unpack_string(params, data,
5993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTP_oi_filenamelen+filenamelen*2
6003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		+capturedatelen*2+2,&capturedatelen);
6013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	oi->ModificationDate = ptp_unpack_PTPTIME(capture_date);
6023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	free(capture_date);
6033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
6043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* Custom Type Value Assignement (without Length) macro frequently used below */
6063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define CTVAL(target,func) {			\
6073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (total - *offset < sizeof(target))	\
6083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;			\
6093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	target = func(&data[*offset]);		\
6103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*offset += sizeof(target);		\
6113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
6123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define RARR(val,member,func)	{			\
6143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int n,j;					\
6153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (total - *offset < sizeof(uint32_t))		\
6163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;				\
6173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	n = dtoh32a (&data[*offset]);			\
6183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*offset += sizeof(uint32_t);			\
6193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev							\
6203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	val->a.count = n;				\
6213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
6223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!val->a.v) return 0;			\
6233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (j=0;j<n;j++)				\
6243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		CTVAL(val->a.v[j].member, func);	\
6253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
6263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline int
6283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_DPV (
6293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	PTPParams *params, unsigned char* data, int *offset, int total,
6303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	PTPPropertyValue* value, uint16_t datatype
6313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev) {
6323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (datatype) {
6333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_INT8:
6343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		CTVAL(value->i8,dtoh8a);
6353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_UINT8:
6373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		CTVAL(value->u8,dtoh8a);
6383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_INT16:
6403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		CTVAL(value->i16,dtoh16a);
6413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_UINT16:
6433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		CTVAL(value->u16,dtoh16a);
6443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_INT32:
6463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		CTVAL(value->i32,dtoh32a);
6473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_UINT32:
6493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		CTVAL(value->u32,dtoh32a);
6503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_INT64:
6523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		CTVAL(value->i64,dtoh64a);
6533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_UINT64:
6553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		CTVAL(value->u64,dtoh64a);
6563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_UINT128:
6593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		*offset += 16;
6603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/*fprintf(stderr,"unhandled unpack of uint128n");*/
6613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_INT128:
6633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		*offset += 16;
6643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/*fprintf(stderr,"unhandled unpack of int128n");*/
6653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AINT8:
6703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		RARR(value,i8,dtoh8a);
6713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AUINT8:
6733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		RARR(value,u8,dtoh8a);
6743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AUINT16:
6763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		RARR(value,u16,dtoh16a);
6773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AINT16:
6793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		RARR(value,i16,dtoh16a);
6803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AUINT32:
6823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		RARR(value,u32,dtoh32a);
6833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AINT32:
6853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		RARR(value,i32,dtoh32a);
6863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AUINT64:
6883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		RARR(value,u64,dtoh64a);
6893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AINT64:
6913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		RARR(value,i64,dtoh64a);
6923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
6933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* XXX: other int types are unimplemented */
6943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* XXX: other int arrays are unimplemented also */
6953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_STR: {
6963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint8_t len;
6973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/* XXX: max size */
6983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		value->str = ptp_unpack_string(params,data,*offset,&len);
6993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		*offset += len*2+1;
7003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!value->str)
7013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			return 1;
7023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
7033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
7043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	default:
7053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;
7063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
7073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return 1;
7083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
7093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* Device Property pack/unpack */
7113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_dpd_DevicePropertyCode	0
7133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_dpd_DataType		2
7143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_dpd_GetSet			4
7153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_dpd_FactoryDefaultValue	5
7163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline int
7183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
7193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
7203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int offset=0, ret;
7213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	memset (dpd, 0, sizeof(*dpd));
7233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
7243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
7253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
7263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	dpd->FormFlag=PTP_DPFF_None;
7273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	offset = PTP_dpd_FactoryDefaultValue;
7293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
7303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!ret) goto outofmemory;
7313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if ((dpd->DataType == PTP_DTC_STR) && (offset == dpdlen))
7323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 1;
7333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
7343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!ret) goto outofmemory;
7353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* if offset==0 then Data Type format is not supported by this
7373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	   code or the Data Type is a string (with two empty strings as
7383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	   values). In both cases Form Flag should be set to 0x00 and FORM is
7393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	   not present. */
7403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (offset==PTP_dpd_FactoryDefaultValue)
7423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 1;
7433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	dpd->FormFlag=dtoh8a(&data[offset]);
7453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	offset+=sizeof(uint8_t);
7463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (dpd->FormFlag) {
7483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DPFF_Range:
7493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
7503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!ret) goto outofmemory;
7513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
7523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!ret) goto outofmemory;
7533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
7543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!ret) goto outofmemory;
7553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
7563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DPFF_Enumeration: {
7573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		int i;
7583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define N	dpd->FORM.Enum.NumberOfValues
7593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		N = dtoh16a(&data[offset]);
7603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		offset+=sizeof(uint16_t);
7613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
7623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!dpd->FORM.Enum.SupportedValue)
7633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			goto outofmemory;
7643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
7663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<N;i++) {
7673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
7683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			/* Slightly different handling here. The HP PhotoSmart 120
7703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 * specifies an enumeration with N in wrong endian
7713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 * 00 01 instead of 01 00, so we count the enum just until the
7723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 * the end of the packet.
7733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 */
7743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (!ret) {
7753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				if (!i)
7763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					goto outofmemory;
7773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				dpd->FORM.Enum.NumberOfValues = i;
7783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				break;
7793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
7803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
7813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
7823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
7833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#undef N
7843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return 1;
7853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevoutofmemory:
7863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ptp_free_devicepropdesc(dpd);
7873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return 0;
7883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
7893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* (MTP) Object Property pack/unpack */
7913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_opd_ObjectPropertyCode	0
7923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_opd_DataType		2
7933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_opd_GetSet			4
7943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_opd_FactoryDefaultValue	5
7953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline int
7973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
7983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
7993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int offset=0, ret;
8003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	memset (opd, 0, sizeof(*opd));
8023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
8033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
8043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
8053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	offset = PTP_opd_FactoryDefaultValue;
8073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
8083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!ret) goto outofmemory;
8093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	opd->GroupCode=dtoh32a(&data[offset]);
8113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	offset+=sizeof(uint32_t);
8123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	opd->FormFlag=dtoh8a(&data[offset]);
8143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	offset+=sizeof(uint8_t);
8153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (opd->FormFlag) {
8173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPFF_Range:
8183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
8193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!ret) goto outofmemory;
8203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
8213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!ret) goto outofmemory;
8223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
8233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!ret) goto outofmemory;
8243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
8253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPFF_Enumeration: {
8263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		int i;
8273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define N	opd->FORM.Enum.NumberOfValues
8283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		N = dtoh16a(&data[offset]);
8293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		offset+=sizeof(uint16_t);
8303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
8313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!opd->FORM.Enum.SupportedValue)
8323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			goto outofmemory;
8333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
8353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<N;i++) {
8363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
8373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			/* Slightly different handling here. The HP PhotoSmart 120
8393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 * specifies an enumeration with N in wrong endian
8403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 * 00 01 instead of 01 00, so we count the enum just until the
8413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 * the end of the packet.
8423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 */
8433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (!ret) {
8443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				if (!i)
8453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					goto outofmemory;
8463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				opd->FORM.Enum.NumberOfValues = i;
8473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				break;
8483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
8493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
8503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#undef N
8513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
8523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
8533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return 1;
8543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevoutofmemory:
8553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ptp_free_objectpropdesc(opd);
8563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return 0;
8573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
8583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
8613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
8623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
8633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned char* dpv=NULL;
8643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t size=0;
8653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int	i;
8663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (datatype) {
8683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_INT8:
8693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(int8_t);
8703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
8713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod8a(dpv,value->i8);
8723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
8733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_UINT8:
8743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint8_t);
8753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
8763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod8a(dpv,value->u8);
8773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
8783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_INT16:
8793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(int16_t);
8803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
8813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod16a(dpv,value->i16);
8823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
8833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_UINT16:
8843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint16_t);
8853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
8863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod16a(dpv,value->u16);
8873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
8883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_INT32:
8893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(int32_t);
8903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
8913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->i32);
8923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
8933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_UINT32:
8943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint32_t);
8953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
8963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->u32);
8973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
8983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_INT64:
8993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(int64_t);
9003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod64a(dpv,value->i64);
9023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_UINT64:
9043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint64_t);
9053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod64a(dpv,value->u64);
9073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AUINT8:
9093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
9103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->a.count);
9123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<value->a.count;i++)
9133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
9143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AINT8:
9163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
9173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->a.count);
9193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<value->a.count;i++)
9203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
9213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AUINT16:
9233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
9243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->a.count);
9263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<value->a.count;i++)
9273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
9283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AINT16:
9303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
9313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->a.count);
9333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<value->a.count;i++)
9343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
9353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AUINT32:
9373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
9383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->a.count);
9403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<value->a.count;i++)
9413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
9423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AINT32:
9443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
9453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->a.count);
9473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<value->a.count;i++)
9483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
9493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AUINT64:
9513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
9523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->a.count);
9543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<value->a.count;i++)
9553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
9563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_AINT64:
9583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
9593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=malloc(size);
9603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(dpv,value->a.count);
9613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<value->a.count;i++)
9623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
9633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* XXX: other int types are unimplemented */
9653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_DTC_STR: {
9663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		dpv=ptp_get_packed_stringcopy(params, value->str, &size);
9673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
9683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
9693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
9703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*dpvptr=dpv;
9713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return size;
9723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
9733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
9743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define MAX_MTP_PROPS 127
9753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
9763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
9773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
9783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned char* opldata;
9793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	MTPProperties *propitr;
9803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned char *packedprops[MAX_MTP_PROPS];
9813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t packedpropslens[MAX_MTP_PROPS];
9823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t packedobjecthandles[MAX_MTP_PROPS];
9833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint16_t packedpropsids[MAX_MTP_PROPS];
9843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint16_t packedpropstypes[MAX_MTP_PROPS];
9853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t totalsize = 0;
9863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t bufp = 0;
9873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t noitems = 0;
9883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t i;
9893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
9903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
9913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	propitr = props;
9923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	while (nrofprops-- && noitems < MAX_MTP_PROPS) {
9933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/* Object Handle */
9943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		packedobjecthandles[noitems]=propitr->ObjectHandle;
9953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		totalsize += sizeof(uint32_t); /* Object ID */
9963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/* Metadata type */
9973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		packedpropsids[noitems]=propitr->property;
9983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		totalsize += sizeof(uint16_t);
9993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/* Data type */
10003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		packedpropstypes[noitems]= propitr->datatype;
10013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		totalsize += sizeof(uint16_t);
10023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/* Add each property to be sent. */
10033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	        packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
10043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		totalsize += packedpropslens[noitems];
10053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		noitems ++;
10063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		propitr ++;
10073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
10083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* Allocate memory for the packed property list */
10103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	opldata = malloc(totalsize);
10113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(&opldata[bufp],noitems);
10133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	bufp += 4;
10143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* Copy into a nice packed list */
10163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i = 0; i < noitems; i++) {
10173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/* Object ID */
10183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(&opldata[bufp],packedobjecthandles[i]);
10193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		bufp += sizeof(uint32_t);
10203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod16a(&opldata[bufp],packedpropsids[i]);
10213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		bufp += sizeof(uint16_t);
10223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod16a(&opldata[bufp],packedpropstypes[i]);
10233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		bufp += sizeof(uint16_t);
10243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/* The copy the actual property */
10253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
10263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		bufp += packedpropslens[i];
10273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		free(packedprops[i]);
10283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
10293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*opldataptr = opldata;
10303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return totalsize;
10313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
10323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int
10343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev_compare_func(const void* x, const void *y) {
10353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	const MTPProperties *px = x;
10363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	const MTPProperties *py = y;
10373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return px->ObjectHandle - py->ObjectHandle;
10393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
10403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline int
10423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
10433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
10443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t prop_count = dtoh32a(data);
10453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	MTPProperties *props = NULL;
10463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int offset = 0, i;
10473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (prop_count == 0) {
10493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		*pprops = NULL;
10503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;
10513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
10523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
10533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	data += sizeof(uint32_t);
10543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	len -= sizeof(uint32_t);
10553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	props = malloc(prop_count * sizeof(MTPProperties));
10563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!props) return 0;
10573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i = 0; i < prop_count; i++) {
10583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (len <= 0) {
10593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
10603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL", i);
10613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i);
10623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			qsort (props, i, sizeof(MTPProperties),_compare_func);
10633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			*pprops = props;
10643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			return i;
10653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
10663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		props[i].ObjectHandle = dtoh32a(data);
10673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		data += sizeof(uint32_t);
10683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		len -= sizeof(uint32_t);
10693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		props[i].property = dtoh16a(data);
10713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		data += sizeof(uint16_t);
10723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		len -= sizeof(uint16_t);
10733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		props[i].datatype = dtoh16a(data);
10753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		data += sizeof(uint16_t);
10763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		len -= sizeof(uint16_t);
10773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		offset = 0;
10793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype);
10803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		data += offset;
10813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		len -= offset;
10823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
10833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
10843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*pprops = props;
10853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return prop_count;
10863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
10873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/*
10893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTP USB Event container unpack
10903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    Copyright (c) 2003 Nikolai Kopanygin
10913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev*/
10923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ec_Length		0
10943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ec_Type		4
10953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ec_Code		6
10963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ec_TransId		8
10973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ec_Param1		12
10983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ec_Param2		16
10993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ec_Param3		20
11003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
11023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
11033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
11043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int	length;
11053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int	type;
11063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (data==NULL)
11083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return;
11093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	memset(ec,0,sizeof(*ec));
11103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	length=dtoh32a(&data[PTP_ec_Length]);
11113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	type = dtoh16a(&data[PTP_ec_Type]);
11123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ec->Code=dtoh16a(&data[PTP_ec_Code]);
11143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
11153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (type!=PTP_USB_CONTAINER_EVENT) {
11173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ptp_debug (params, "Unknown canon event type %d (code=%x,tid=%x), please report!",type,ec->Code,ec->Transaction_ID);
11183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return;
11193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
11203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (length>=(PTP_ec_Param1+4)) {
11213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
11223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ec->Nparam=1;
11233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
11243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (length>=(PTP_ec_Param2+4)) {
11253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
11263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ec->Nparam=2;
11273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
11283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (length>=(PTP_ec_Param3+4)) {
11293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
11303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ec->Nparam=3;
11313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
11323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
11333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/*
11353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTP Canon Folder Entry unpack
11363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    Copyright (c) 2003 Nikolai Kopanygin
11373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev*/
11383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_cfe_ObjectHandle		0
11393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_cfe_ObjectFormatCode	4
11403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_cfe_Flags			6
11413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_cfe_ObjectSize		7
11423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_cfe_Time			11
11433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_cfe_Filename		15
11443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
11463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
11473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
11483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int i;
11493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (data==NULL)
11503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return;
11513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
11523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
11533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
11543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
11553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
11563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
11573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
11583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
11593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint16_t
11613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
11623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
11633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/*
11643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  EOS ImageFormat entries (of at least the 5DMII and the 400D ) look like this:
11653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32: number of entries / generated files (1 or 2)
11663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32: size of this entry in bytes (most likely allways 0x10)
11673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32: image type (1 == JPG, 6 == RAW)
11683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32: image size (0 == Large, 1 == Medium, 2 == Small)
11693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW)
11703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  If number of entries is 2 the last uint32 repeat.
11713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  example:
11733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		0: 0x       1
11743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		1: 0x      10
11753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		2: 0x       6
11763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		3: 0x       1
11773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		4: 0x       4
11783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  The idea is to simply 'condense' these values to just one uint16 to be able to conveniontly
11803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  use the available enumeration facilities (look-up table). The image size and compression
11813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  values fully describe the image format. Hence we generate a uint16 with the four nibles set
11823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  as follows: entry 1 size | entry 1 compression | entry 2 size | entry 2 compression.
11833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  The above example would result in the value 0x1400.
11843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  */
11853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	const unsigned char* d = *data;
11873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t n = dtoh32a( d );
11883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t l, s1, c1, s2 = 0, c2 = 0;
11893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (n != 1 && n !=2) {
11913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
11923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;
11933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
11943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	l = dtoh32a( d+=4 );
11963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (l != 0x10) {
11973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
11983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;
11993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
12003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	d+=4; /* skip type */
12023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	s1 = dtoh32a( d+=4 );
12033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	c1 = dtoh32a( d+=4 );
12043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (n == 2) {
12063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		l = dtoh32a( d+=4 );
12073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (l != 0x10) {
12083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
12093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			return 0;
12103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
12113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		d+=4; /* skip type */
12123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		s2 = dtoh32a( d+=4 );
12133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		c2 = dtoh32a( d+=4 );
12143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
12153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*data = (unsigned char*) d+4;
12173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
12193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
12203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
12223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
12233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
12243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t n = (value & 0xFF) ? 2 : 1;
12253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t s = 4 + 0x10 * n;
12263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if( !data )
12283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return s;
12293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(data+=0, n);
12313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(data+=4, 0x10);
12323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(data+=4, ((value >> 8) & 0xF) == 4 ? 6 : 1);
12333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(data+=4, (value >> 12) & 0xF);
12343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(data+=4, (value >> 8) & 0xF);
12353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (n==2) {
12373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(data+=4, 0x10);
12383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(data+=4, ((value >> 0) & 0xF) == 4 ? 6 : 1);
12393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(data+=4, (value >> 4) & 0xF);
12403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod32a(data+=4, (value >> 0) & 0xF);
12413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
12423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return s;
12443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
12453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/*
12473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTP EOS Changes Entry unpack
12483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev*/
12493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_Size		0
12503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_Type		4
12513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_Prop_Subtype	8	/* only for properties */
12533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_Prop_Val_Data	0xc	/* only for properties */
12543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_Prop_Desc_Type	0xc	/* only for property descs */
12553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_Prop_Desc_Count	0x10	/* only for property descs */
12563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_Prop_Desc_Data	0x14	/* only for property descs */
12573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* for PTP_EC_CANON_EOS_RequestObjectTransfer */
12593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OI_ObjectID	8
12603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OI_OFC		0x0c
12613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OI_Size		0x14
12623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OI_Name		0x1c
12633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* for PTP_EC_CANON_EOS_ObjectAddedEx */
12653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OA_ObjectID	8
12663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OA_StorageID	0x0c
12673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OA_OFC		0x10
12683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OA_Size		0x1c
12693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OA_Parent	0x20
12703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_ece_OA_Name		0x28
12713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline int
12733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **ce)
12743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
12753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int	i = 0, entries = 0;
12763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned char	*curdata = data;
12773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (data==NULL)
12793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return 0;
12803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	while (curdata - data < datasize) {
12813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
12823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
12833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		curdata += size;
12853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if ((size == 8) && (type == 0))
12863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			break;
12873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		entries++;
12883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
12893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
12903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!*ce) return 0;
12913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	curdata = data;
12933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	while (curdata - data < datasize) {
12943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
12953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
12963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
12983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		switch (type) {
12993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		case  PTP_EC_CANON_EOS_ObjectAddedEx:
13003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
13013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
13023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.StorageID 		= dtoh32a(&curdata[PTP_ece_OA_StorageID]);
13033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.ParentObject	= dtoh32a(&curdata[PTP_ece_OA_Parent]);
13043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OA_OFC]);
13053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
13063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OA_Name]));
13073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			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);
13083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			break;
13093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		case  PTP_EC_CANON_EOS_RequestObjectTransfer:
13103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
13113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
13123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.StorageID 		= 0; /* use as marker */
13133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OI_OFC]);
13143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.ParentObject	= 0; /* check, but use as marker */
13153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
13163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OI_Name]));
13173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			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);
13193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			break;
13203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		case  PTP_EC_CANON_EOS_AvailListChanged: {	/* property desc */
13213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
13223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			uint32_t	propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
13233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			uint32_t	propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
13243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			unsigned char	*data = &curdata[PTP_ece_Prop_Desc_Data];
13253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			int		j;
13263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			PTPDevicePropDesc	*dpd;
13273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype);
13293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			for (j=0;j<params->nrofcanon_props;j++)
13303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				if (params->canon_props[j].proptype == proptype)
13313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
13323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (j==params->nrofcanon_props) {
13333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
13343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				break;
13353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
13363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			dpd = &params->canon_props[j].dpd;
13373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			/* 1 - uint16 ?
13383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 * 3 - uint16
13393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 * 7 - string?
13403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 */
13413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (propxtype != 3) {
13423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled.", i, propxtype, proptype);
13433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++)
13443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params, "    %d: %02x", j, data[j]);
13453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				break;
13463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
13473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (! propxcnt)
13483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				break;
13493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
13513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				   i, propxtype, proptype, dpd->DataType, propxcnt);
13523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			dpd->FormFlag = PTP_DPFF_Enumeration;
13533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			dpd->FORM.Enum.NumberOfValues = propxcnt;
13543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
13553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			switch (proptype) {
13573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			case PTP_DPC_CANON_EOS_ImageFormat:
13583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			case PTP_DPC_CANON_EOS_ImageFormatCF:
13593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			case PTP_DPC_CANON_EOS_ImageFormatSD:
13603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			case PTP_DPC_CANON_EOS_ImageFormatExtHD:
13613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				/* special handling of ImageFormat properties */
13623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				for (j=0;j<propxcnt;j++) {
13633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->FORM.Enum.SupportedValue[j].u16 =
13643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev							dtoh16( ptp_unpack_EOS_ImageFormat( params, &data ) );
13653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
13663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
13673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				break;
13683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			default:
13693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				/* 'normal' enumerated types */
13703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				switch (dpd->DataType) {
13713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define XX( TYPE, CONV )\
13723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					for (j=0;j<propxcnt;j++) { \
13733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(data); \
13743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(data)); \
13753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						data += 4; /* might only be for propxtype 3 */ \
13763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					} \
13773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
13783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DTC_INT16:	XX( i16, dtoh16a );
13803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DTC_UINT32:	XX( u32, dtoh32a );
13813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DTC_UINT16:	XX( u16, dtoh16a );
13823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DTC_UINT8:	XX( u8,  dtoh8a );
13833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#undef XX
13843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				default:
13853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, raw values:", i, dpd->DataType, proptype, dtoh32a(data));
13863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, data+=4) /* 4 is good for propxtype 3 */
13873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						ptp_debug (params, "    %3d: 0x%8x", j, dtoh32a(data));
13883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
13893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
13903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
13913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			break;
13923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
13933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		case PTP_EC_CANON_EOS_PropValueChanged:
13943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (size >= 0xc) {	/* property info */
13953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				int j;
13963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
13973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				unsigned char	*data = &curdata[PTP_ece_Prop_Val_Data];
13983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				PTPDevicePropDesc	*dpd;
13993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				ptp_debug (params, "event %d: EOS prop %04x info record, datasize is %d", i, proptype, size-PTP_ece_Prop_Val_Data);
14013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				for (j=0;j<params->nrofcanon_props;j++)
14023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					if (params->canon_props[j].proptype == proptype)
14033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						break;
14043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				if (j<params->nrofcanon_props) {
14053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					if (	(params->canon_props[j].size != size) ||
14063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						(memcmp(params->canon_props[j].data,data,size-PTP_ece_Prop_Val_Data))) {
14073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
14083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						memcpy (params->canon_props[j].data,data,size-PTP_ece_Prop_Val_Data);
14093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					}
14103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				} else {
14113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					if (j)
14123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
14133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					else
14143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						params->canon_props = malloc(sizeof(params->canon_props[0]));
14153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					params->canon_props[j].type = type;
14163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					params->canon_props[j].proptype = proptype;
14173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					params->canon_props[j].size = size;
14183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
14193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					memcpy(params->canon_props[j].data, data, size-PTP_ece_Prop_Val_Data);
14203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
14213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					params->canon_props[j].dpd.GetSet = 1;
14223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
14233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					params->nrofcanon_props = j+1;
14243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
14253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				dpd = &params->canon_props[j].dpd;
14263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				/* fix GetSet value */
14283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				switch (proptype) {
14293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define XX(x) case PTP_DPC_CANON_##x:
14303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_FocusMode)
14313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_BatteryPower)
14323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_BatterySelect)
14333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_ModelID)
14343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_PTPExtensionVersion)
14353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_DPOFVersion)
14363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_AvailableShots)
14373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_CurrentStorage)
14383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_CurrentFolder)
14393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_MyMenu)
14403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_MyMenuList)
14413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_HDDirectoryStructure)
14423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_BatteryInfo)
14433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_AdapterInfo)
14443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_LensStatus)
14453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_CardExtension)
14463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_TempStatus)
14473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_ShutterCounter)
14483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_SerialNumber)
14493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_DepthOfFieldPreview)
14503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_EVFRecordStatus)
14513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_LvAfSystem)
14523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_FocusInfoEx)
14533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_DepthOfField)
14543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_Brightness)
14553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_EFComp)
14563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_LensName)
14573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					XX(EOS_LensID)
14583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#undef XX
14593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						dpd->GetSet = PTP_DPGS_Get;
14603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						break;
14613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
14623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				/* set DataType */
14643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				switch (proptype) {
14653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CameraTime:
14663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_EVFOutputDevice:
14673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_AvailableShots:
14683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CaptureDestination:
14693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_WhiteBalanceXA:
14703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_WhiteBalanceXB:
14713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_QuickReviewTime:
14723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CurrentStorage:
14733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CurrentFolder:
14743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ShutterCounter:
14753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ModelID:
14763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_LensID:
14773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_StroboFiring:
14783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->DataType = PTP_DTC_UINT32;
14793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
14803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_Aperture:
14813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ShutterSpeed:
14823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ISOSpeed:
14833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_FocusMode:
14843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_AutoExposureMode:
14853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ColorSpace:
14863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_BatteryPower:
14873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_PTPExtensionVersion:
14883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_DriveMode:
14893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_AEB:
14903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->DataType = PTP_DTC_UINT16;
14913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
14923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_PictureStyle:
14933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_WhiteBalance:
14943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_MeteringMode:
14953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ExpCompensation: /* actually int8 if you calculate */
14963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->DataType = PTP_DTC_UINT8;
14973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
14983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_Owner:
14993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_Artist:
15003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_Copyright:
15013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_SerialNumber:
15023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_LensName:
15033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->DataType = PTP_DTC_STR;
15043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
15053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
15063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
15073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->DataType = PTP_DTC_INT16;
15083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
15093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				/* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
15103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_BatterySelect:
15113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case 0xd114:
15123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_DPOFVersion:
15133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_BracketMode:
15143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->DataType = PTP_DTC_UINT16;
15153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
15163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
15173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						ptp_debug (params, "    %d: %02x", j, data[j]);
15183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
15193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc1:
15203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc2:
15213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc3:
15223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc4:
15233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc5:
15243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc6:
15253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc7:
15263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc8:
15273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc9:
15283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc10:
15293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFunc11:
15303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->DataType = PTP_DTC_UINT8;
15313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint8", i ,proptype, size-PTP_ece_Prop_Val_Data);
15323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
15333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						ptp_debug (params, "    %d: %02x", j, data[j]);
15343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					/* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */
15353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					data += 4;
15363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
15373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				/* yet unknown 32bit props */
15383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ColorTemperature:
15393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_WftStatus:
15403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_LensStatus:
15413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CardExtension:
15423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_TempStatus:
15433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_PhotoStudioMode:
15443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_EVFMode:
15453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_DepthOfFieldPreview:
15463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_EVFSharpness:
15473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_EVFWBMode:
15483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
15493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_EVFColorTemp:
15503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_EVFRecordStatus:
15513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ExposureSimMode:
15523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_LvAfSystem:
15533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_MovSize:
15543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_DepthOfField:
15553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_LvViewTypeSelect:
15563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ImageFormat:
15573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ImageFormatCF:
15583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ImageFormatSD:
15593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
15603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_CustomFuncEx:
15613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev//					dpd->DataType = PTP_DTC_UINT32;
15623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
15633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
15643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
15653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
15663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						ptp_debug (params, "    %d: 0x%8x", j, ((uint32_t*)data)[j]);
15673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
15683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				default:
15693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
15703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
15713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						ptp_debug (params, "    %d: %02x", j, data[j]);
15723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
15733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
15743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				switch (dpd->DataType) {
15753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DTC_UINT32:
15763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->FactoryDefaultValue.u32	= dtoh32a(data);
15773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->CurrentValue.u32		= dtoh32a(data);
15783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
15793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
15803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DTC_UINT16:
15813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->FactoryDefaultValue.u16	= dtoh16a(data);
15823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->CurrentValue.u16		= dtoh16a(data);
15833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
15843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
15853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DTC_UINT8:
15863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->FactoryDefaultValue.u8	= dtoh8a(data);
15873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->CurrentValue.u8		= dtoh8a(data);
15883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
15893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
15903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DTC_STR: {
15913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
15923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					uint8_t len = 0;
15933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->FactoryDefaultValue.str	= ptp_unpack_string(params, data, 0, &len);
15943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->CurrentValue.str		= ptp_unpack_string(params, data, 0, &len);
15953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
15963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->FactoryDefaultValue.str	= strdup( (char*)data );
15973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->CurrentValue.str		= strdup( (char*)data );
15983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
15993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
16003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
16013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
16023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				default:
16033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					/* debug is printed in switch above this one */
16043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
16053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
16063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				/* ImageFormat special handling */
16083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				switch (proptype) {
16093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ImageFormat:
16103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ImageFormatCF:
16113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ImageFormatSD:
16123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
16133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->DataType = PTP_DTC_UINT16;
16143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->FactoryDefaultValue.u16	= ptp_unpack_EOS_ImageFormat( params, &data );
16153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					dpd->CurrentValue.u16		= dpd->FactoryDefaultValue.u16;
16163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
16173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					break;
16183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
16193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				break;
16213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
16223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		case 0: /* end marker */
16233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (size == 8) /* no output */
16243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				break;
16253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
16263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			break;
16273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		default:
16283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			switch (type) {
16293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define XX(x)		case PTP_EC_CANON_EOS_##x: ptp_debug (params, "event %d: unhandled EOS event "#x" (size %d)", i, size);break;
16303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(RequestGetEvent)
16313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(ObjectRemoved)
16323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(RequestGetObjectInfoEx)
16333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(StorageStatusChanged)
16343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(StorageInfoChanged)
16353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(ObjectInfoChangedEx)
16363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(ObjectContentChanged)
16373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(CameraStatusChanged)
16383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(WillSoonShutdown)
16393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(ShutdownTimerUpdated)
16403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(RequestCancelTransfer)
16413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(RequestObjectTransferDT)
16423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(RequestCancelTransferDT)
16433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(StoreAdded)
16443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(StoreRemoved)
16453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(BulbExposureTime)
16463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(RecordingTime)
16473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(RequestObjectTransferTS)
16483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			XX(AfResult)
16493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#undef XX
16503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			default:
16513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
16523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				break;
16533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
16543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (size >= 0x8) {	/* event info */
16553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				int j;
16563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				for (j=8;j<size;j++)
16573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					ptp_debug (params, "    %d: %02x", j, curdata[j]);
16583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
16593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
16603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			break;
16613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
16623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		curdata += size;
16633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		i++;
16643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if ((size == 8) && (type == 0))
16653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			break;
16663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
16673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return entries;
16693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
16703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/*
16723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTP USB Event container unpack for Nikon events.
16733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev*/
16743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_nikon_ec_Length		0
16753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_nikon_ec_Code		2
16763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_nikon_ec_Param1		4
16773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define PTP_nikon_ec_Size		6
16783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline void
16793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, int *cnt)
16803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
16813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int i;
16823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*ec = NULL;
16843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (data == NULL)
16853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return;
16863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (len < PTP_nikon_ec_Code)
16873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return;
16883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
16893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
16903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		return;
16913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*ec = malloc(sizeof(PTPContainer)*(*cnt));
16923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<*cnt;i++) {
16943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		memset(&(*ec)[i],0,sizeof(PTPContainer));
16953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		(*ec)[i].Code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
16963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		(*ec)[i].Param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
16973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		(*ec)[i].Nparam	= 1;
16983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
16993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
17003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint32_t
17033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
17043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	int i, len = 0;
17053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint8_t	retlen;
17063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned char *curdata;
17073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	len =	2*(strlen(text->title)+1)+1+
17093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		2*(strlen(text->line[0])+1)+1+
17103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		2*(strlen(text->line[1])+1)+1+
17113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		2*(strlen(text->line[2])+1)+1+
17123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		2*(strlen(text->line[3])+1)+1+
17133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		2*(strlen(text->line[4])+1)+1+
17143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		4*2+2*4+2+4+2+5*4*2;
17153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*data = malloc(len);
17163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!*data) return 0;
17173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	curdata = *data;
17193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(curdata,100);curdata+=2;
17203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(curdata,1);curdata+=2;
17213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(curdata,0);curdata+=2;
17223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(curdata,1000);curdata+=2;
17233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(curdata,0);curdata+=4;
17253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(curdata,0);curdata+=4;
17263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(curdata,6);curdata+=2;
17283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod32a(curdata,0);curdata+=4;
17293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
17313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	htod16a(curdata,0x10);curdata+=2;
17323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<5;i++) {
17343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
17353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod16a(curdata,0x10);curdata+=2;
17363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod16a(curdata,0x01);curdata+=2;
17373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod16a(curdata,0x02);curdata+=2;
17383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		htod16a(curdata,0x06);curdata+=2;
17393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
17403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return len;
17413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
17423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_version	0x00
17443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_ofc	0x02
17453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_unk1	0x04
17463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_objectid	0x08
17473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_parentid	0x0c
17483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_previd	0x10	/* in same dir */
17493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_nextid	0x14	/* in same dir */
17503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_nextchild	0x18	/* down one dir */
17513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_storageid	0x1c	/* only in storage entry */
17523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_name	0x20
17533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_flags	0x2c
17543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_size	0x30
17553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_unixtime	0x34
17563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_year	0x38
17573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_month	0x39
17583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_mday	0x3a
17593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_hour	0x3b
17603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_minute	0x3c
17613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_second	0x3d
17623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_unk2	0x3e
17633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_thumbsize	0x40
17643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_width	0x44
17653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ptp_canon_dir_height	0x48
17663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic inline uint16_t
17683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevptp_unpack_canon_directory (
17693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	PTPParams		*params,
17703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned char		*dir,
17713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t		cnt,
17723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	PTPObjectHandles	*handles,
17733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	PTPObjectInfo		**oinfos,	/* size(handles->n) */
17743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	uint32_t		**flags		/* size(handles->n) */
17753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev) {
17763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	unsigned int	i, j, nrofobs = 0, curob = 0;
17773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
17793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<cnt;i++)
17803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (ISOBJECT(dir+i*0x4c)) nrofobs++;
17813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	handles->n = nrofobs;
17823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs);
17833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!handles->Handler) return PTP_RC_GeneralError;
17843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*oinfos = calloc(sizeof((*oinfos)[0]),nrofobs);
17853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!*oinfos) return PTP_RC_GeneralError;
17863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	*flags  = calloc(sizeof((*flags)[0]),nrofobs);
17873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!*flags) return PTP_RC_GeneralError;
17883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* Migrate data into objects ids, handles into
17903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 * the object handler array.
17913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 */
17923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	curob = 0;
17933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<cnt;i++) {
17943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		unsigned char	*cur = dir+i*0x4c;
17953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		PTPObjectInfo	*oi = (*oinfos)+curob;
17963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!ISOBJECT(cur))
17983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			continue;
17993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
18013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oi->StorageID		= 0xffffffff;
18023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oi->ObjectFormat	= dtoh16a(cur + ptp_canon_dir_ofc);
18033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oi->ParentObject	= dtoh32a(cur + ptp_canon_dir_parentid);
18043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oi->Filename		= strdup((char*)(cur + ptp_canon_dir_name));
18053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
18063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oi->ThumbCompressedSize	= dtoh32a(cur + ptp_canon_dir_thumbsize);
18073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oi->ImagePixWidth	= dtoh32a(cur + ptp_canon_dir_width);
18083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oi->ImagePixHeight	= dtoh32a(cur + ptp_canon_dir_height);
18093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		oi->CaptureDate		= oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
18103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		(*flags)[curob]		= dtoh32a(cur + ptp_canon_dir_flags);
18113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		curob++;
18123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
18133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* Walk over Storage ID entries and distribute the IDs to
18143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 * the parent objects. */
18153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<cnt;i++) {
18163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		unsigned char	*cur = dir+i*0x4c;
18173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
18183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (ISOBJECT(cur))
18203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			continue;
18213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
18223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (j == handles->n) continue;
18233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		(*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
18243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
18253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	/* Walk over all objects and distribute the storage ids */
18263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	while (1) {
18273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		int changed = 0;
18283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for (i=0;i<cnt;i++) {
18293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			unsigned char	*cur = dir+i*0x4c;
18303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			uint32_t	oid = dtoh32a(cur + ptp_canon_dir_objectid);
18313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			uint32_t	nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
18323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
18333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			uint32_t	storageid;
18343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (!ISOBJECT(cur))
18363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				continue;
18373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
18383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (j == handles->n) {
18393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				/*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
18403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				continue;
18413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
18423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 		storageid = (*oinfos)[j].StorageID;
18433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (storageid == 0xffffffff) continue;
18443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (nextoid != 0xffffffff) {
18453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
18463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				if (j == handles->n) {
18473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					/*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
18483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					continue;
18493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
18503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				if ((*oinfos)[j].StorageID == 0xffffffff) {
18513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					(*oinfos)[j].StorageID = storageid;
18523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					changed++;
18533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
18543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
18553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			if (nextchild != 0xffffffff) {
18563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
18573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				if (j == handles->n) {
18583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					/*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
18593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					continue;
18603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
18613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				if ((*oinfos)[j].StorageID == 0xffffffff) {
18623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					(*oinfos)[j].StorageID = storageid;
18633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					changed++;
18643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				}
18653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			}
18663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
18673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		/* Check if we:
18683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		 * - changed no entry (nothing more to do)
18693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		 * - changed all of them at once (usually happens)
18703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		 * break if we do.
18713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		 */
18723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (!changed || (changed==nrofobs-1))
18733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			break;
18743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
18753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#undef ISOBJECT
18763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return PTP_RC_OK;
18773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
1878