ptp-pack.c revision d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33
1b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/* currently this file is included into ptp.c */
2eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
36db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#ifdef HAVE_ICONV
4a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij#include <iconv.h>
56db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#endif
6a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
7b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
8eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod16p (PTPParams *params, uint16_t var)
9eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
10eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
11eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
12eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
13b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
14eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod32p (PTPParams *params, uint32_t var)
15eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
16eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
17eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
18eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
19b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
20eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod16ap (PTPParams *params, unsigned char *a, uint16_t val)
21eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
22eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (params->byteorder==PTP_DL_LE)
23b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htole16a(a,val);
24e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	else
25eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		htobe16a(a,val);
26eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
27eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
28b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
29eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod32ap (PTPParams *params, unsigned char *a, uint32_t val)
30eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
31eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (params->byteorder==PTP_DL_LE)
32b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htole32a(a,val);
33e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	else
34eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		htobe32a(a,val);
35eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
36eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
37abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijstatic inline void
38abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijhtod64ap (PTPParams *params, unsigned char *a, uint64_t val)
39abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij{
40abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	if (params->byteorder==PTP_DL_LE)
41abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htole64a(a,val);
42e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	else
43abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htobe64a(a,val);
44abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij}
45abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
46b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
47eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh16p (PTPParams *params, uint16_t var)
48eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
49eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
50eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
51eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
52b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
53eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh32p (PTPParams *params, uint32_t var)
54eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
55eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
56eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
57eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
58abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijstatic inline uint64_t
59abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijdtoh64p (PTPParams *params, uint64_t var)
60abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij{
61abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	return ((params->byteorder==PTP_DL_LE)?le64toh(var):be64toh(var));
62abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij}
63abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
64b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijdtoh16ap (PTPParams *params, const unsigned char *a)
66eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
67eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
68eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
69eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
70b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijdtoh32ap (PTPParams *params, const unsigned char *a)
72eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
73eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
74eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
75eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
76b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint64_t
771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijdtoh64ap (PTPParams *params, const unsigned char *a)
78eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
79abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a));
80eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
81eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
82b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod8a(a,x)	*(uint8_t*)(a) = x
83b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16a(a,x)	htod16ap(params,a,x)
84b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32a(a,x)	htod32ap(params,a,x)
85abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define htod64a(a,x)	htod64ap(params,a,x)
86b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16(x)	htod16p(params,x)
87b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32(x)	htod32p(params,x)
88abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define htod64(x)	htod64p(params,x)
89b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
90b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh8a(x)	(*(uint8_t*)(x))
91b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16a(a)	dtoh16ap(params,a)
92b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32a(a)	dtoh32ap(params,a)
93b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh64a(a)	dtoh64ap(params,a)
94b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16(x)	dtoh16p(params,x)
95b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32(x)	dtoh32p(params,x)
96abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define dtoh64(x)	dtoh64p(params,x)
97b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
98b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
99b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline char*
100b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
101eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
102a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	uint8_t length;
103a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	uint16_t string[PTP_MAXSTRLEN+1];
104a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* allow for UTF-8: max of 3 bytes per UCS-2 char, plus final null */
105e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	char loclstr[PTP_MAXSTRLEN*3+1];
106a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	size_t nconv, srclen, destlen;
107a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	char *src, *dest;
108a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
109a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	length = dtoh8a(&data[offset]);	/* PTP_MAXSTRLEN == 255, 8 bit len */
110a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*len = length;
111a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (length == 0)		/* nothing to do? */
112a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		return(NULL);
113a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
114a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* copy to string[] to ensure correct alignment for iconv(3) */
115a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(string, &data[offset+1], length * sizeof(string[0]));
116a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	string[length] = 0x0000U;   /* be paranoid!  add a terminator. */
117a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[0] = '\0';
118e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij
119a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* convert from camera UCS-2 to our locale */
120a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	src = (char *)string;
121a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	srclen = length * sizeof(string[0]);
122a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	dest = loclstr;
123a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	destlen = sizeof(loclstr)-1;
1246db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	nconv = (size_t)-1;
1256db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#ifdef HAVE_ICONV
126d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij	if (params->cd_ucs2_to_locale != (iconv_t)-1)
127d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij		nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen, &dest, &destlen);
1286db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#endif
129a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (nconv == (size_t) -1) { /* do it the hard way */
130a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		int i;
131a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		/* try the old way, in case iconv is broken */
132a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		for (i=0;i<length;i++) {
133a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			if (dtoh16a(&data[offset+1+2*i])>127)
134a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = '?';
135a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			else
136a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = dtoh16a(&data[offset+1+2*i]);
137eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
138a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		dest = loclstr+length;
139eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
140a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*dest = '\0';
141a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[sizeof(loclstr)-1] = '\0';   /* be safe? */
142a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	return(strdup(loclstr));
143a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
144a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
145a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline int
146a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijucs2strlen(uint16_t const * const unicstr)
147a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
148a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	int length;
149a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
150a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Unicode strings are terminated with 2 * 0x00 */
151a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	for(length = 0; unicstr[length] != 0x0000U; length ++);
152a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return length;
153eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
154eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
155a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
156b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
157b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
158eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
159a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	int packedlen;
160a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	uint16_t ucs2str[PTP_MAXSTRLEN+1];
161a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	char *ucs2strp = (char *) ucs2str;
162a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t convlen = strlen(string);
163a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
164a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
165a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memset(ucs2strp, 0, sizeof(ucs2str));  /* XXX: necessary? */
1666db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#ifdef HAVE_ICONV
167d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij	if (params->cd_locale_to_ucs2 == (iconv_t)-1) {
1686db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		size_t nconv;
1696db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
1706db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		char *stringp = string;
1716db174f4d18af574fab991309e11010aa0eb4543Linus Walleij
1726db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
1736db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			&ucs2strp, &convmax);
1746db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		if (nconv == (size_t) -1)
1756db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			ucs2str[0] = 0x0000U;
176d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij	} else
1776db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#else
1786db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	{
1796db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		int i;
1806db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		for (i=0;i<convlen;i++) {
1816db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			ucs2str[i] = string[i];
1826db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		}
1836db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		ucs2str[convlen] = 0;
1846db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	}
1856db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#endif
186a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/*
187a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
188a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 *      why do we need ucs2strlen()?
189a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 */
190a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packedlen = ucs2strlen(ucs2str);
191a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (packedlen > PTP_MAXSTRLEN-1) {
192a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		*len=0;
193a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return;
194a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	}
195958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
1967f2343824550452974d78f5dbd94e64844355c33Linus Walleij	/* number of characters including terminating 0 (PTP standard confirmed) */
197a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	htod8a(&data[offset],packedlen+1);
198a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
199a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
200958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
201958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* The returned length is in number of characters */
202048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij	*len = (uint8_t) packedlen+1;
203eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
204eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
205a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline unsigned char *
206735f41692934a716158cf051d76e988febeca7eeLinus Walleijptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
207a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
2088b42ca3d3baeb7c8f3e5eca88c613adb612e4ec0Richard Low	uint8_t packed[PTP_MAXSTRLEN*2+3], len;
209a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t plen;
210a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	unsigned char *retcopy = NULL;
211d47b9218023a6b943a93faa743712ae072cba85cRichard Low
212d47b9218023a6b943a93faa743712ae072cba85cRichard Low	if (string == NULL)
213d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
214d47b9218023a6b943a93faa743712ae072cba85cRichard Low	else
215d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
216d47b9218023a6b943a93faa743712ae072cba85cRichard Low
217958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* returned length is in characters, then one byte for string length */
218958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	plen = len*2 + 1;
219048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij
220a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	retcopy = malloc(plen);
221735f41692934a716158cf051d76e988febeca7eeLinus Walleij	if (!retcopy) {
222735f41692934a716158cf051d76e988febeca7eeLinus Walleij		*packed_size = 0;
223a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return NULL;
224735f41692934a716158cf051d76e988febeca7eeLinus Walleij	}
225a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	memcpy(retcopy, packed, plen);
226735f41692934a716158cf051d76e988febeca7eeLinus Walleij	*packed_size = plen;
227a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return (retcopy);
228a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
229a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
230b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
231b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
232eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
233eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
234eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
235eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
236eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint32_t));
237eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
238eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
239eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
240eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
241eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
242eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
243eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
244b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
245f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
246f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij{
247f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	uint32_t i=0;
248f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
249f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	*data = malloc ((arraylen+1)*sizeof(uint32_t));
250f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	htod32a(&(*data)[0],arraylen);
251f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	for (i=0;i<arraylen;i++)
252f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
253f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	return (arraylen+1)*sizeof(uint32_t);
254f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij}
255f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
256f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijstatic inline uint32_t
257b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
258eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
259eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
260eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
261eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
262eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint16_t));
263eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
264eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
265eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
266eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
267eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
268eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
269eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
270eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* DeviceInfo pack/unpack */
271eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
272eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_StandardVersion		 0
273eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionID	 2
274eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionVersion	 6
275eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionDesc	 8
276eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_FunctionalMode		 8
277eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_OperationsSupported	10
278eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
279b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
280b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
281eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
282eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t len;
283eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	unsigned int totallen;
2847e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
285d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij	if (!data) return;
286d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij	if (datalen < 12) return;
2877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
288eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionID =
289eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh32a(&data[PTP_di_VendorExtensionID]);
290eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionVersion =
291eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
292eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionDesc =
293eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_string(params, data,
294eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_VendorExtensionDesc, &len);
295eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=len*2+1;
296eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->FunctionalMode =
297eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
298eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
299eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
300eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->OperationsSupported);
301eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
302eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
303eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
304eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->EventsSupported);
305eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
306eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DevicePropertiesSupported_len =
307eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_uint16_t_array(params, data,
308eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
309eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->DevicePropertiesSupported);
310eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
311eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
312eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
313eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->CaptureFormats);
314eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
315eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
316eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
317eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->ImageFormats);
318eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
319eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Manufacturer = ptp_unpack_string(params, data,
320eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
321eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
322eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
323eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Model = ptp_unpack_string(params, data,
324eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
325eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
326eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
327eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DeviceVersion = ptp_unpack_string(params, data,
328eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
329eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
330eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
331eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->SerialNumber = ptp_unpack_string(params, data,
332eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
333eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
334eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
335a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
336e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleijstatic void inline
337a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleijptp_free_DI (PTPDeviceInfo *di) {
338a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->SerialNumber) free (di->SerialNumber);
339a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->DeviceVersion) free (di->DeviceVersion);
340a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->Model) free (di->Model);
341a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->Manufacturer) free (di->Manufacturer);
342a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->ImageFormats) free (di->ImageFormats);
343a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->CaptureFormats) free (di->CaptureFormats);
344a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->VendorExtensionDesc) free (di->VendorExtensionDesc);
345a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->OperationsSupported) free (di->OperationsSupported);
346a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->EventsSupported) free (di->EventsSupported);
347a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->DevicePropertiesSupported) free (di->DevicePropertiesSupported);
348a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij}
3497e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij/* EOS Device Info unpack */
3517e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijstatic inline void
3527e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
3537e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij{
3547e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int totallen = 4;
3557e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (datalen < 8) return;
3567e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3577e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	/* uint32_t struct len - ignore */
3587e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
3597e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		totallen, &di->EventsSupported);
3607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->EventsSupported) return;
3617e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
3627e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (totallen >= datalen) return;
3637e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3647e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
3657e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		totallen, &di->DevicePropertiesSupported);
3667e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->DevicePropertiesSupported) return;
3677e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
3687e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (totallen >= datalen) return;
3697e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3707e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->unk_len = ptp_unpack_uint32_t_array(params, data,
3717e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		totallen, &di->unk);
3727e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->unk) return;
3737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->unk_len*sizeof(uint32_t)+4;
3747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	return;
3757e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij}
3760d762ccc39331608119dd0267021b165e22de499Linus Walleij
3770d762ccc39331608119dd0267021b165e22de499Linus Walleijstatic inline void
3780d762ccc39331608119dd0267021b165e22de499Linus Walleijptp_free_EOS_DI (PTPCanonEOSDeviceInfo *di)
3790d762ccc39331608119dd0267021b165e22de499Linus Walleij{
3800d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->EventsSupported);
3810d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->DevicePropertiesSupported);
3820d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->unk);
3830d762ccc39331608119dd0267021b165e22de499Linus Walleij}
384eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
385eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectHandles array pack/unpack */
386eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
387eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oh				 0
388eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
389b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
390b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
391eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
392f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (len) {
393f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
394f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	} else {
395f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = 0;
396f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->Handler = NULL;
397f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
398eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
399eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
400eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StoreIDs array pack/unpack */
401eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
402eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_sids			 0
403eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
404b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
405b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
406eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
407eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
408eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	&sids->Storage);
409eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
410eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
411eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StorageInfo pack/unpack */
412eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
413eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageType		 0
414eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FilesystemType		 2
415eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_AccessCapability		 4
416eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_MaxCapability		 6
417eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInBytes		14
418eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInImages	22
419eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageDescription	26
420eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
421b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
422b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
423eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
424eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t storagedescriptionlen;
425eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
426eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
427eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
428eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
429eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
430eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
431eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
432eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageDescription=ptp_unpack_string(params, data,
433eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription, &storagedescriptionlen);
434eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->VolumeLabel=ptp_unpack_string(params, data,
435eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription+storagedescriptionlen*2+1,
436eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&storagedescriptionlen);
437eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
438eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
439eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectInfo pack/unpack */
440eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
441eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_StorageID		 0
442eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectFormat		 4
443eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ProtectionStatus		 6
444eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectCompressedSize	 8
445eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbFormat		12
446eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbCompressedSize	14
447eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixWidth		18
448eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixHeight		22
449eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixWidth		26
450eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixHeight		30
451eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImageBitDepth		34
452eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ParentObject		38
453eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationType		42
454eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationDesc		44
455eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_SequenceNumber		48
456eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_filenamelen		52
457eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_Filename			53
458eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
459a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* the max length assuming zero length dates. We have need 3 */
460a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* bytes for these. */
461a679b1c4d273f210abb6befc5d9954a25427c329Richard Low#define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
462a679b1c4d273f210abb6befc5d9954a25427c329Richard Low
463b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
464b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
465eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
466b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* oidata;
467eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
468eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen=0;
469a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	/* let's allocate some memory first; correct assuming zero length dates */
470a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	oidata=malloc(PTP_oi_MaxLen);
471eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* the caller should free it after use! */
472eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0
473eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date="20020101T010101"; /* XXX Fake date */
474eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
475a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	memset (oidata, 0, PTP_oi_MaxLen);
476eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
477eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
478eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
479eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
480eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
481eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
482eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
483eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
484eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
485eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
486eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
487eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
488eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
489eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
490eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
491eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
492eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
493eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
494eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	filenamelen=(uint8_t)strlen(oi->Filename);
495eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
496eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
497eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
498eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
499eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
500eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/*
501eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 *XXX Fake date.
502eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * for example Kodak sets Capture date on the basis of EXIF data.
503eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * Spec says that this field is from perspective of Initiator.
504eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
505eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
506eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capturedatelen=strlen(capture_date);
507eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
508eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
509eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
510eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
511eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
512eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
513eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
514eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
515eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
516eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		  capture_date[i];
517eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
518eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
519eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* XXX this function should return dataset length */
520eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
521eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*oidataptr=oidata;
522a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3);
523eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
524eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
5253bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleijstatic time_t
5266db174f4d18af574fab991309e11010aa0eb4543Linus Walleijptp_unpack_PTPTIME (const char *str) {
5273bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char ptpdate[40];
5283bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char tmp[5];
5293bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	int  ptpdatelen;
5303bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	struct tm tm;
5313bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
5323bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	if (!str)
5333bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
5343bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	ptpdatelen = strlen(str);
5357e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen >= sizeof (ptpdate)) {
5366db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
5373bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
5387e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
5393bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strcpy (ptpdate, str);
5407e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen<15) {
5416db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
5423bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
5437e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
5443bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
5453bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	memset(&tm,0,sizeof(tm));
5463bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate, 4);
5473bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[4] = 0;
5483bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_year=atoi (tmp) - 1900;
5493bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 4, 2);
5503bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5513bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mon = atoi (tmp) - 1;
5523bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 6, 2);
5533bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5543bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mday = atoi (tmp);
5553bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 9, 2);
5563bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5573bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_hour = atoi (tmp);
5583bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 11, 2);
5593bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5603bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_min = atoi (tmp);
5613bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 13, 2);
5623bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5633bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_sec = atoi (tmp);
564e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	tm.tm_isdst = -1;
5653bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	return mktime (&tm);
5663bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij}
5673bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
568b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
569b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
570eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
571eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
572eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen;
573eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date;
574eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
575eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
576eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
577eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
578eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
579eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
580eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
581eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
582eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
583eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
584eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
585eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
586eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
587eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
588eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
589eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
590eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
591eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
592eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
593eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
594eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* subset of ISO 8601, without '.s' tenths of second and
595eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * time zone
596eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
5976db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
598eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
599eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
6003bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	/* now the modification date ... */
601eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
602eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2
603eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		+capturedatelen*2+2,&capturedatelen);
6046db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->ModificationDate = ptp_unpack_PTPTIME(capture_date);
605eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
606eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
607eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
608eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Custom Type Value Assignement (without Length) macro frequently used below */
609b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define CTVAL(target,func) {			\
610b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(target))	\
611b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;			\
612b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	target = func(&data[*offset]);		\
613b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(target);		\
614eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
615eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
616b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define RARR(val,member,func)	{			\
617b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int n,j;					\
618b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(uint32_t))		\
619b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;				\
620b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	n = dtoh32a (&data[*offset]);			\
621b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(uint32_t);			\
622b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij							\
623b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.count = n;				\
624b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
625b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!val->a.v) return 0;			\
626b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (j=0;j<n;j++)				\
627b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(val->a.v[j].member, func);	\
628b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
629eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
630b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
631b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPV (
632b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPParams *params, unsigned char* data, int *offset, int total,
633b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPPropertyValue* value, uint16_t datatype
634b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij) {
635eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
636b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
637b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i8,dtoh8a);
638b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
639b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
640b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u8,dtoh8a);
641b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
642b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
643b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i16,dtoh16a);
644b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
645b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
646b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u16,dtoh16a);
647b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
648b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
649b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i32,dtoh32a);
650b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
651b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
652b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u32,dtoh32a);
653b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
654abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
655abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->i64,dtoh64a);
656abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
657abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
658abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->u64,dtoh64a);
659abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
660abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
661037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_UINT128:
662037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
663037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of uint128n");*/
664037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
665037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_INT128:
666037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
667037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of int128n");*/
668037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
669037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
670037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
671037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
672b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
673b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i8,dtoh8a);
674b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
675b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
676b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u8,dtoh8a);
677b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
678b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
679b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u16,dtoh16a);
680b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
681b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
682b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i16,dtoh16a);
683b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
684b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
685b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u32,dtoh32a);
686b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
687b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
688b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i32,dtoh32a);
689b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
690abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
691abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,u64,dtoh64a);
692abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
693abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
694abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,i64,dtoh64a);
695abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
696b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
697b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int arrays are unimplemented also */
698b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
699b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		uint8_t len;
700b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		/* XXX: max size */
701b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		value->str = ptp_unpack_string(params,data,*offset,&len);
702b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		*offset += len*2+1;
703b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!value->str)
704deddc3490b3084b802737017982285bfa58b382fLinus Walleij			return 1;
705b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
706eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
707037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	default:
708037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		return 0;
709b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
710b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
711eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
712eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
713eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Device Property pack/unpack */
714eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
715eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DevicePropertyCode	0
716eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DataType		2
717eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_GetSet			4
718eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_FactoryDefaultValue	5
719eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
720b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
721b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
722eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
723b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
724eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
725b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (dpd, 0, sizeof(*dpd));
726eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
727eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
728eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
729deddc3490b3084b802737017982285bfa58b382fLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
730b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
731b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_dpd_FactoryDefaultValue;
732b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
733b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
734deddc3490b3084b802737017982285bfa58b382fLinus Walleij	if ((dpd->DataType == PTP_DTC_STR) && (offset == dpdlen))
735deddc3490b3084b802737017982285bfa58b382fLinus Walleij		return 1;
736b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
737b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
738b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
739b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* if offset==0 then Data Type format is not supported by this
740b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   code or the Data Type is a string (with two empty strings as
741b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
742b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   not present. */
743b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
744b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (offset==PTP_dpd_FactoryDefaultValue)
745b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 1;
746b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
747b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	dpd->FormFlag=dtoh8a(&data[offset]);
748b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
749eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
750eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (dpd->FormFlag) {
751b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Range:
752b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
753b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
754b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
755b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
756b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
757b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
758eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
759b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Enumeration: {
760b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
761eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
762b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
763b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
764b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
765b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
766b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
767b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
768b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
769b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
770b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
771b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
772b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
773b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
774b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
775b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
776b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
777b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
778b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
779b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
780b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
781b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
782eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			}
783b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
784eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
785eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
786b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
787b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
788b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
789b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_devicepropdesc(dpd);
790b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
791eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
792eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
793b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/* (MTP) Object Property pack/unpack */
794b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_ObjectPropertyCode	0
795b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_DataType		2
796b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_GetSet			4
797b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_FactoryDefaultValue	5
798eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
799b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
800b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
801eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
802b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
803b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
804b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (opd, 0, sizeof(*opd));
805b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
806b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
807b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
808b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
809b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_opd_FactoryDefaultValue;
810b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
811b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
812b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
813b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GroupCode=dtoh32a(&data[offset]);
814b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint32_t);
815b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
816b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->FormFlag=dtoh8a(&data[offset]);
817b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
818b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
819b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	switch (opd->FormFlag) {
820b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Range:
821b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
822b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
823b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
824b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
825b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
826b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
827b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
828b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Enumeration: {
829b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
830b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define N	opd->FORM.Enum.NumberOfValues
831b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
832b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
833b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
834b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!opd->FORM.Enum.SupportedValue)
835b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
836b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
837b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
838b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
839b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
840b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
841b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
842b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
843b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
844b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
845b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
846b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
847b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
848b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
849b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				opd->FORM.Enum.NumberOfValues = i;
850b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
851b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			}
852b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
853b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
854b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
855eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
856b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
857b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
858b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_objectpropdesc(opd);
859b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
860eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
861eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
862eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
863b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
864b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
865eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
866b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* dpv=NULL;
867eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t size=0;
868b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int	i;
869eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
870eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
871b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
872b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int8_t);
873b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
874b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->i8);
875b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
876b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
877b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint8_t);
878b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
879b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->u8);
880b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
881b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
882b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int16_t);
883b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
884b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->i16);
885b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
886b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
887b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint16_t);
888b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
889b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->u16);
890b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
891b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
892b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int32_t);
893b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
894b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->i32);
895b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
896b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
897b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t);
898b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
899b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->u32);
900b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
901abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
902abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(int64_t);
903abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
904abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->i64);
905abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
906abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
907abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint64_t);
908abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
909abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->u64);
910abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
911b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
912b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
913b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
914b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
915b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
916cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
917b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
918b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
919b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
920b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
921b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
922b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
923cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
924b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
925b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
926b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
927b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
928b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
929b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
930cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
931b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
932b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
933b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
934b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
935b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
936b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
937cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
938b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
939b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
940b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
941b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
942b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
943b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
944cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
945b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
946b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
947b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
948b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
949b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
950b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
951cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
952b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
953abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
954abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
955abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
956abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
957abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
958cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
959abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
960abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
961abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
962abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
963abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
964abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
965cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
966abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
967b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
968b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
969735f41692934a716158cf051d76e988febeca7eeLinus Walleij		dpv=ptp_get_packed_stringcopy(params, value->str, &size);
970eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
971b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
972eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
973eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*dpvptr=dpv;
974eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return size;
97599310d4445697da39f22dff35457c75e35e97171Linus Walleij}
97699310d4445697da39f22dff35457c75e35e97171Linus Walleij
97799310d4445697da39f22dff35457c75e35e97171Linus Walleij#define MAX_MTP_PROPS 127
97899310d4445697da39f22dff35457c75e35e97171Linus Walleijstatic inline uint32_t
9791e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
98099310d4445697da39f22dff35457c75e35e97171Linus Walleij{
98199310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char* opldata;
9821e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *propitr;
98399310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char *packedprops[MAX_MTP_PROPS];
98499310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t packedpropslens[MAX_MTP_PROPS];
98539b9374f23451201dece736db13f0f648584dc32Linus Walleij	uint32_t packedobjecthandles[MAX_MTP_PROPS];
98699310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropsids[MAX_MTP_PROPS];
98799310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropstypes[MAX_MTP_PROPS];
98899310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t totalsize = 0;
98999310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t bufp = 0;
99099310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t noitems = 0;
99199310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t i;
99299310d4445697da39f22dff35457c75e35e97171Linus Walleij
99399310d4445697da39f22dff35457c75e35e97171Linus Walleij	totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
9941e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	propitr = props;
9951e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	while (nrofprops-- && noitems < MAX_MTP_PROPS) {
9966c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		/* Object Handle */
99739b9374f23451201dece736db13f0f648584dc32Linus Walleij		packedobjecthandles[noitems]=propitr->ObjectHandle;
99899310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint32_t); /* Object ID */
99999310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Metadata type */
100099310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropsids[noitems]=propitr->property;
100199310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
100299310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Data type */
100399310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropstypes[noitems]= propitr->datatype;
100499310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
100599310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Add each property to be sent. */
100699310d4445697da39f22dff35457c75e35e97171Linus Walleij	        packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
100799310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += packedpropslens[noitems];
100899310d4445697da39f22dff35457c75e35e97171Linus Walleij		noitems ++;
10091e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		propitr ++;
101099310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
101199310d4445697da39f22dff35457c75e35e97171Linus Walleij
101299310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Allocate memory for the packed property list */
101399310d4445697da39f22dff35457c75e35e97171Linus Walleij	opldata = malloc(totalsize);
101499310d4445697da39f22dff35457c75e35e97171Linus Walleij
101599310d4445697da39f22dff35457c75e35e97171Linus Walleij	htod32a(&opldata[bufp],noitems);
101699310d4445697da39f22dff35457c75e35e97171Linus Walleij	bufp += 4;
101799310d4445697da39f22dff35457c75e35e97171Linus Walleij
101899310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Copy into a nice packed list */
101999310d4445697da39f22dff35457c75e35e97171Linus Walleij	for (i = 0; i < noitems; i++) {
102099310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Object ID */
10216c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		htod32a(&opldata[bufp],packedobjecthandles[i]);
102299310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint32_t);
102399310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropsids[i]);
102499310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
102599310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropstypes[i]);
102699310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
102799310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* The copy the actual property */
102899310d4445697da39f22dff35457c75e35e97171Linus Walleij		memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
102999310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += packedpropslens[i];
103099310d4445697da39f22dff35457c75e35e97171Linus Walleij		free(packedprops[i]);
103199310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
103299310d4445697da39f22dff35457c75e35e97171Linus Walleij	*opldataptr = opldata;
103399310d4445697da39f22dff35457c75e35e97171Linus Walleij	return totalsize;
1034eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1035eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
10361e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijstatic int
10371e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij_compare_func(const void* x, const void *y) {
10381e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *px = x;
10391e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *py = y;
10401e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
10411e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	return px->ObjectHandle - py->ObjectHandle;
10421e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij}
10431e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
10448d82d2f4b0794e41ec26289045867eebb3496b8cRichard Lowstatic inline int
10451e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
10468d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low{
1047277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	uint32_t prop_count = dtoh32a(data);
10481e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *props = NULL;
1049277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	int offset = 0, i;
1050277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1051277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	if (prop_count == 0) {
10521e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		*pprops = NULL;
1053277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		return 0;
1054277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
1055d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij	ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
1056277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	data += sizeof(uint32_t);
10573bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	len -= sizeof(uint32_t);
10581e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	props = malloc(prop_count * sizeof(MTPProperties));
10591e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	if (!props) return 0;
1060277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	for (i = 0; i < prop_count; i++) {
10613bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		if (len <= 0) {
1062d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
10633bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL", i);
10643bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i);
1065d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			qsort (props, i, sizeof(MTPProperties),_compare_func);
1066d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			*pprops = props;
10673bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			return i;
10683bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		}
10691e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].ObjectHandle = dtoh32a(data);
1070277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint32_t);
1071277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint32_t);
1072277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
10731e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].property = dtoh16a(data);
1074277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1075277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1076277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
10771e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].datatype = dtoh16a(data);
1078277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1079277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1080277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1081277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		offset = 0;
10821e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype);
1083277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += offset;
1084277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= offset;
1085277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
10861e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
10871e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	*pprops = props;
1088277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	return prop_count;
10898d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low}
10908d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low
1091eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1092eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP USB Event container unpack
1093eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1094eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1095eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1096eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Length		0
1097eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Type		4
1098eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Code		6
1099eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_TransId		8
1100eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param1		12
1101eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param2		16
1102eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param3		20
1103eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1104b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
11057e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
1106eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
11077e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int	length;
11087e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int	type;
11097e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
1110eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1111eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
11127e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	memset(ec,0,sizeof(*ec));
11137e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	length=dtoh32a(&data[PTP_ec_Length]);
11147e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	type = dtoh16a(&data[PTP_ec_Type]);
1115b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
11167e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Code=dtoh16a(&data[PTP_ec_Code]);
11177e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
11187e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
11197e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (type!=PTP_USB_CONTAINER_EVENT) {
11207e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ptp_debug (params, "Unknown canon event type %d (code=%x,tid=%x), please report!",type,ec->Code,ec->Transaction_ID);
11217e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		return;
11227e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
11237e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param1+4)) {
11247e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
11257e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=1;
11267e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
11277e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param2+4)) {
11287e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
11297e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=2;
11307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
11317e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param3+4)) {
11327e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
11337e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=3;
11347e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
1135eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1136eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1137eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1138eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP Canon Folder Entry unpack
1139eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1140eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1141eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectHandle		0
1142eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectFormatCode	4
1143eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Flags			6
1144eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectSize		7
1145eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Time			11
1146eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Filename		15
1147eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1148b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1149b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1150eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1151eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
1152eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1153eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
1154eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
1155eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
1156eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
1157b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
1158eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
1159eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1160b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
1161b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
1162b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
11631a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint16_t
11641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
11651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
11661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	/*
11671a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  EOS ImageFormat entries (of at least the 5DMII and the 400D ) look like this:
11681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: number of entries / generated files (1 or 2)
11691a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: size of this entry in bytes (most likely allways 0x10)
11701a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image type (1 == JPG, 6 == RAW)
11711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image size (0 == Large, 1 == Medium, 2 == Small)
11721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW)
11731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  If number of entries is 2 the last uint32 repeat.
11741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
11751a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  example:
11761a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		0: 0x       1
11771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		1: 0x      10
11781a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		2: 0x       6
11791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		3: 0x       1
11801a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		4: 0x       4
11811a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
11821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  The idea is to simply 'condense' these values to just one uint16 to be able to conveniontly
11831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  use the available enumeration facilities (look-up table). The image size and compression
11841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  values fully describe the image format. Hence we generate a uint16 with the four nibles set
11851a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  as follows: entry 1 size | entry 1 compression | entry 2 size | entry 2 compression.
11861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  The above example would result in the value 0x1400.
11871a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  */
11881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
11891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	const unsigned char* d = *data;
11901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = dtoh32a( d );
11911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t l, s1, c1, s2 = 0, c2 = 0;
11921a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
11931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n != 1 && n !=2) {
11941a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
11951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
11961a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
11971a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
11981a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	l = dtoh32a( d+=4 );
11991a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (l != 0x10) {
12001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
12011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
12021a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
12031a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	d+=4; /* skip type */
12051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	s1 = dtoh32a( d+=4 );
12061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	c1 = dtoh32a( d+=4 );
12071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12081a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n == 2) {
12091a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		l = dtoh32a( d+=4 );
12101a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		if (l != 0x10) {
12111a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
12121a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			return 0;
12131a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		}
12141a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		d+=4; /* skip type */
12151a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		s2 = dtoh32a( d+=4 );
12161a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		c2 = dtoh32a( d+=4 );
12171a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
12181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12191a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	*data = (unsigned char*) d+4;
12201a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12211a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
12221a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
12231a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint32_t
12251a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
12261a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
12271a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = (value & 0xFF) ? 2 : 1;
12281a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t s = 4 + 0x10 * n;
12291a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12301a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if( !data )
12311a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return s;
12321a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12331a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=0, n);
12341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, 0x10);
12351a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, ((value >> 8) & 0xF) == 4 ? 6 : 1);
12361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, (value >> 12) & 0xF);
12371a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, (value >> 8) & 0xF);
12381a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12391a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n==2) {
12401a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, 0x10);
12411a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, ((value >> 0) & 0xF) == 4 ? 6 : 1);
12421a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, (value >> 4) & 0xF);
12431a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, (value >> 0) & 0xF);
12441a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
12451a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12461a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return s;
12471a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
12481a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
1249b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/*
1250f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij    PTP EOS Changes Entry unpack
1251f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij*/
1252f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Size		0
1253f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Type		4
1254f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1255f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Subtype	8	/* only for properties */
1256f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Val_Data	0xc	/* only for properties */
1257f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Type	0xc	/* only for property descs */
1258f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Count	0x10	/* only for property descs */
1259f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Data	0x14	/* only for property descs */
1260f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1261d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_RequestObjectTransfer */
1262d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_ObjectID	8
1263d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_OFC		0x0c
1264d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Size		0x14
1265d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Name		0x1c
1266d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij
1267d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_ObjectAddedEx */
1268d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_ObjectID	8
1269d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_StorageID	0x0c
1270d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_OFC		0x10
1271d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Size		0x1c
1272d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Parent	0x20
1273d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Name		0x28
1274f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1275f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijstatic inline int
1276f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **ce)
1277f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij{
1278f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	int	i = 0, entries = 0;
1279f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	unsigned char	*curdata = data;
1280f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1281f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (data==NULL)
1282f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		return 0;
1283f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1284f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1285f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1286f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1287f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
1288f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		if ((size == 8) && (type == 0))
1289f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1290f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		entries++;
1291f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
12929d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij	*ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
1293f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (!*ce) return 0;
1294f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1295f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	curdata = data;
1296f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1297f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1298f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1299f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1300d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1301d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij		(*ce)[i].u.info = NULL;
1302f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		switch (type) {
1303d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		case  PTP_EC_CANON_EOS_ObjectAddedEx:
1304f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
1305d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
1306d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.StorageID 		= dtoh32a(&curdata[PTP_ece_OA_StorageID]);
1307d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ParentObject	= dtoh32a(&curdata[PTP_ece_OA_Parent]);
1308d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OA_OFC]);
1309d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
1310d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OA_Name]));
1311d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			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);
1312d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			break;
1313d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		case  PTP_EC_CANON_EOS_RequestObjectTransfer:
1314d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
1315f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
1316d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.StorageID 		= 0; /* use as marker */
1317f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OI_OFC]);
1318d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ParentObject	= 0; /* check, but use as marker */
1319f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
1320f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OI_Name]));
13213bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
1322d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			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);
1323f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
13247e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case  PTP_EC_CANON_EOS_AvailListChanged: {	/* property desc */
1325f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1326f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
1327f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
1328e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij			unsigned char	*xdata = &curdata[PTP_ece_Prop_Desc_Data];
1329f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			int		j;
1330f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			PTPDevicePropDesc	*dpd;
1331f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
13327e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype);
1333f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			for (j=0;j<params->nrofcanon_props;j++)
1334f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (params->canon_props[j].proptype == proptype)
1335f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1336f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (j==params->nrofcanon_props) {
13373bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
1338f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1339f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1340f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			dpd = &params->canon_props[j].dpd;
13417e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			/* 1 - uint16 ?
13427e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 3 - uint16
13437e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 7 - string?
13447e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 */
1345f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (propxtype != 3) {
13463bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled.", i, propxtype, proptype);
13473bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++)
1348e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					ptp_debug (params, "    %d: %02x", j, xdata[j]);
1349f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1350f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
13511a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			if (! propxcnt)
13521a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
13531a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
13551a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				   i, propxtype, proptype, dpd->DataType, propxcnt);
13561a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FormFlag = PTP_DPFF_Enumeration;
13571a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.NumberOfValues = propxcnt;
13580d762ccc39331608119dd0267021b165e22de499Linus Walleij			if (dpd->FORM.Enum.SupportedValue) free (dpd->FORM.Enum.SupportedValue);
13591a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
13601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13611a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			switch (proptype) {
13621a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormat:
13631a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatCF:
13641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatSD:
13651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatExtHD:
13661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* special handling of ImageFormat properties */
1367f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<propxcnt;j++) {
13681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->FORM.Enum.SupportedValue[j].u16 =
1369e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij							dtoh16( ptp_unpack_EOS_ImageFormat( params, &xdata ) );
13701a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
13711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
13721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
13731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			default:
13741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* 'normal' enumerated types */
13751a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (dpd->DataType) {
13761a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX( TYPE, CONV )\
13771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<propxcnt;j++) { \
1378e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(xdata); \
1379e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(xdata)); \
1380e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						xdata += 4; /* might only be for propxtype 3 */ \
13811a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					} \
13821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
13831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_INT16:	XX( i16, dtoh16a );
13851a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT32:	XX( u32, dtoh32a );
13861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT16:	XX( u16, dtoh16a );
13871a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT8:	XX( u8,  dtoh8a );
13881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
13891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				default:
1390e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, raw values:", i, dpd->DataType, proptype, dtoh32a(xdata));
1391e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, xdata+=4) /* 4 is good for propxtype 3 */
1392e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %3d: 0x%8x", j, dtoh32a(xdata));
13931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
1394f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1395f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1396f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1397f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
13987e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case PTP_EC_CANON_EOS_PropValueChanged:
1399f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (size >= 0xc) {	/* property info */
1400f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				int j;
1401f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1402e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij				unsigned char	*xdata = &curdata[PTP_ece_Prop_Val_Data];
1403f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				PTPDevicePropDesc	*dpd;
1404f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
14051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				ptp_debug (params, "event %d: EOS prop %04x info record, datasize is %d", i, proptype, size-PTP_ece_Prop_Val_Data);
1406f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<params->nrofcanon_props;j++)
1407f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (params->canon_props[j].proptype == proptype)
1408f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						break;
1409f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (j<params->nrofcanon_props) {
1410f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (	(params->canon_props[j].size != size) ||
1411e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						(memcmp(params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data))) {
1412f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
1413e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						memcpy (params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data);
1414f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					}
1415f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				} else {
1416f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (j)
1417f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
1418f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					else
1419f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = malloc(sizeof(params->canon_props[0]));
1420f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].type = type;
1421f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].proptype = proptype;
1422f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].size = size;
1423f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
1424e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					memcpy(params->canon_props[j].data, xdata, size-PTP_ece_Prop_Val_Data);
1425f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
1426f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.GetSet = 1;
1427f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
1428f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->nrofcanon_props = j+1;
1429f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1430f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				dpd = &params->canon_props[j].dpd;
14311a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
1432d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
1433d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				(*ce)[i].u.propid = proptype;
1434d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
14351a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* fix GetSet value */
14361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (proptype) {
14371a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX(x) case PTP_DPC_CANON_##x:
14381a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusMode)
14391a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryPower)
14401a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatterySelect)
14411a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ModelID)
14421a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_PTPExtensionVersion)
14431a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DPOFVersion)
14441a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AvailableShots)
14451a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentStorage)
14461a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentFolder)
14471a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenu)
14481a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenuList)
14491a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_HDDirectoryStructure)
14501a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryInfo)
14511a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AdapterInfo)
14521a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensStatus)
14531a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CardExtension)
14541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_TempStatus)
14551a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ShutterCounter)
14561a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_SerialNumber)
14571a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfFieldPreview)
14581a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EVFRecordStatus)
14591a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LvAfSystem)
14601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusInfoEx)
14611a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfField)
14621a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_Brightness)
14631a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EFComp)
14641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensName)
14651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensID)
14661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
14671a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						dpd->GetSet = PTP_DPGS_Get;
14681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						break;
14691a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
14701a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
14711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* set DataType */
1472f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (proptype) {
1473ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DPC_CANON_EOS_CameraTime:
1474d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_AvailableShots:
1475d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CaptureDestination:
1476d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXA:
1477d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXB:
1478d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentStorage:
1479d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentFolder:
1480d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ShutterCounter:
1481d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ModelID:
1482d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LensID:
1483d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_StroboFiring:
1484ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
1485ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
14860d762ccc39331608119dd0267021b165e22de499Linus Walleij				/* enumeration for AEM is never provided, but is available to set */
14870d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_AutoExposureMode:
14880d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
14890d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FormFlag = PTP_DPFF_Enumeration;
14900d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FORM.Enum.NumberOfValues = 0;
14910d762ccc39331608119dd0267021b165e22de499Linus Walleij					break;
1492f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Aperture:
1493f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ShutterSpeed:
1494f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ISOSpeed:
14957e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_FocusMode:
14967e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorSpace:
14977e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_BatteryPower:
1498e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BatterySelect:
1499d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_PTPExtensionVersion:
15001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_DriveMode:
15011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_AEB:
1502e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BracketMode:
1503e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_QuickReviewTime:
15040d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFMode:
15050d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFOutputDevice:
1506f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
1507f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1508f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_PictureStyle:
1509f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalance:
1510f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_MeteringMode:
15117e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ExpCompensation: /* actually int8 if you calculate */
1512f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT8;
1513f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1514f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Owner:
15151a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Artist:
15161a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Copyright:
15171a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_SerialNumber:
15181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_LensName:
1519f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_STR;
1520f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
15217e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
15227e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
15237e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					dpd->DataType = PTP_DTC_INT16;
15247e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
15257e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
15267e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case 0xd114:
15277e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DPOFVersion:
15281a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
15291a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
15301a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1531e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
15321a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
15337e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc1:
15347e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc2:
15357e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc3:
15367e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc4:
15377e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc5:
15387e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc6:
15397e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc7:
15407e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc8:
15417e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc9:
15427e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc10:
15437e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc11:
15441a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT8;
15451a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint8", i ,proptype, size-PTP_ece_Prop_Val_Data);
15467e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1547e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
15481a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					/* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */
1549e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					xdata += 4;
15507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
15517e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* yet unknown 32bit props */
15527e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorTemperature:
15537e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WftStatus:
15547e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_LensStatus:
15557e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CardExtension:
15567e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_TempStatus:
15577e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_PhotoStudioMode:
15587e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfFieldPreview:
15597e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFSharpness:
15607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFWBMode:
15617e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
15627e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFColorTemp:
1563d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_EVFRecordStatus:
1564d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ExposureSimMode:
1565d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvAfSystem:
1566d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_MovSize:
1567d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfField:
1568d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvViewTypeSelect:
15691a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_CustomFuncEx:
15700d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
15717e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
15721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
15731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
15741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
1575e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: 0x%8x", j, ((uint32_t*)xdata)[j]);
15767e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
1577d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				/* ImageFormat properties have to be ignored here, see special handling below */
1578d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
1579d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
1580d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
1581d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1582d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
1583f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
15843bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
15853bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1586e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
1587f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1588f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1589f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (dpd->DataType) {
1590ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DTC_UINT32:
1591e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u32	= dtoh32a(xdata);
1592e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u32		= dtoh32a(xdata);
15933bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
1594ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
1595f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT16:
1596e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= dtoh16a(xdata);
1597e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u16		= dtoh16a(xdata);
15983bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
1599f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1600f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT8:
1601e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u8	= dtoh8a(xdata);
1602e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u8		= dtoh8a(xdata);
16033bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
1604f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1605f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_STR: {
16061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
1607f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					uint8_t len = 0;
1608f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->FactoryDefaultValue.str	= ptp_unpack_string(params, data, 0, &len);
1609f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->CurrentValue.str		= ptp_unpack_string(params, data, 0, &len);
16101a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#else
16110d762ccc39331608119dd0267021b165e22de499Linus Walleij					if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
1612e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.str	= strdup( (char*)xdata );
16130d762ccc39331608119dd0267021b165e22de499Linus Walleij
16140d762ccc39331608119dd0267021b165e22de499Linus Walleij					if (dpd->CurrentValue.str) free (dpd->CurrentValue.str);
1615e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.str		= strdup( (char*)xdata );
16161a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#endif
16177e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
1618f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1619f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1620f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
1621f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					/* debug is printed in switch above this one */
1622f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1623f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
16241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
1625d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				/* ImageFormat special handling (WARNING: dont move this in front of the dpd->DataType switch!) */
1626d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				switch (proptype) {
1627d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
1628d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
1629d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
1630d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1631d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
1632e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= ptp_unpack_EOS_ImageFormat( params, &xdata );
1633d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->CurrentValue.u16		= dpd->FactoryDefaultValue.u16;
1634d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					ptp_debug (params,"event %d: decoded imageformat, currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
1635d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
1636d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				}
1637d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
1638f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1639f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1640d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij		case PTP_EC_CANON_EOS_CameraStatusChanged:
1641d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			ptp_debug (params, "event %d: EOS event CameraStatusChanged (size %d)", i, size);
1642d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS;
1643d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			(*ce)[i].u.status =  dtoh32a(curdata+8);
16449e09ad0e32cbdac88637d4ee2cc02ca3b771ca40Linus Walleij			params->eos_camerastatus = dtoh32a(curdata+8);
1645d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			break;
16467e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case 0: /* end marker */
16477e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size == 8) /* no output */
16487e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				break;
16497e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
16507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			break;
1651f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		default:
1652d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			switch (type) {
1653d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij#define XX(x)		case PTP_EC_CANON_EOS_##x: 								\
1654d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				ptp_debug (params, "event %d: unhandled EOS event "#x" (size %d)", i, size); 	\
1655d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				(*ce)[i].u.info = malloc(strlen("unhandled EOS event "#x" (size 123456789)"));	\
1656d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				sprintf ((*ce)[i].u.info, "unhandled EOS event "#x" (size %d)",  size);		\
1657d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				break;
1658d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetEvent)
1659d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectRemoved)
1660d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetObjectInfoEx)
1661d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageStatusChanged)
1662d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageInfoChanged)
1663d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectInfoChangedEx)
1664d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectContentChanged)
1665d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(WillSoonShutdown)
1666d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ShutdownTimerUpdated)
1667d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransfer)
1668d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferDT)
1669d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransferDT)
1670d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreAdded)
1671d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreRemoved)
1672d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(BulbExposureTime)
1673d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RecordingTime)
1674d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferTS)
1675d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(AfResult)
1676d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#undef XX
1677d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			default:
1678d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
1679d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				break;
1680d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			}
16817e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size >= 0x8) {	/* event info */
16827e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				int j;
1683d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				for (j=8;j<size;j++)
1684d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij					ptp_debug (params, "    %d: %02x", j, curdata[j]);
16857e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			}
1686f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1687f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1688f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1689f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
1690f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		i++;
16919d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij		if ((size == 8) && (type == 0))
16929d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij			break;
1693f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
16940d762ccc39331608119dd0267021b165e22de499Linus Walleij	if (!entries) {
16950d762ccc39331608119dd0267021b165e22de499Linus Walleij		free (*ce);
16960d762ccc39331608119dd0267021b165e22de499Linus Walleij		*ce = NULL;
16970d762ccc39331608119dd0267021b165e22de499Linus Walleij	}
1698f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	return entries;
1699f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij}
1700f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1701f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij/*
1702b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij    PTP USB Event container unpack for Nikon events.
1703b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij*/
1704b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Length		0
1705b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Code		2
1706b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Param1		4
1707b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Size		6
1708b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
17097e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, int *cnt)
1710b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij{
1711b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i;
1712b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1713b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = NULL;
1714b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (data == NULL)
1715b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1716b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (len < PTP_nikon_ec_Code)
1717b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1718b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
1719b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
1720b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
17210d762ccc39331608119dd0267021b165e22de499Linus Walleij	if (!*cnt)
17220d762ccc39331608119dd0267021b165e22de499Linus Walleij		return;
17230d762ccc39331608119dd0267021b165e22de499Linus Walleij
17247e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	*ec = malloc(sizeof(PTPContainer)*(*cnt));
1725b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1726b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<*cnt;i++) {
17277e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		memset(&(*ec)[i],0,sizeof(PTPContainer));
17287e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
17297e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
17307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Nparam	= 1;
1731b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1732eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1733eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1734eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1735b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
1736b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
1737b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i, len = 0;
1738b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint8_t	retlen;
1739b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char *curdata;
1740b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1741b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	len =	2*(strlen(text->title)+1)+1+
1742b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[0])+1)+1+
1743b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[1])+1)+1+
1744b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[2])+1)+1+
1745b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[3])+1)+1+
1746b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[4])+1)+1+
1747b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		4*2+2*4+2+4+2+5*4*2;
1748b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*data = malloc(len);
1749b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!*data) return 0;
1750b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1751b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	curdata = *data;
1752b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,100);curdata+=2;
1753b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1);curdata+=2;
1754b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0);curdata+=2;
1755b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1000);curdata+=2;
1756b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1757b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1758b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1759b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1760b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,6);curdata+=2;
1761b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1762b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1763b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1764b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0x10);curdata+=2;
1765b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1766b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<5;i++) {
1767b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1768b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x10);curdata+=2;
1769b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x01);curdata+=2;
1770b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x02);curdata+=2;
1771b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x06);curdata+=2;
1772b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1773b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return len;
1774b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
17757347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
17767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_version	0x00
17777347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_ofc	0x02
17787347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk1	0x04
17797347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_objectid	0x08
17807347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_parentid	0x0c
17817347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_previd	0x10	/* in same dir */
17827347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextid	0x14	/* in same dir */
17837347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextchild	0x18	/* down one dir */
17847347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_storageid	0x1c	/* only in storage entry */
17857347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_name	0x20
17867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_flags	0x2c
17877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_size	0x30
17887347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unixtime	0x34
17897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_year	0x38
17907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_month	0x39
17917347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_mday	0x3a
17927347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_hour	0x3b
17937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_minute	0x3c
17947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_second	0x3d
17957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk2	0x3e
17967347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_thumbsize	0x40
17977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_width	0x44
17987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_height	0x48
17997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
18007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijstatic inline uint16_t
18017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijptp_unpack_canon_directory (
18027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPParams		*params,
18037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned char		*dir,
18047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		cnt,
18057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectHandles	*handles,
18067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectInfo		**oinfos,	/* size(handles->n) */
18077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		**flags		/* size(handles->n) */
18087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij) {
18097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned int	i, j, nrofobs = 0, curob = 0;
18107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
18117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
18127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++)
18137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(dir+i*0x4c)) nrofobs++;
18147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->n = nrofobs;
18157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs);
18167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!handles->Handler) return PTP_RC_GeneralError;
18177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*oinfos = calloc(sizeof((*oinfos)[0]),nrofobs);
18187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*oinfos) return PTP_RC_GeneralError;
18197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*flags  = calloc(sizeof((*flags)[0]),nrofobs);
18207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*flags) return PTP_RC_GeneralError;
18217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
18227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Migrate data into objects ids, handles into
18237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the object handler array.
18247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 */
18257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	curob = 0;
18267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
18277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
18287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		PTPObjectInfo	*oi = (*oinfos)+curob;
18297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
18307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!ISOBJECT(cur))
18317347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
18327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
18337347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
18347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->StorageID		= 0xffffffff;
18357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectFormat	= dtoh16a(cur + ptp_canon_dir_ofc);
18367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ParentObject	= dtoh32a(cur + ptp_canon_dir_parentid);
18377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->Filename		= strdup((char*)(cur + ptp_canon_dir_name));
18387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
18397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ThumbCompressedSize	= dtoh32a(cur + ptp_canon_dir_thumbsize);
18407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixWidth	= dtoh32a(cur + ptp_canon_dir_width);
18417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixHeight	= dtoh32a(cur + ptp_canon_dir_height);
18427347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->CaptureDate		= oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
18437347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*flags)[curob]		= dtoh32a(cur + ptp_canon_dir_flags);
18447347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		curob++;
18457347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
18467347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over Storage ID entries and distribute the IDs to
18477347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the parent objects. */
18487347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
18497347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
18507347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
18517347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
18527347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(cur))
18537347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
18547347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
18557347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (j == handles->n) continue;
18567347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
18577347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
18587347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over all objects and distribute the storage ids */
18597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	while (1) {
18607347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		int changed = 0;
18617347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (i=0;i<cnt;i++) {
18627347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			unsigned char	*cur = dir+i*0x4c;
18637347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	oid = dtoh32a(cur + ptp_canon_dir_objectid);
18647347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
18657347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
18667347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	storageid;
18677347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
18687347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (!ISOBJECT(cur))
18697347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
18707347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
18717347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (j == handles->n) {
18727347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				/*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
18737347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
18747347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
18757347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 		storageid = (*oinfos)[j].StorageID;
18767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (storageid == 0xffffffff) continue;
18777347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextoid != 0xffffffff) {
18787347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
18797347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
18807347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
18817347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
18827347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
18837347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
18847347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
18857347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
18867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
18877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
18887347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextchild != 0xffffffff) {
18897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
18907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
18917347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
18927347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
18937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
18947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
18957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
18967347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
18977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
18987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
18997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		}
19007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		/* Check if we:
19017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed no entry (nothing more to do)
19027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed all of them at once (usually happens)
19037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * break if we do.
19047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 */
19057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!changed || (changed==nrofobs-1))
19067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			break;
19077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
19087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#undef ISOBJECT
19097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	return PTP_RC_OK;
19107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij}
1911