ptp-pack.c revision 0546a76acd169daf35572ece1f58c9b3bc7f0f56
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{
14896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int length = 0;
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{
15996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int packedlen = 0;
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
167d000c371601fafcf75d2de2d1060ee11be2007d6Linus 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
177d000c371601fafcf75d2de2d1060ee11be2007d6Linus Walleij#endif
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	}
185a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/*
186a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
187a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 *      why do we need ucs2strlen()?
188a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 */
189a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packedlen = ucs2strlen(ucs2str);
190a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (packedlen > PTP_MAXSTRLEN-1) {
191a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		*len=0;
192a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return;
193a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	}
194958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
1957f2343824550452974d78f5dbd94e64844355c33Linus Walleij	/* number of characters including terminating 0 (PTP standard confirmed) */
196a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	htod8a(&data[offset],packedlen+1);
197a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
198a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
199958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
200958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* The returned length is in number of characters */
201048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij	*len = (uint8_t) packedlen+1;
202eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
203eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
204a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline unsigned char *
205735f41692934a716158cf051d76e988febeca7eeLinus Walleijptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
206a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
2078b42ca3d3baeb7c8f3e5eca88c613adb612e4ec0Richard Low	uint8_t packed[PTP_MAXSTRLEN*2+3], len;
208a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t plen;
209a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	unsigned char *retcopy = NULL;
210d47b9218023a6b943a93faa743712ae072cba85cRichard Low
211d47b9218023a6b943a93faa743712ae072cba85cRichard Low	if (string == NULL)
212d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
213d47b9218023a6b943a93faa743712ae072cba85cRichard Low	else
214d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
215d47b9218023a6b943a93faa743712ae072cba85cRichard Low
216958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* returned length is in characters, then one byte for string length */
217958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	plen = len*2 + 1;
218048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij
219a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	retcopy = malloc(plen);
220735f41692934a716158cf051d76e988febeca7eeLinus Walleij	if (!retcopy) {
221735f41692934a716158cf051d76e988febeca7eeLinus Walleij		*packed_size = 0;
222a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return NULL;
223735f41692934a716158cf051d76e988febeca7eeLinus Walleij	}
224a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	memcpy(retcopy, packed, plen);
225735f41692934a716158cf051d76e988febeca7eeLinus Walleij	*packed_size = plen;
226a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return (retcopy);
227a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
228a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
229b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
230b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
231eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
232eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
233eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
234eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
235eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint32_t));
236eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
237eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
238eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
239eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
240eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
241eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
242eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
243b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
244f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
245f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij{
246f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	uint32_t i=0;
247f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
248f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	*data = malloc ((arraylen+1)*sizeof(uint32_t));
249f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	htod32a(&(*data)[0],arraylen);
250f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	for (i=0;i<arraylen;i++)
251f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
252f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	return (arraylen+1)*sizeof(uint32_t);
253f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij}
254f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
255f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijstatic inline uint32_t
256b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
257eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
258eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
259eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
260eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
261eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint16_t));
262eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
263eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
264eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
265eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
266eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
267eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
268eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
269eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* DeviceInfo pack/unpack */
270eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
271eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_StandardVersion		 0
272eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionID	 2
273eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionVersion	 6
274eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionDesc	 8
275eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_FunctionalMode		 8
276eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_OperationsSupported	10
277eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
278b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
279b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
280eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
281eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t len;
282eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	unsigned int totallen;
2837e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
284d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij	if (!data) return;
285d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij	if (datalen < 12) return;
2867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
287eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionID =
288eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh32a(&data[PTP_di_VendorExtensionID]);
289eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionVersion =
290eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
291eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionDesc =
292eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_string(params, data,
293eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_VendorExtensionDesc, &len);
294eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=len*2+1;
295eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->FunctionalMode =
296eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
297eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
298eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
299eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->OperationsSupported);
300eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
301eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
302eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
303eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->EventsSupported);
304eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
305eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DevicePropertiesSupported_len =
306eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_uint16_t_array(params, data,
307eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
308eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->DevicePropertiesSupported);
309eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
310eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
311eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
312eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->CaptureFormats);
313eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
314eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
315eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
316eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->ImageFormats);
317eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
318eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Manufacturer = ptp_unpack_string(params, data,
319eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
320eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
321eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
322eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Model = ptp_unpack_string(params, data,
323eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
324eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
325eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
326eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DeviceVersion = ptp_unpack_string(params, data,
327eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
328eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
329eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
330eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->SerialNumber = ptp_unpack_string(params, data,
331eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
332eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
333eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
334a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
335e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleijstatic void inline
336a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleijptp_free_DI (PTPDeviceInfo *di) {
337a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->SerialNumber) free (di->SerialNumber);
338a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->DeviceVersion) free (di->DeviceVersion);
339a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->Model) free (di->Model);
340a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->Manufacturer) free (di->Manufacturer);
341a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->ImageFormats) free (di->ImageFormats);
342a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->CaptureFormats) free (di->CaptureFormats);
343a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->VendorExtensionDesc) free (di->VendorExtensionDesc);
344a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->OperationsSupported) free (di->OperationsSupported);
345a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->EventsSupported) free (di->EventsSupported);
346a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->DevicePropertiesSupported) free (di->DevicePropertiesSupported);
347a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij}
3487e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3497e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij/* EOS Device Info unpack */
3507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijstatic inline void
3517e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
3527e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij{
3537e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int totallen = 4;
35496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
35596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	memset (di,0, sizeof(*di));
3567e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (datalen < 8) return;
3577e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3587e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	/* uint32_t struct len - ignore */
3597e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
3607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		totallen, &di->EventsSupported);
3617e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->EventsSupported) return;
3627e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
3637e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (totallen >= datalen) return;
3647e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3657e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
3667e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		totallen, &di->DevicePropertiesSupported);
3677e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->DevicePropertiesSupported) return;
3687e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
3697e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (totallen >= datalen) return;
3707e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3717e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->unk_len = ptp_unpack_uint32_t_array(params, data,
3727e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		totallen, &di->unk);
3737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->unk) return;
3747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->unk_len*sizeof(uint32_t)+4;
3757e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	return;
3767e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij}
3770d762ccc39331608119dd0267021b165e22de499Linus Walleij
3780d762ccc39331608119dd0267021b165e22de499Linus Walleijstatic inline void
3790d762ccc39331608119dd0267021b165e22de499Linus Walleijptp_free_EOS_DI (PTPCanonEOSDeviceInfo *di)
3800d762ccc39331608119dd0267021b165e22de499Linus Walleij{
3810d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->EventsSupported);
3820d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->DevicePropertiesSupported);
3830d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->unk);
3840d762ccc39331608119dd0267021b165e22de499Linus Walleij}
385eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
386eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectHandles array pack/unpack */
387eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
388eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oh				 0
389eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
390b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
391b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
392eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
393f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (len) {
394f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
395f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	} else {
396f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = 0;
397f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->Handler = NULL;
398f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
399eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
400eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
401eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StoreIDs array pack/unpack */
402eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
403eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_sids			 0
404eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
405b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
406b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
407eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
40896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij        if (!data && !len) {
40996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		sids->n = 0;
41096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		sids->Storage = NULL;
41196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		return;
41296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij        }
413eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
414eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	&sids->Storage);
415eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
416eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
417eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StorageInfo pack/unpack */
418eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
419eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageType		 0
420eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FilesystemType		 2
421eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_AccessCapability		 4
422eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_MaxCapability		 6
423eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInBytes		14
424eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInImages	22
425eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageDescription	26
426eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
427b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
428b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
429eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
430eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t storagedescriptionlen;
431eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
432eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
433eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
434eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
435eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
436eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
437eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
438eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageDescription=ptp_unpack_string(params, data,
439eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription, &storagedescriptionlen);
440eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->VolumeLabel=ptp_unpack_string(params, data,
441eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription+storagedescriptionlen*2+1,
442eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&storagedescriptionlen);
443eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
444eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
445eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectInfo pack/unpack */
446eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
447eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_StorageID		 0
448eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectFormat		 4
449eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ProtectionStatus		 6
450eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectCompressedSize	 8
451eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbFormat		12
452eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbCompressedSize	14
453eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixWidth		18
454eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixHeight		22
455eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixWidth		26
456eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixHeight		30
457eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImageBitDepth		34
458eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ParentObject		38
459eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationType		42
460eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationDesc		44
461eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_SequenceNumber		48
462eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_filenamelen		52
463eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_Filename			53
464eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
465a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* the max length assuming zero length dates. We have need 3 */
466a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* bytes for these. */
467a679b1c4d273f210abb6befc5d9954a25427c329Richard Low#define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
468a679b1c4d273f210abb6befc5d9954a25427c329Richard Low
469b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
470b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
471eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
472b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* oidata;
473eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
474eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen=0;
475a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	/* let's allocate some memory first; correct assuming zero length dates */
4760546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	oidata=malloc(PTP_oi_MaxLen + params->ocs64*4);
4770546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	*oidataptr=oidata;
478eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* the caller should free it after use! */
479eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0
480eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date="20020101T010101"; /* XXX Fake date */
481eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
4820546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	memset (oidata, 0, PTP_oi_MaxLen + params->ocs64*4);
483eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
484eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
485eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
486eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
4870546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (params->ocs64)
4880546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		oidata += 4;
489eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
490eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
491eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
492eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
493eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
494eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
495eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
496eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
497eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
498eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
499eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
500eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
501eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
502eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
503eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	filenamelen=(uint8_t)strlen(oi->Filename);
504eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
505eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
506eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
507eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
508eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
509eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/*
510eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 *XXX Fake date.
511eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * for example Kodak sets Capture date on the basis of EXIF data.
512eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * Spec says that this field is from perspective of Initiator.
513eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
514eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
515eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capturedatelen=strlen(capture_date);
516eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
517eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
518eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
519eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
520eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
521eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
522eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
523eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
524eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
525eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		  capture_date[i];
526eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
527eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
528eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* XXX this function should return dataset length */
5290546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3)+params->ocs64*4;
530eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
531eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
5323bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleijstatic time_t
5336db174f4d18af574fab991309e11010aa0eb4543Linus Walleijptp_unpack_PTPTIME (const char *str) {
5343bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char ptpdate[40];
5353bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char tmp[5];
5363bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	int  ptpdatelen;
5373bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	struct tm tm;
5383bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
5393bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	if (!str)
5403bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
5413bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	ptpdatelen = strlen(str);
5427e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen >= sizeof (ptpdate)) {
5436db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
5443bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
5457e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
5463bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strcpy (ptpdate, str);
5477e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen<15) {
5486db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
5493bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
5507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
5513bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
5523bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	memset(&tm,0,sizeof(tm));
5533bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate, 4);
5543bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[4] = 0;
5553bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_year=atoi (tmp) - 1900;
5563bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 4, 2);
5573bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5583bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mon = atoi (tmp) - 1;
5593bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 6, 2);
5603bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5613bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mday = atoi (tmp);
5623bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 9, 2);
5633bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5643bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_hour = atoi (tmp);
5653bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 11, 2);
5663bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5673bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_min = atoi (tmp);
5683bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 13, 2);
5693bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5703bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_sec = atoi (tmp);
571e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	tm.tm_isdst = -1;
5723bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	return mktime (&tm);
5733bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij}
5743bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
575b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
576b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
577eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
578eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
579eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen;
580eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date;
581eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
582eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
583eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
584eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
585eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
5860546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
5870546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	/* Stupid Samsung Galaxy developers emit a 64bit objectcompressedsize */
5880546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if ((data[PTP_oi_filenamelen] == 0) && (data[PTP_oi_filenamelen+4] != 0)) {
5890546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		params->ocs64 = 1;
5900546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		data += 4;
5910546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	}
592eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
593eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
594eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
595eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
596eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
597eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
598eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
599eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
600eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
601eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
602eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
6030546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
604eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
605eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
606eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
607eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
608eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* subset of ISO 8601, without '.s' tenths of second and
609eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * time zone
610eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
6116db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
612eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
613eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
6143bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	/* now the modification date ... */
615eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
616eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2
617eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		+capturedatelen*2+2,&capturedatelen);
6186db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->ModificationDate = ptp_unpack_PTPTIME(capture_date);
619eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
620eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
621eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
622eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Custom Type Value Assignement (without Length) macro frequently used below */
623b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define CTVAL(target,func) {			\
624b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(target))	\
625b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;			\
626b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	target = func(&data[*offset]);		\
627b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(target);		\
628eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
629eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
630b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define RARR(val,member,func)	{			\
631b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int n,j;					\
632b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(uint32_t))		\
633b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;				\
634b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	n = dtoh32a (&data[*offset]);			\
635b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(uint32_t);			\
636b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij							\
637b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.count = n;				\
638b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
639b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!val->a.v) return 0;			\
640b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (j=0;j<n;j++)				\
641b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(val->a.v[j].member, func);	\
642b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
643eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
644b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
645b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPV (
646b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPParams *params, unsigned char* data, int *offset, int total,
647b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPPropertyValue* value, uint16_t datatype
648b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij) {
649eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
650b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
651b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i8,dtoh8a);
652b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
653b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
654b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u8,dtoh8a);
655b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
656b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
657b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i16,dtoh16a);
658b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
659b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
660b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u16,dtoh16a);
661b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
662b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
663b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i32,dtoh32a);
664b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
665b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
666b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u32,dtoh32a);
667b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
668abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
669abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->i64,dtoh64a);
670abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
671abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
672abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->u64,dtoh64a);
673abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
674abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
675037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_UINT128:
676037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
677037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of uint128n");*/
678037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
679037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_INT128:
680037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
681037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of int128n");*/
682037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
683037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
684037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
685037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
686b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
687b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i8,dtoh8a);
688b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
689b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
690b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u8,dtoh8a);
691b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
692b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
693b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u16,dtoh16a);
694b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
695b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
696b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i16,dtoh16a);
697b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
698b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
699b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u32,dtoh32a);
700b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
701b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
702b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i32,dtoh32a);
703b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
704abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
705abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,u64,dtoh64a);
706abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
707abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
708abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,i64,dtoh64a);
709abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
710b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
711b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int arrays are unimplemented also */
712b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
713b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		uint8_t len;
714b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		/* XXX: max size */
715b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		value->str = ptp_unpack_string(params,data,*offset,&len);
716b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		*offset += len*2+1;
717b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!value->str)
718deddc3490b3084b802737017982285bfa58b382fLinus Walleij			return 1;
719b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
720eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
721037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	default:
722037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		return 0;
723b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
724b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
725eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
726eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
727eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Device Property pack/unpack */
728eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
729eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DevicePropertyCode	0
730eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DataType		2
731eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_GetSet			4
732eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_FactoryDefaultValue	5
733eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
734b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
735b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
736eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
737b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
738eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
739b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (dpd, 0, sizeof(*dpd));
740eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
741eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
742eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
743deddc3490b3084b802737017982285bfa58b382fLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
744b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
745b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_dpd_FactoryDefaultValue;
746b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
747b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
748deddc3490b3084b802737017982285bfa58b382fLinus Walleij	if ((dpd->DataType == PTP_DTC_STR) && (offset == dpdlen))
749deddc3490b3084b802737017982285bfa58b382fLinus Walleij		return 1;
750b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
751b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
752b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
753b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* if offset==0 then Data Type format is not supported by this
754b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   code or the Data Type is a string (with two empty strings as
755b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
756b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   not present. */
757b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
758b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (offset==PTP_dpd_FactoryDefaultValue)
759b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 1;
760b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
761b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	dpd->FormFlag=dtoh8a(&data[offset]);
762b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
763eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
764eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (dpd->FormFlag) {
765b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Range:
766b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
767b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
768b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
769b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
770b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
771b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
772eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
773b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Enumeration: {
774b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
775eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
776b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
777b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
778b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
779b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
780b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
781b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
782b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
783b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
784b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
785b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
786b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
787b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
788b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
789b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
790b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
791b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
792b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
793b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
794b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
795b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
796eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			}
797b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
798eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
799eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
800b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
801b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
802b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
803b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_devicepropdesc(dpd);
804b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
805eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
806eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
807b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/* (MTP) Object Property pack/unpack */
808b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_ObjectPropertyCode	0
809b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_DataType		2
810b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_GetSet			4
811b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_FactoryDefaultValue	5
812eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
813b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
814b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
815eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
816b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
817b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
818b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (opd, 0, sizeof(*opd));
819b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
820b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
821b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
822b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
823b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_opd_FactoryDefaultValue;
824b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
825b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
826b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
827b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GroupCode=dtoh32a(&data[offset]);
828b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint32_t);
829b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
830b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->FormFlag=dtoh8a(&data[offset]);
831b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
832b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
833b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	switch (opd->FormFlag) {
834b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Range:
835b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
836b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
837b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
838b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
839b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
840b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
841b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
842b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Enumeration: {
843b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
844b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define N	opd->FORM.Enum.NumberOfValues
845b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
846b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
847b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
848b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!opd->FORM.Enum.SupportedValue)
849b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
850b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
851b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
852b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
853b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
854b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
855b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
856b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
857b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
858b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
859b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
860b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
861b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
862b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
863b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				opd->FORM.Enum.NumberOfValues = i;
864b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
865b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			}
866b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
867b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
868b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
869eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
870b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
871b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
872b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_objectpropdesc(opd);
873b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
874eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
875eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
876eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
877b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
878b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
879eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
880b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* dpv=NULL;
881eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t size=0;
882b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int	i;
883eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
884eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
885b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
886b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int8_t);
887b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
888b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->i8);
889b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
890b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
891b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint8_t);
892b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
893b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->u8);
894b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
895b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
896b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int16_t);
897b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
898b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->i16);
899b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
900b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
901b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint16_t);
902b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
903b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->u16);
904b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
905b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
906b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int32_t);
907b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
908b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->i32);
909b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
910b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
911b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t);
912b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
913b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->u32);
914b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
915abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
916abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(int64_t);
917abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
918abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->i64);
919abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
920abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
921abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint64_t);
922abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
923abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->u64);
924abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
925b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
926b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_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			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
931b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
932b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
933b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int8_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			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
938b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
939b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
940b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_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			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
945b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
946b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
947b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int16_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			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
952b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
953b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
954b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
955b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
956b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
957b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
958cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
959b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
960b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
961b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
962b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
963b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
964b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
965cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
966b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
967abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
968abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
969abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
970abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
971abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
972cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
973abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
974abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
975abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
976abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
977abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
978abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
979cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
980abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
981b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
982b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
983735f41692934a716158cf051d76e988febeca7eeLinus Walleij		dpv=ptp_get_packed_stringcopy(params, value->str, &size);
984eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
985b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
986eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
987eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*dpvptr=dpv;
988eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return size;
98999310d4445697da39f22dff35457c75e35e97171Linus Walleij}
99099310d4445697da39f22dff35457c75e35e97171Linus Walleij
99199310d4445697da39f22dff35457c75e35e97171Linus Walleij#define MAX_MTP_PROPS 127
99299310d4445697da39f22dff35457c75e35e97171Linus Walleijstatic inline uint32_t
9931e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
99499310d4445697da39f22dff35457c75e35e97171Linus Walleij{
99599310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char* opldata;
9961e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *propitr;
99799310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char *packedprops[MAX_MTP_PROPS];
99899310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t packedpropslens[MAX_MTP_PROPS];
99939b9374f23451201dece736db13f0f648584dc32Linus Walleij	uint32_t packedobjecthandles[MAX_MTP_PROPS];
100099310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropsids[MAX_MTP_PROPS];
100199310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropstypes[MAX_MTP_PROPS];
100299310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t totalsize = 0;
100399310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t bufp = 0;
100499310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t noitems = 0;
100599310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t i;
100699310d4445697da39f22dff35457c75e35e97171Linus Walleij
100799310d4445697da39f22dff35457c75e35e97171Linus Walleij	totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
10081e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	propitr = props;
10091e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	while (nrofprops-- && noitems < MAX_MTP_PROPS) {
10106c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		/* Object Handle */
101139b9374f23451201dece736db13f0f648584dc32Linus Walleij		packedobjecthandles[noitems]=propitr->ObjectHandle;
101299310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint32_t); /* Object ID */
101399310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Metadata type */
101499310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropsids[noitems]=propitr->property;
101599310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
101699310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Data type */
101799310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropstypes[noitems]= propitr->datatype;
101899310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
101999310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Add each property to be sent. */
102099310d4445697da39f22dff35457c75e35e97171Linus Walleij	        packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
102199310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += packedpropslens[noitems];
102299310d4445697da39f22dff35457c75e35e97171Linus Walleij		noitems ++;
10231e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		propitr ++;
102499310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
102599310d4445697da39f22dff35457c75e35e97171Linus Walleij
102699310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Allocate memory for the packed property list */
102799310d4445697da39f22dff35457c75e35e97171Linus Walleij	opldata = malloc(totalsize);
102899310d4445697da39f22dff35457c75e35e97171Linus Walleij
102999310d4445697da39f22dff35457c75e35e97171Linus Walleij	htod32a(&opldata[bufp],noitems);
103099310d4445697da39f22dff35457c75e35e97171Linus Walleij	bufp += 4;
103199310d4445697da39f22dff35457c75e35e97171Linus Walleij
103299310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Copy into a nice packed list */
103399310d4445697da39f22dff35457c75e35e97171Linus Walleij	for (i = 0; i < noitems; i++) {
103499310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Object ID */
10356c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		htod32a(&opldata[bufp],packedobjecthandles[i]);
103699310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint32_t);
103799310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropsids[i]);
103899310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
103999310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropstypes[i]);
104099310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
104199310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* The copy the actual property */
104299310d4445697da39f22dff35457c75e35e97171Linus Walleij		memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
104399310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += packedpropslens[i];
104499310d4445697da39f22dff35457c75e35e97171Linus Walleij		free(packedprops[i]);
104599310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
104699310d4445697da39f22dff35457c75e35e97171Linus Walleij	*opldataptr = opldata;
104799310d4445697da39f22dff35457c75e35e97171Linus Walleij	return totalsize;
1048eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1049eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
10501e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijstatic int
10511e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij_compare_func(const void* x, const void *y) {
10521e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *px = x;
10531e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *py = y;
10541e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
10551e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	return px->ObjectHandle - py->ObjectHandle;
10561e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij}
10571e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
10588d82d2f4b0794e41ec26289045867eebb3496b8cRichard Lowstatic inline int
10591e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
10608d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low{
1061277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	uint32_t prop_count = dtoh32a(data);
10621e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *props = NULL;
1063277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	int offset = 0, i;
1064277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1065277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	if (prop_count == 0) {
10661e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		*pprops = NULL;
1067277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		return 0;
1068277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
1069d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij	ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
1070277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	data += sizeof(uint32_t);
10713bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	len -= sizeof(uint32_t);
10721e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	props = malloc(prop_count * sizeof(MTPProperties));
10731e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	if (!props) return 0;
1074277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	for (i = 0; i < prop_count; i++) {
10753bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		if (len <= 0) {
1076d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
10773bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL", i);
10783bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i);
1079d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			qsort (props, i, sizeof(MTPProperties),_compare_func);
1080d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			*pprops = props;
10813bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			return i;
10823bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		}
10831e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].ObjectHandle = dtoh32a(data);
1084277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint32_t);
1085277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint32_t);
1086277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
10871e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].property = dtoh16a(data);
1088277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1089277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1090277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
10911e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].datatype = dtoh16a(data);
1092277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1093277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1094277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1095277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		offset = 0;
10961e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype);
1097277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += offset;
1098277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= offset;
1099277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
11001e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
11011e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	*pprops = props;
1102277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	return prop_count;
11038d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low}
11048d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low
1105eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1106eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP USB Event container unpack
1107eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1108eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1109eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1110eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Length		0
1111eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Type		4
1112eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Code		6
1113eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_TransId		8
1114eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param1		12
1115eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param2		16
1116eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param3		20
1117eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1118b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
11197e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
1120eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
11217e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int	length;
11227e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int	type;
11237e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
1124eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1125eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
11267e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	memset(ec,0,sizeof(*ec));
11277e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	length=dtoh32a(&data[PTP_ec_Length]);
11287e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	type = dtoh16a(&data[PTP_ec_Type]);
1129b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
11307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Code=dtoh16a(&data[PTP_ec_Code]);
11317e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
11327e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
11337e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (type!=PTP_USB_CONTAINER_EVENT) {
11347e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ptp_debug (params, "Unknown canon event type %d (code=%x,tid=%x), please report!",type,ec->Code,ec->Transaction_ID);
11357e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		return;
11367e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
11377e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param1+4)) {
11387e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
11397e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=1;
11407e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
11417e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param2+4)) {
11427e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
11437e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=2;
11447e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
11457e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param3+4)) {
11467e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
11477e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=3;
11487e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
1149eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1150eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1151eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1152eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP Canon Folder Entry unpack
1153eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1154eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1155eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectHandle		0
1156eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectFormatCode	4
1157eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Flags			6
1158eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectSize		7
1159eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Time			11
1160eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Filename		15
1161eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1162b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1163b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1164eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1165eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
1166eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1167eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
1168eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
1169eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
1170eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
1171b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
1172eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
1173eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1174b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
1175b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
1176b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
117796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij/*
117896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij    PTP Canon EOS Folder Entry unpack
117996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0: 00 00 08 a0     objectid
118096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij4: 01 00 02 00     storageid
118196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij8: 01 30 00 00     ofc
118296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij12: 01 00
118396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij14: 00 00
118496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij16: 11 00 00 00
118596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij20: 00 00 00 00
118696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij24: 00 00 00 80
118796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij28: 00 00 08 a0
118896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij32: 4d 49 53 43-00 00 00 00 00 00 00 00     name
118996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij00 00 00 00
119096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij84 bc 74 46     objectime
119196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
119296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
119396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij(normal PTP GetObjectInfo)
119496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus WalleijObjectInfo for 'IMG_0199.JPG':
119596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  Object ID: 0x92740c72
119696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  StorageID: 0x00020001
119796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ObjectFormat: 0x3801
119896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ProtectionStatus: 0x0000
119996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ObjectCompressedSize: 2217241
120096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbFormat: 0x3808
120196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbCompressedSize: 5122
120296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbPixWidth: 160
120396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbPixHeight: 120
120496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImagePixWidth: 4000
120596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImagePixHeight: 3000
120696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImageBitDepth: 24
120796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ParentObject: 0x92740000
120896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  AssociationType: 0x0000
120996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  AssociationDesc: 0x00000000
121096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  SequenceNumber: 0x00000000
121196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ModificationDate: 0x4d985ff0
121296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  CaptureDate: 0x4d985ff0
121396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
121496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0010  38 00 00 00  Size of this entry
121596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0014  72 0c 74 92  OID
121696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0018  01 00 02 00  StorageID
121796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij001c  01 38 00 00  OFC
121896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0020  00 00 00 00 00 00 00 00  ?
121996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0028  19 d5 21 00  Size
122096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij002c  00 00 74 92  ?
122196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0030  70 0c 74 92  OID
122296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0034  49 4d 47 5f-30 31 39 39 2e 4a 50 47  IMG_0199.JPG
122396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0040  00 00 00 00
122496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0044  10 7c 98 4d Time
122596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
122696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
122796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij*/
122896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectHandle		0
122996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_StorageID		4
123096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectFormatCode	8
123196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Flags			12
123296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectSize		20
123396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Filename		32
123496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Time			48
123596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
123696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleijstatic inline void
123796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleijptp_unpack_Canon_EOS_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
123896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij{
123996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int i;
124096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
124196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cefe_ObjectHandle]);
124296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cefe_ObjectFormatCode]);
124396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->Flags=dtoh8a(&data[PTP_cefe_Flags]);
124496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cefe_ObjectSize]);
124596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cefe_Time]);
124696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
124796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		fe->Filename[i]=(char)data[PTP_cefe_Filename+i];
124896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij}
124996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
125096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
12511a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint16_t
12521a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
12531a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
12541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	/*
12550546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  EOS ImageFormat entries (of at least the 5DM2 and the 400D) look like this:
12561a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: number of entries / generated files (1 or 2)
12571a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: size of this entry in bytes (most likely allways 0x10)
12581a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image type (1 == JPG, 6 == RAW)
12590546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		uint32: image size (0 == Large, 1 == Medium, 2 == Small, 0xe == S1, 0xf == S2, 0x10 == S3)
12601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW)
12610546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  If the number of entries is 2 the last 4 uint32 repeat.
12621a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12631a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  example:
12641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		0: 0x       1
12651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		1: 0x      10
12661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		2: 0x       6
12671a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		3: 0x       1
12681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		4: 0x       4
12691a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12700546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  The idea is to simply 'condense' these values to just one uint16 to be able to conveniently
12711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  use the available enumeration facilities (look-up table). The image size and compression
12721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  values fully describe the image format. Hence we generate a uint16 with the four nibles set
12731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  as follows: entry 1 size | entry 1 compression | entry 2 size | entry 2 compression.
12741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  The above example would result in the value 0x1400.
12750546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
12760546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  The EOS 5D Mark III (and possibly other high-end EOS as well) added the extra fancy S1, S2
12770546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  and S3 JPEG options. S1 replaces the old Small. -1 the S1/S2/S3 to prevent the 0x10 overflow.
12781a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  */
12791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12801a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	const unsigned char* d = *data;
12811a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = dtoh32a( d );
12821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t l, s1, c1, s2 = 0, c2 = 0;
12831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n != 1 && n !=2) {
12851a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
12861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
12871a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
12881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	l = dtoh32a( d+=4 );
12901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (l != 0x10) {
12911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
12921a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
12931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
12941a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	d+=4; /* skip type */
12961a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	s1 = dtoh32a( d+=4 );
12971a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	c1 = dtoh32a( d+=4 );
12981a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
12991a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n == 2) {
13001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		l = dtoh32a( d+=4 );
13011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		if (l != 0x10) {
13021a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
13031a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			return 0;
13041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		}
13051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		d+=4; /* skip type */
13061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		s2 = dtoh32a( d+=4 );
13071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		c2 = dtoh32a( d+=4 );
13081a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
13091a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13101a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	*data = (unsigned char*) d+4;
13111a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13120546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	/* deal with S1/S2/S3 JPEG sizes, see above. */
13130546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if( s1 >= 0xe )
13140546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		s1--;
13150546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if( s2 >= 0xe )
13160546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		s2--;
13170546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
13191a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
13201a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13211a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint32_t
13221a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
13231a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
13241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = (value & 0xFF) ? 2 : 1;
13251a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t s = 4 + 0x10 * n;
13261a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13271a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if( !data )
13281a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return s;
13291a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13300546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner#define PACK_5DM3_SMALL_JPEG_SIZE( X ) (X) >= 0xd ? (X)+1 : (X)
13310546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13321a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=0, n);
13331a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, 0x10);
13341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, ((value >> 8) & 0xF) == 4 ? 6 : 1);
13350546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 12) & 0xF));
13361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, (value >> 8) & 0xF);
13371a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13381a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n==2) {
13391a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, 0x10);
13401a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, ((value >> 0) & 0xF) == 4 ? 6 : 1);
13410546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 4) & 0xF));
13421a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, (value >> 0) & 0xF);
13431a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
13441a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13450546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner#undef PACK_5DM3_SMALL_JPEG_SIZE
13460546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13470546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return s;
13480546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner}
13490546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13500546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerstatic inline char*
13510546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerptp_unpack_EOS_CustomFuncEx (PTPParams* params, unsigned char** data )
13520546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner{
13530546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t s = dtoh32a( *data );
13540546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t n = s/4, i;
13550546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	char* str = (char*)malloc( s ); // n is size in uint32, average len(itoa(i)) < 4 -> alloc n chars
13560546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (!str)
13570546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		return str;
13580546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	char* p = str;
13590546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13600546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	for (i=0; i < n; ++i)
13610546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		p += sprintf(p, "%x,", dtoh32a( *data + 4*i ));
13620546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13630546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return str;
13640546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner}
13650546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13660546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerstatic inline uint32_t
13670546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerptp_pack_EOS_CustomFuncEx (PTPParams* params, unsigned char* data, char* str)
13680546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner{
13690546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t s = strtoul(str, NULL, 16);
13700546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t n = s/4, i, v;
13710546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13720546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (!data)
13730546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		return s;
13740546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13750546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	for (i=0; i<n; i++)
13760546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	{
13770546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		v = strtoul(str, &str, 16);
13780546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		str++; // skip the ',' delimiter
13790546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		htod32a(data + i*4, v);
13800546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	}
13810546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return s;
13831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
13841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
1385b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/*
1386f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij    PTP EOS Changes Entry unpack
1387f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij*/
1388f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Size		0
1389f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Type		4
1390f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1391f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Subtype	8	/* only for properties */
1392f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Val_Data	0xc	/* only for properties */
1393f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Type	0xc	/* only for property descs */
1394f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Count	0x10	/* only for property descs */
1395f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Data	0x14	/* only for property descs */
1396f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1397d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_RequestObjectTransfer */
1398d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_ObjectID	8
1399d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_OFC		0x0c
1400d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Size		0x14
1401d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Name		0x1c
1402d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij
1403d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_ObjectAddedEx */
1404d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_ObjectID	8
1405d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_StorageID	0x0c
1406d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_OFC		0x10
1407d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Size		0x1c
1408d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Parent	0x20
1409d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Name		0x28
1410f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1411f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijstatic inline int
1412f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **ce)
1413f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij{
1414f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	int	i = 0, entries = 0;
1415f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	unsigned char	*curdata = data;
1416f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1417f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (data==NULL)
1418f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		return 0;
1419f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1420f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1421f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1422f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1423f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
1424f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		if ((size == 8) && (type == 0))
1425f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1426f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		entries++;
1427f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
14289d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij	*ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
1429f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (!*ce) return 0;
1430f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1431f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	curdata = data;
1432f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1433f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1434f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1435f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1436d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1437d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij		(*ce)[i].u.info = NULL;
1438f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		switch (type) {
1439d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		case  PTP_EC_CANON_EOS_ObjectAddedEx:
1440f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
1441d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
1442d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.StorageID 		= dtoh32a(&curdata[PTP_ece_OA_StorageID]);
1443d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ParentObject	= dtoh32a(&curdata[PTP_ece_OA_Parent]);
1444d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OA_OFC]);
1445d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
1446d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OA_Name]));
1447d4637506d9551957a152cab2cfb80fdfed029424Linus 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);
1448d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			break;
1449d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		case  PTP_EC_CANON_EOS_RequestObjectTransfer:
1450d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
1451f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
1452d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.StorageID 		= 0; /* use as marker */
1453f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OI_OFC]);
1454d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ParentObject	= 0; /* check, but use as marker */
1455f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
1456f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OI_Name]));
14573bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
1458d4637506d9551957a152cab2cfb80fdfed029424Linus 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);
1459f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
14607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case  PTP_EC_CANON_EOS_AvailListChanged: {	/* property desc */
1461f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1462f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
1463f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
1464e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij			unsigned char	*xdata = &curdata[PTP_ece_Prop_Desc_Data];
1465f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			int		j;
1466f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			PTPDevicePropDesc	*dpd;
1467f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
14687e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype);
1469f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			for (j=0;j<params->nrofcanon_props;j++)
1470f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (params->canon_props[j].proptype == proptype)
1471f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1472f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (j==params->nrofcanon_props) {
14733bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
1474f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1475f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1476f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			dpd = &params->canon_props[j].dpd;
14777e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			/* 1 - uint16 ?
14787e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 3 - uint16
14797e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 7 - string?
14807e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 */
1481f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (propxtype != 3) {
14823bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled.", i, propxtype, proptype);
14833bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++)
1484e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					ptp_debug (params, "    %d: %02x", j, xdata[j]);
1485f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1486f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
14871a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			if (! propxcnt)
14881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
14891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
14901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
14911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				   i, propxtype, proptype, dpd->DataType, propxcnt);
14921a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FormFlag = PTP_DPFF_Enumeration;
14931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.NumberOfValues = propxcnt;
14940d762ccc39331608119dd0267021b165e22de499Linus Walleij			if (dpd->FORM.Enum.SupportedValue) free (dpd->FORM.Enum.SupportedValue);
14951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
14961a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
14971a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			switch (proptype) {
14981a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormat:
14991a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatCF:
15001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatSD:
15011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatExtHD:
15021a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* special handling of ImageFormat properties */
1503f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<propxcnt;j++) {
15041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->FORM.Enum.SupportedValue[j].u16 =
1505e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij							dtoh16( ptp_unpack_EOS_ImageFormat( params, &xdata ) );
15061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
15071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
15081a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
15091a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			default:
15101a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* 'normal' enumerated types */
15111a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (dpd->DataType) {
15121a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX( TYPE, CONV )\
15131a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<propxcnt;j++) { \
1514e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(xdata); \
1515e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(xdata)); \
1516e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						xdata += 4; /* might only be for propxtype 3 */ \
15171a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					} \
15181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
15191a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15201a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_INT16:	XX( i16, dtoh16a );
15211a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT32:	XX( u32, dtoh32a );
15221a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT16:	XX( u16, dtoh16a );
15231a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT8:	XX( u8,  dtoh8a );
15241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
15251a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				default:
1526e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, raw values:", i, dpd->DataType, proptype, dtoh32a(xdata));
1527e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, xdata+=4) /* 4 is good for propxtype 3 */
1528e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %3d: 0x%8x", j, dtoh32a(xdata));
15291a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
1530f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1531f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1532f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1533f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
15347e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case PTP_EC_CANON_EOS_PropValueChanged:
1535f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (size >= 0xc) {	/* property info */
1536f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				int j;
1537f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1538e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij				unsigned char	*xdata = &curdata[PTP_ece_Prop_Val_Data];
1539f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				PTPDevicePropDesc	*dpd;
1540f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
15411a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				ptp_debug (params, "event %d: EOS prop %04x info record, datasize is %d", i, proptype, size-PTP_ece_Prop_Val_Data);
1542f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<params->nrofcanon_props;j++)
1543f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (params->canon_props[j].proptype == proptype)
1544f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						break;
1545f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (j<params->nrofcanon_props) {
1546f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (	(params->canon_props[j].size != size) ||
1547e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						(memcmp(params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data))) {
1548f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
1549e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						memcpy (params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data);
1550f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					}
1551f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				} else {
1552f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (j)
1553f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
1554f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					else
1555f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = malloc(sizeof(params->canon_props[0]));
1556f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].type = type;
1557f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].proptype = proptype;
1558f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].size = size;
1559f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
1560e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					memcpy(params->canon_props[j].data, xdata, size-PTP_ece_Prop_Val_Data);
1561f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
1562f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.GetSet = 1;
1563f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
1564f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->nrofcanon_props = j+1;
1565f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1566f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				dpd = &params->canon_props[j].dpd;
15671a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
1568d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
1569d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				(*ce)[i].u.propid = proptype;
1570d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
15711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* fix GetSet value */
15721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (proptype) {
15731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX(x) case PTP_DPC_CANON_##x:
15741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusMode)
15751a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryPower)
15761a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatterySelect)
15771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ModelID)
15781a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_PTPExtensionVersion)
15791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DPOFVersion)
15801a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AvailableShots)
15811a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentStorage)
15821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentFolder)
15831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenu)
15841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenuList)
15851a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_HDDirectoryStructure)
15861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryInfo)
15871a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AdapterInfo)
15881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensStatus)
15891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CardExtension)
15901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_TempStatus)
15911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ShutterCounter)
15921a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_SerialNumber)
15931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfFieldPreview)
15941a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EVFRecordStatus)
15951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LvAfSystem)
15961a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusInfoEx)
15971a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfField)
15981a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_Brightness)
15991a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EFComp)
16001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensName)
16011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensID)
16021a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
16031a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						dpd->GetSet = PTP_DPGS_Get;
16041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						break;
16051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
16061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* set DataType */
1608f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (proptype) {
1609ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DPC_CANON_EOS_CameraTime:
1610d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_AvailableShots:
1611d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CaptureDestination:
1612d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXA:
1613d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXB:
1614d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentStorage:
1615d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentFolder:
1616d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ShutterCounter:
1617d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ModelID:
1618d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LensID:
1619d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_StroboFiring:
1620ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
1621ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
16220d762ccc39331608119dd0267021b165e22de499Linus Walleij				/* enumeration for AEM is never provided, but is available to set */
16230d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_AutoExposureMode:
16240d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
16250d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FormFlag = PTP_DPFF_Enumeration;
16260d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FORM.Enum.NumberOfValues = 0;
16270d762ccc39331608119dd0267021b165e22de499Linus Walleij					break;
1628f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Aperture:
1629f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ShutterSpeed:
1630f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ISOSpeed:
16317e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_FocusMode:
16327e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorSpace:
16337e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_BatteryPower:
1634e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BatterySelect:
1635d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_PTPExtensionVersion:
16361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_DriveMode:
16371a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_AEB:
1638e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BracketMode:
1639e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_QuickReviewTime:
16400d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFMode:
16410d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFOutputDevice:
1642f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
1643f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1644f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_PictureStyle:
1645f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalance:
1646f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_MeteringMode:
16477e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ExpCompensation: /* actually int8 if you calculate */
1648f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT8;
1649f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1650f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Owner:
16511a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Artist:
16521a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Copyright:
16531a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_SerialNumber:
16541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_LensName:
1655f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_STR;
1656f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
16577e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
16587e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
16597e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					dpd->DataType = PTP_DTC_INT16;
16607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
16617e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
16627e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case 0xd114:
16637e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DPOFVersion:
16641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
16651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
16661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1667e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
16681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
16697e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc1:
16707e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc2:
16717e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc3:
16727e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc4:
16737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc5:
16747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc6:
16757e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc7:
16767e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc8:
16777e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc9:
16787e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc10:
16797e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc11:
16801a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT8;
16811a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint8", i ,proptype, size-PTP_ece_Prop_Val_Data);
16827e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1683e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
16841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					/* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */
1685e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					xdata += 4;
16867e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
16877e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* yet unknown 32bit props */
16887e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorTemperature:
16897e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WftStatus:
16907e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_LensStatus:
16917e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CardExtension:
16927e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_TempStatus:
16937e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_PhotoStudioMode:
16947e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfFieldPreview:
16957e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFSharpness:
16967e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFWBMode:
16977e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
16987e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFColorTemp:
1699d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_EVFRecordStatus:
1700d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ExposureSimMode:
1701d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvAfSystem:
1702d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_MovSize:
1703d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfField:
1704d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvViewTypeSelect:
17050d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
17067e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
17071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
17081a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
17091a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
1710e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: 0x%8x", j, ((uint32_t*)xdata)[j]);
17117e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
1712d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				/* ImageFormat properties have to be ignored here, see special handling below */
1713d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
1714d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
1715d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
1716d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
17170546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				case PTP_DPC_CANON_EOS_CustomFuncEx:
1718d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
1719f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
17203bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
17213bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1722e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
1723f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1724f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1725f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (dpd->DataType) {
1726ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DTC_UINT32:
1727e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u32	= dtoh32a(xdata);
1728e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u32		= dtoh32a(xdata);
17293bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
1730ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
1731f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT16:
1732e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= dtoh16a(xdata);
1733e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u16		= dtoh16a(xdata);
17343bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
1735f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1736f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT8:
1737e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u8	= dtoh8a(xdata);
1738e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u8		= dtoh8a(xdata);
17393bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
1740f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1741f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_STR: {
17421a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
1743f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					uint8_t len = 0;
1744f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->FactoryDefaultValue.str	= ptp_unpack_string(params, data, 0, &len);
1745f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->CurrentValue.str		= ptp_unpack_string(params, data, 0, &len);
17461a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#else
17470d762ccc39331608119dd0267021b165e22de499Linus Walleij					if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
1748e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.str	= strdup( (char*)xdata );
17490d762ccc39331608119dd0267021b165e22de499Linus Walleij
17500d762ccc39331608119dd0267021b165e22de499Linus Walleij					if (dpd->CurrentValue.str) free (dpd->CurrentValue.str);
1751e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.str		= strdup( (char*)xdata );
17521a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#endif
17537e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
1754f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1755f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1756f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
1757f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					/* debug is printed in switch above this one */
1758f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1759f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
17601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
17610546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				/* ImageFormat and customFuncEx special handling (WARNING: dont move this in front of the dpd->DataType switch!) */
1762d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				switch (proptype) {
1763d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
1764d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
1765d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
1766d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1767d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
1768e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= ptp_unpack_EOS_ImageFormat( params, &xdata );
1769d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->CurrentValue.u16		= dpd->FactoryDefaultValue.u16;
1770d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					ptp_debug (params,"event %d: decoded imageformat, currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
1771d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
17720546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				case PTP_DPC_CANON_EOS_CustomFuncEx:
17730546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->DataType = PTP_DTC_STR;
17740546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
17750546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					if (dpd->CurrentValue.str)	  free (dpd->CurrentValue.str);
17760546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->FactoryDefaultValue.str	= ptp_unpack_EOS_CustomFuncEx( params, &data );
17770546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->CurrentValue.str		= strdup( (char*)dpd->FactoryDefaultValue.str );
17780546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					ptp_debug (params,"event %d: decoded custom function, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
17790546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					break;
1780d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				}
1781d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
1782f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1783f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1784d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij		case PTP_EC_CANON_EOS_CameraStatusChanged:
1785d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			ptp_debug (params, "event %d: EOS event CameraStatusChanged (size %d)", i, size);
1786d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS;
1787d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			(*ce)[i].u.status =  dtoh32a(curdata+8);
17889e09ad0e32cbdac88637d4ee2cc02ca3b771ca40Linus Walleij			params->eos_camerastatus = dtoh32a(curdata+8);
1789d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			break;
17907e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case 0: /* end marker */
17917e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size == 8) /* no output */
17927e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				break;
17937e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
17947e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			break;
179596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		case PTP_EC_CANON_EOS_BulbExposureTime:
179696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
179796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			(*ce)[i].u.info = malloc(strlen("BulbExposureTime 123456789"));
179896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			sprintf ((*ce)[i].u.info, "BulbExposureTime %d",  dtoh32a(curdata+8));
179996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			break;
1800f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		default:
1801d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			switch (type) {
1802d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij#define XX(x)		case PTP_EC_CANON_EOS_##x: 								\
1803d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				ptp_debug (params, "event %d: unhandled EOS event "#x" (size %d)", i, size); 	\
1804d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				(*ce)[i].u.info = malloc(strlen("unhandled EOS event "#x" (size 123456789)"));	\
1805d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				sprintf ((*ce)[i].u.info, "unhandled EOS event "#x" (size %d)",  size);		\
1806d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				break;
1807d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetEvent)
1808d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectRemoved)
1809d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetObjectInfoEx)
1810d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageStatusChanged)
1811d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageInfoChanged)
1812d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectInfoChangedEx)
1813d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectContentChanged)
1814d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(WillSoonShutdown)
1815d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ShutdownTimerUpdated)
1816d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransfer)
1817d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferDT)
1818d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransferDT)
1819d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreAdded)
1820d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreRemoved)
1821d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(BulbExposureTime)
1822d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RecordingTime)
1823d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferTS)
1824d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(AfResult)
1825d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#undef XX
1826d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			default:
1827d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
1828d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				break;
1829d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			}
18307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size >= 0x8) {	/* event info */
18317e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				int j;
1832d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				for (j=8;j<size;j++)
1833d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij					ptp_debug (params, "    %d: %02x", j, curdata[j]);
18347e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			}
1835f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1836f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1837f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1838f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
1839f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		i++;
18409d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij		if ((size == 8) && (type == 0))
18419d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij			break;
1842f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
18430d762ccc39331608119dd0267021b165e22de499Linus Walleij	if (!entries) {
18440d762ccc39331608119dd0267021b165e22de499Linus Walleij		free (*ce);
18450d762ccc39331608119dd0267021b165e22de499Linus Walleij		*ce = NULL;
18460d762ccc39331608119dd0267021b165e22de499Linus Walleij	}
1847f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	return entries;
1848f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij}
1849f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1850f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij/*
1851b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij    PTP USB Event container unpack for Nikon events.
1852b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij*/
1853b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Length		0
1854b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Code		2
1855b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Param1		4
1856b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Size		6
1857b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
18587e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, int *cnt)
1859b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij{
1860b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i;
1861b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1862b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = NULL;
1863b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (data == NULL)
1864b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1865b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (len < PTP_nikon_ec_Code)
1866b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1867b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
1868b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
1869b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
18700d762ccc39331608119dd0267021b165e22de499Linus Walleij	if (!*cnt)
18710d762ccc39331608119dd0267021b165e22de499Linus Walleij		return;
18720d762ccc39331608119dd0267021b165e22de499Linus Walleij
18737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	*ec = malloc(sizeof(PTPContainer)*(*cnt));
1874b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1875b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<*cnt;i++) {
18767e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		memset(&(*ec)[i],0,sizeof(PTPContainer));
18777e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
18787e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
18797e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Nparam	= 1;
1880b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1881eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1882eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1883eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1884b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
1885b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
1886b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i, len = 0;
1887b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint8_t	retlen;
1888b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char *curdata;
1889b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1890b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	len =	2*(strlen(text->title)+1)+1+
1891b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[0])+1)+1+
1892b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[1])+1)+1+
1893b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[2])+1)+1+
1894b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[3])+1)+1+
1895b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[4])+1)+1+
1896b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		4*2+2*4+2+4+2+5*4*2;
1897b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*data = malloc(len);
1898b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!*data) return 0;
1899b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1900b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	curdata = *data;
1901b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,100);curdata+=2;
1902b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1);curdata+=2;
1903b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0);curdata+=2;
1904b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1000);curdata+=2;
1905b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1906b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1907b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1908b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1909b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,6);curdata+=2;
1910b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1911b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1912b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1913b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0x10);curdata+=2;
1914b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1915b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<5;i++) {
1916b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1917b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x10);curdata+=2;
1918b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x01);curdata+=2;
1919b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x02);curdata+=2;
1920b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x06);curdata+=2;
1921b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1922b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return len;
1923b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
19247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
19257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_version	0x00
19267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_ofc	0x02
19277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk1	0x04
19287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_objectid	0x08
19297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_parentid	0x0c
19307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_previd	0x10	/* in same dir */
19317347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextid	0x14	/* in same dir */
19327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextchild	0x18	/* down one dir */
19337347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_storageid	0x1c	/* only in storage entry */
19347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_name	0x20
19357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_flags	0x2c
19367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_size	0x30
19377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unixtime	0x34
19387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_year	0x38
19397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_month	0x39
19407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_mday	0x3a
19417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_hour	0x3b
19427347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_minute	0x3c
19437347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_second	0x3d
19447347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk2	0x3e
19457347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_thumbsize	0x40
19467347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_width	0x44
19477347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_height	0x48
19487347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
19497347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijstatic inline uint16_t
19507347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijptp_unpack_canon_directory (
19517347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPParams		*params,
19527347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned char		*dir,
19537347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		cnt,
19547347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectHandles	*handles,
19557347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectInfo		**oinfos,	/* size(handles->n) */
19567347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		**flags		/* size(handles->n) */
19577347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij) {
19587347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned int	i, j, nrofobs = 0, curob = 0;
19597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
19607347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
19617347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++)
19627347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(dir+i*0x4c)) nrofobs++;
19637347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->n = nrofobs;
19647347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs);
19657347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!handles->Handler) return PTP_RC_GeneralError;
19667347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*oinfos = calloc(sizeof((*oinfos)[0]),nrofobs);
19677347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*oinfos) return PTP_RC_GeneralError;
19687347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*flags  = calloc(sizeof((*flags)[0]),nrofobs);
19697347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*flags) return PTP_RC_GeneralError;
19707347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
19717347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Migrate data into objects ids, handles into
19727347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the object handler array.
19737347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 */
19747347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	curob = 0;
19757347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
19767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
19777347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		PTPObjectInfo	*oi = (*oinfos)+curob;
19787347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
19797347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!ISOBJECT(cur))
19807347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
19817347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
19827347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
19837347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->StorageID		= 0xffffffff;
19847347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectFormat	= dtoh16a(cur + ptp_canon_dir_ofc);
19857347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ParentObject	= dtoh32a(cur + ptp_canon_dir_parentid);
19867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->Filename		= strdup((char*)(cur + ptp_canon_dir_name));
19877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
19887347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ThumbCompressedSize	= dtoh32a(cur + ptp_canon_dir_thumbsize);
19897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixWidth	= dtoh32a(cur + ptp_canon_dir_width);
19907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixHeight	= dtoh32a(cur + ptp_canon_dir_height);
19917347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->CaptureDate		= oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
19927347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*flags)[curob]		= dtoh32a(cur + ptp_canon_dir_flags);
19937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		curob++;
19947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
19957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over Storage ID entries and distribute the IDs to
19967347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the parent objects. */
19977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
19987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
19997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
20007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(cur))
20027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
20037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
20047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (j == handles->n) continue;
20057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
20067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
20077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over all objects and distribute the storage ids */
20087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	while (1) {
20097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		int changed = 0;
20107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (i=0;i<cnt;i++) {
20117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			unsigned char	*cur = dir+i*0x4c;
20127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	oid = dtoh32a(cur + ptp_canon_dir_objectid);
20137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
20147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
20157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	storageid;
20167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (!ISOBJECT(cur))
20187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
20197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
20207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (j == handles->n) {
20217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				/*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
20227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
20237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
20247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 		storageid = (*oinfos)[j].StorageID;
20257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (storageid == 0xffffffff) continue;
20267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextoid != 0xffffffff) {
20277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
20287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
20297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
20307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
20317347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
20327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
20337347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
20347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
20357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
20367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
20377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextchild != 0xffffffff) {
20387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
20397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
20407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
20417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
20427347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
20437347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
20447347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
20457347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
20467347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
20477347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
20487347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		}
20497347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		/* Check if we:
20507347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed no entry (nothing more to do)
20517347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed all of them at once (usually happens)
20527347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * break if we do.
20537347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 */
20547347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!changed || (changed==nrofobs-1))
20557347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			break;
20567347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
20577347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#undef ISOBJECT
20587347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	return PTP_RC_OK;
20597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij}
2060