ptp-pack.c revision cc2659036a503fce161cb77d9b0af17a52d7437b
1b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/* currently this file is included into ptp.c */
2eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
3a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij#include <iconv.h>
4a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
5b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
6eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod16p (PTPParams *params, uint16_t var)
7eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
8eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
9eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
10eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
11b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
12eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod32p (PTPParams *params, uint32_t var)
13eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
14eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
15eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
16eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
17b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
18eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod16ap (PTPParams *params, unsigned char *a, uint16_t val)
19eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
20eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (params->byteorder==PTP_DL_LE)
21b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htole16a(a,val);
22b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	else
23eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		htobe16a(a,val);
24eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
25eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
26b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
27eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod32ap (PTPParams *params, unsigned char *a, uint32_t val)
28eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
29eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (params->byteorder==PTP_DL_LE)
30b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htole32a(a,val);
31b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	else
32eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		htobe32a(a,val);
33eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
34eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
35abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijstatic inline void
36abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijhtod64ap (PTPParams *params, unsigned char *a, uint64_t val)
37abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij{
38abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	if (params->byteorder==PTP_DL_LE)
39abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htole64a(a,val);
40abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	else
41abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htobe64a(a,val);
42abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij}
43abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
44b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
45eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh16p (PTPParams *params, uint16_t var)
46eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
47eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
48eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
49eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
50b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
51eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh32p (PTPParams *params, uint32_t var)
52eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
53eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
54eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
55eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
56abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijstatic inline uint64_t
57abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijdtoh64p (PTPParams *params, uint64_t var)
58abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij{
59abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	return ((params->byteorder==PTP_DL_LE)?le64toh(var):be64toh(var));
60abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij}
61abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
62b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
63eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh16ap (PTPParams *params, unsigned char *a)
64eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
65eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
66eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
67eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
68b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
69eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh32ap (PTPParams *params, unsigned char *a)
70eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
71eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
72eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
73eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
74b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint64_t
75eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh64ap (PTPParams *params, unsigned char *a)
76eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
77abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a));
78abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	/*
79b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint64_t tmp = 0;
80b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i;
81b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
82b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (params->byteorder==PTP_DL_LE) {
83b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<8;i++)
84b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			tmp |= (((uint64_t)a[i]) << (8*i));
85b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	} else {
86b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<8;i++)
87b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			tmp |= (((uint64_t)a[i]) << (8*(7-i)));
88b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
89b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return tmp;
90abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	*/
91eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
92eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
93b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod8a(a,x)	*(uint8_t*)(a) = x
94b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16a(a,x)	htod16ap(params,a,x)
95b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32a(a,x)	htod32ap(params,a,x)
96abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define htod64a(a,x)	htod64ap(params,a,x)
97b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16(x)	htod16p(params,x)
98b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32(x)	htod32p(params,x)
99abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define htod64(x)	htod64p(params,x)
100b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
101b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh8a(x)	(*(uint8_t*)(x))
102b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16a(a)	dtoh16ap(params,a)
103b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32a(a)	dtoh32ap(params,a)
104b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh64a(a)	dtoh64ap(params,a)
105b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16(x)	dtoh16p(params,x)
106b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32(x)	dtoh32p(params,x)
107abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define dtoh64(x)	dtoh64p(params,x)
108b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
109b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
110b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline char*
111b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
112eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
113a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	uint8_t length;
114a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	uint16_t string[PTP_MAXSTRLEN+1];
115a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* allow for UTF-8: max of 3 bytes per UCS-2 char, plus final null */
116a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	char loclstr[PTP_MAXSTRLEN*3+1];
117a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	size_t nconv, srclen, destlen;
118a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	char *src, *dest;
119a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
120a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	length = dtoh8a(&data[offset]);	/* PTP_MAXSTRLEN == 255, 8 bit len */
121a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*len = length;
122a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (length == 0)		/* nothing to do? */
123a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		return(NULL);
124a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
125a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* copy to string[] to ensure correct alignment for iconv(3) */
126a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(string, &data[offset+1], length * sizeof(string[0]));
127a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	string[length] = 0x0000U;   /* be paranoid!  add a terminator. */
128a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[0] = '\0';
129a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
130a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* convert from camera UCS-2 to our locale */
131a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	src = (char *)string;
132a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	srclen = length * sizeof(string[0]);
133a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	dest = loclstr;
134a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	destlen = sizeof(loclstr)-1;
135a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen,
136a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			&dest, &destlen);
137a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (nconv == (size_t) -1) { /* do it the hard way */
138a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		int i;
139a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		/* try the old way, in case iconv is broken */
140a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		for (i=0;i<length;i++) {
141a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			if (dtoh16a(&data[offset+1+2*i])>127)
142a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = '?';
143a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			else
144a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = dtoh16a(&data[offset+1+2*i]);
145eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
146a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		dest = loclstr+length;
147eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
148a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*dest = '\0';
149a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[sizeof(loclstr)-1] = '\0';   /* be safe? */
150a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	return(strdup(loclstr));
151a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
152a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
153a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline int
154a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijucs2strlen(uint16_t const * const unicstr)
155a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
156a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	int length;
157a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
158a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Unicode strings are terminated with 2 * 0x00 */
159a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	for(length = 0; unicstr[length] != 0x0000U; length ++);
160a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return length;
161eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
162eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
163a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
164b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
165b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
166eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
167a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	int packedlen;
168a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	uint16_t ucs2str[PTP_MAXSTRLEN+1];
169a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	char *ucs2strp = (char *) ucs2str;
170a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	char *stringp = string;
171a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t nconv;
172a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t convlen = strlen(string);
173a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
174a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
175a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
176a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memset(ucs2strp, 0, sizeof(ucs2str));  /* XXX: necessary? */
177a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
178a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		&ucs2strp, &convmax);
1794f40d11374a0ea3c4038f3b18a3601b3bbfe6dcfLinus Walleij	if (nconv == (size_t) -1)
180a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		ucs2str[0] = 0x0000U;
181a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/*
182a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
183a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 *      why do we need ucs2strlen()?
184a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 */
185a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packedlen = ucs2strlen(ucs2str);
186a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (packedlen > PTP_MAXSTRLEN-1) {
187a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		*len=0;
188a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return;
189a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	}
190958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
1917f2343824550452974d78f5dbd94e64844355c33Linus Walleij	/* number of characters including terminating 0 (PTP standard confirmed) */
192a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	htod8a(&data[offset],packedlen+1);
193a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
194a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
195958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
196958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* The returned length is in number of characters */
197048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij	*len = (uint8_t) packedlen+1;
198eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
199eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
200a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline unsigned char *
201735f41692934a716158cf051d76e988febeca7eeLinus Walleijptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
202a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
2038b42ca3d3baeb7c8f3e5eca88c613adb612e4ec0Richard Low	uint8_t packed[PTP_MAXSTRLEN*2+3], len;
204a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t plen;
205a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	unsigned char *retcopy = NULL;
206a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
207a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
208958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* returned length is in characters, then one byte for string length */
209958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	plen = len*2 + 1;
210048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij
211a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	retcopy = malloc(plen);
212735f41692934a716158cf051d76e988febeca7eeLinus Walleij	if (!retcopy) {
213735f41692934a716158cf051d76e988febeca7eeLinus Walleij		*packed_size = 0;
214a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return NULL;
215735f41692934a716158cf051d76e988febeca7eeLinus Walleij	}
216a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	memcpy(retcopy, packed, plen);
217735f41692934a716158cf051d76e988febeca7eeLinus Walleij	*packed_size = plen;
218a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return (retcopy);
219a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
220a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
221b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
222b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
223eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
224eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
225eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
226eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
227eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint32_t));
228eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
229eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
230eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
231eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
232eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
233eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
234eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
235b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
236f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
237f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij{
238f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	uint32_t i=0;
239f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
240f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	*data = malloc ((arraylen+1)*sizeof(uint32_t));
241f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	htod32a(&(*data)[0],arraylen);
242f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	for (i=0;i<arraylen;i++)
243f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
244f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	return (arraylen+1)*sizeof(uint32_t);
245f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij}
246f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
247f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijstatic inline uint32_t
248b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
249eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
250eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
251eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
252eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
253eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint16_t));
254eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
255eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
256eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
257eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
258eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
259eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
260eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
261eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* DeviceInfo pack/unpack */
262eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
263eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_StandardVersion		 0
264eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionID	 2
265eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionVersion	 6
266eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionDesc	 8
267eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_FunctionalMode		 8
268eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_OperationsSupported	10
269eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
270b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
271b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
272eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
273eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t len;
274eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	unsigned int totallen;
275eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
2767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
277eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionID =
278eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh32a(&data[PTP_di_VendorExtensionID]);
279eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionVersion =
280eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
281eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionDesc =
282eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_string(params, data,
283eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_VendorExtensionDesc, &len);
284eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=len*2+1;
285eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->FunctionalMode =
286eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
287eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
288eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
289eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->OperationsSupported);
290eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
291eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
292eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
293eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->EventsSupported);
294eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
295eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DevicePropertiesSupported_len =
296eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_uint16_t_array(params, data,
297eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
298eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->DevicePropertiesSupported);
299eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
300eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
301eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
302eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->CaptureFormats);
303eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
304eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
305eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
306eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->ImageFormats);
307eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
308eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Manufacturer = ptp_unpack_string(params, data,
309eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
310eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
311eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
312eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Model = ptp_unpack_string(params, data,
313eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
314eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
315eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
316eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DeviceVersion = ptp_unpack_string(params, data,
317eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
318eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
319eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
320eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->SerialNumber = ptp_unpack_string(params, data,
321eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
322eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
323eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
324a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
325a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleijstatic void
326a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleijptp_free_DI (PTPDeviceInfo *di) {
327a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->SerialNumber) free (di->SerialNumber);
328a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->DeviceVersion) free (di->DeviceVersion);
329a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->Model) free (di->Model);
330a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->Manufacturer) free (di->Manufacturer);
331a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->ImageFormats) free (di->ImageFormats);
332a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->CaptureFormats) free (di->CaptureFormats);
333a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->VendorExtensionDesc) free (di->VendorExtensionDesc);
334a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->OperationsSupported) free (di->OperationsSupported);
335a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->EventsSupported) free (di->EventsSupported);
336a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->DevicePropertiesSupported) free (di->DevicePropertiesSupported);
337a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij}
338eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
339eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectHandles array pack/unpack */
340eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
341eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oh				 0
342eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
343b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
344b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
345eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
346f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (len) {
347f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
348f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	} else {
349f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = 0;
350f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->Handler = NULL;
351f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
352eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
353eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
354eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StoreIDs array pack/unpack */
355eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
356eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_sids			 0
357eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
358b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
359b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
360eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
361eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
362eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	&sids->Storage);
363eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
364eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
365eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StorageInfo pack/unpack */
366eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
367eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageType		 0
368eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FilesystemType		 2
369eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_AccessCapability		 4
370eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_MaxCapability		 6
371eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInBytes		14
372eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInImages	22
373eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageDescription	26
374eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
375b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
376b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
377eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
378eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t storagedescriptionlen;
379eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
380eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
381eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
382eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
383eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
384eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
385eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
386eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageDescription=ptp_unpack_string(params, data,
387eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription, &storagedescriptionlen);
388eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->VolumeLabel=ptp_unpack_string(params, data,
389eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription+storagedescriptionlen*2+1,
390eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&storagedescriptionlen);
391eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
392eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
393eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectInfo pack/unpack */
394eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
395eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_StorageID		 0
396eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectFormat		 4
397eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ProtectionStatus		 6
398eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectCompressedSize	 8
399eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbFormat		12
400eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbCompressedSize	14
401eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixWidth		18
402eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixHeight		22
403eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixWidth		26
404eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixHeight		30
405eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImageBitDepth		34
406eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ParentObject		38
407eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationType		42
408eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationDesc		44
409eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_SequenceNumber		48
410eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_filenamelen		52
411eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_Filename			53
412eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
413a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* the max length assuming zero length dates. We have need 3 */
414a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* bytes for these. */
415a679b1c4d273f210abb6befc5d9954a25427c329Richard Low#define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
416a679b1c4d273f210abb6befc5d9954a25427c329Richard Low
417b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
418b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
419eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
420b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* oidata;
421eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
422eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen=0;
423a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	/* let's allocate some memory first; correct assuming zero length dates */
424a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	oidata=malloc(PTP_oi_MaxLen);
425eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* the caller should free it after use! */
426eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0
427eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date="20020101T010101"; /* XXX Fake date */
428eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
429a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	memset (oidata, 0, PTP_oi_MaxLen);
430eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
431eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
432eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
433eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
434eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
435eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
436eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
437eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
438eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
439eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
440eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
441eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
442eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
443eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
444eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
445eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
446eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
447eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
448eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	filenamelen=(uint8_t)strlen(oi->Filename);
449eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
450eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
451eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
452eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
453eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
454eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/*
455eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 *XXX Fake date.
456eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * for example Kodak sets Capture date on the basis of EXIF data.
457eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * Spec says that this field is from perspective of Initiator.
458eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
459eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
460eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capturedatelen=strlen(capture_date);
461eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
462eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
463eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
464eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
465eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
466eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
467eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
468eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
469eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
470eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		  capture_date[i];
471eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
472eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
473eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* XXX this function should return dataset length */
474eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
475eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*oidataptr=oidata;
476a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3);
477eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
478eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
479b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
480b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
481eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
482eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
483eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen;
484eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date;
485eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char tmp[16];
486eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	struct tm tm;
487eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
488eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	memset(&tm,0,sizeof(tm));
489eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
490eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
491eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
492eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
493eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
494eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
495eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
496eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
497eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
498eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
499eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
500eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
501eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
502eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
503eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
504eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
505eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
506eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
507eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
508eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
509eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* subset of ISO 8601, without '.s' tenths of second and
510eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * time zone
511eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
512eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (capturedatelen>15)
513eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	{
514eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date, 4);
515eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[4] = 0;
516eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_year=atoi (tmp) - 1900;
517eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 4, 2);
518eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
519eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mon = atoi (tmp) - 1;
520eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 6, 2);
521eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
522eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mday = atoi (tmp);
523eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 9, 2);
524eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
525eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_hour = atoi (tmp);
526eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 11, 2);
527eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
528eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_min = atoi (tmp);
529eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 13, 2);
530eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
531eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_sec = atoi (tmp);
532eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		oi->CaptureDate=mktime (&tm);
533eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
534eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
535eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
536eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* now it's modification date ;) */
537eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
538eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2
539eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		+capturedatelen*2+2,&capturedatelen);
540eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (capturedatelen>15)
541eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	{
542eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date, 4);
543eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[4] = 0;
544eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_year=atoi (tmp) - 1900;
545eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 4, 2);
546eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
547eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mon = atoi (tmp) - 1;
548eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 6, 2);
549eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
550eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mday = atoi (tmp);
551eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 9, 2);
552eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
553eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_hour = atoi (tmp);
554eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 11, 2);
555eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
556eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_min = atoi (tmp);
557eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 13, 2);
558eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
559eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_sec = atoi (tmp);
560eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		oi->ModificationDate=mktime (&tm);
561eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
562eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
563eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
564eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
565eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Custom Type Value Assignement (without Length) macro frequently used below */
566b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define CTVAL(target,func) {			\
567b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(target))	\
568b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;			\
569b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	target = func(&data[*offset]);		\
570b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(target);		\
571eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
572eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
573b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define RARR(val,member,func)	{			\
574b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int n,j;					\
575b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(uint32_t))		\
576b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;				\
577b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	n = dtoh32a (&data[*offset]);			\
578b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(uint32_t);			\
579b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij							\
580b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.count = n;				\
581b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
582b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!val->a.v) return 0;			\
583b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (j=0;j<n;j++)				\
584b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(val->a.v[j].member, func);	\
585b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
586eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
587b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
588b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPV (
589b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPParams *params, unsigned char* data, int *offset, int total,
590b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPPropertyValue* value, uint16_t datatype
591b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij) {
592eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
593b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
594b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i8,dtoh8a);
595b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
596b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
597b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u8,dtoh8a);
598b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
599b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
600b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i16,dtoh16a);
601b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
602b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
603b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u16,dtoh16a);
604b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
605b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
606b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i32,dtoh32a);
607b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
608b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
609b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u32,dtoh32a);
610b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
611abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
612abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->i64,dtoh64a);
613abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
614abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
615abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->u64,dtoh64a);
616abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
617abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
618037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_UINT128:
619037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
620037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of uint128n");*/
621037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
622037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_INT128:
623037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
624037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of int128n");*/
625037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
626037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
627037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
628037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
629b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
630b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i8,dtoh8a);
631b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
632b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
633b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u8,dtoh8a);
634b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
635b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
636b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u16,dtoh16a);
637b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
638b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
639b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i16,dtoh16a);
640b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
641b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
642b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u32,dtoh32a);
643b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
644b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
645b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i32,dtoh32a);
646b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
647abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
648abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,u64,dtoh64a);
649abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
650abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
651abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,i64,dtoh64a);
652abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
653b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
654b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int arrays are unimplemented also */
655b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
656b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		uint8_t len;
657b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		/* XXX: max size */
658b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		value->str = ptp_unpack_string(params,data,*offset,&len);
659b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		*offset += len*2+1;
660b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!value->str)
661eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			return 0;
662b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
663eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
664037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	default:
665037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		return 0;
666b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
667b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
668eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
669eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
670eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Device Property pack/unpack */
671eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
672eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DevicePropertyCode	0
673eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DataType		2
674eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_GetSet			4
675eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_FactoryDefaultValue	5
676eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
677b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
678b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
679eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
680b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
681eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
682b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (dpd, 0, sizeof(*dpd));
683eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
684eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
685eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
686b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
687b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_dpd_FactoryDefaultValue;
688b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
689b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
690b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
691b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
692b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
693b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* if offset==0 then Data Type format is not supported by this
694b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   code or the Data Type is a string (with two empty strings as
695b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
696b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   not present. */
697b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
698eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
699b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (offset==PTP_dpd_FactoryDefaultValue)
700b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 1;
701b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
702b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	dpd->FormFlag=dtoh8a(&data[offset]);
703b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
704eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
705eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (dpd->FormFlag) {
706b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Range:
707b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
708b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
709b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
710b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
711b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
712b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
713eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
714b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Enumeration: {
715b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
716eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
717b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
718b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
719b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
720b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
721b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
722b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
723b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
724b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
725b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
726b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
727b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
728b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
729b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
730b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
731b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
732b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
733b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
734b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
735b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
736b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
737eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			}
738b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
739eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
740eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
741b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
742b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
743b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
744b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_devicepropdesc(dpd);
745b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
746eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
747eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
748b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/* (MTP) Object Property pack/unpack */
749b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_ObjectPropertyCode	0
750b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_DataType		2
751b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_GetSet			4
752b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_FactoryDefaultValue	5
753eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
754b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
755b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
756eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
757b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
758b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
759b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (opd, 0, sizeof(*opd));
760b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
761b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
762b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
763b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
764b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_opd_FactoryDefaultValue;
765b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
766b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
767b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
768b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GroupCode=dtoh32a(&data[offset]);
769b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint32_t);
770b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
771b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->FormFlag=dtoh8a(&data[offset]);
772b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
773b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
774b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	switch (opd->FormFlag) {
775b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Range:
776b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
777b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
778b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
779b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
780b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
781b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
782b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
783b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Enumeration: {
784b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
785b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define N	opd->FORM.Enum.NumberOfValues
786b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
787b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
788b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
789b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!opd->FORM.Enum.SupportedValue)
790b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
791b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
792b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
793b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
794b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
795b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
796b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
797b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
798b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
799b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
800b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
801b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
802b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
803b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
804b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				opd->FORM.Enum.NumberOfValues = i;
805b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
806b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			}
807b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
808b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
809b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
810eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
811b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
812b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
813b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_objectpropdesc(opd);
814b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
815eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
816eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
817eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
818b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
819b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
820eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
821b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* dpv=NULL;
822eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t size=0;
823b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int	i;
824eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
825eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
826b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
827b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int8_t);
828b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
829b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->i8);
830b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
831b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
832b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint8_t);
833b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
834b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->u8);
835b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
836b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
837b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int16_t);
838b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
839b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->i16);
840b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
841b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
842b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint16_t);
843b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
844b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->u16);
845b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
846b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
847b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int32_t);
848b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
849b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->i32);
850b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
851b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
852b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t);
853b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
854b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->u32);
855b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
856abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
857abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(int64_t);
858abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
859abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->i64);
860abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
861abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
862abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint64_t);
863abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
864abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->u64);
865abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
866b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
867b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
868b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
869b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
870b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
871cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
872b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
873b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
874b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
875b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
876b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
877b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
878cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
879b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
880b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
881b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
882b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
883b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
884b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
885cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
886b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
887b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
888b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
889b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
890b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
891b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
892cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
893b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
894b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
895b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
896b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
897b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
898b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
899cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
900b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
901b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
902b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
903b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
904b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
905b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
906cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
907b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
908abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
909abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
910abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
911abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
912abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
913cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
914abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
915abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
916abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
917abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
918abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
919abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
920cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
921abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
922b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
923b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
924735f41692934a716158cf051d76e988febeca7eeLinus Walleij		dpv=ptp_get_packed_stringcopy(params, value->str, &size);
925eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
926b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
927eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
928eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*dpvptr=dpv;
929eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return size;
93099310d4445697da39f22dff35457c75e35e97171Linus Walleij}
93199310d4445697da39f22dff35457c75e35e97171Linus Walleij
93299310d4445697da39f22dff35457c75e35e97171Linus Walleij#define MAX_MTP_PROPS 127
93399310d4445697da39f22dff35457c75e35e97171Linus Walleijstatic inline uint32_t
9346c0a6ce803cf79802b1c48339adf0964db30ec83Richard Lowptp_pack_OPL (PTPParams *params, MTPPropList *proplist, unsigned char** opldataptr)
93599310d4445697da39f22dff35457c75e35e97171Linus Walleij{
93699310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char* opldata;
93799310d4445697da39f22dff35457c75e35e97171Linus Walleij	MTPPropList *propitr;
93899310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char *packedprops[MAX_MTP_PROPS];
93999310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t packedpropslens[MAX_MTP_PROPS];
94039b9374f23451201dece736db13f0f648584dc32Linus Walleij	uint32_t packedobjecthandles[MAX_MTP_PROPS];
94199310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropsids[MAX_MTP_PROPS];
94299310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropstypes[MAX_MTP_PROPS];
94399310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t totalsize = 0;
94499310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t bufp = 0;
94599310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t noitems = 0;
94699310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t i;
94799310d4445697da39f22dff35457c75e35e97171Linus Walleij
94899310d4445697da39f22dff35457c75e35e97171Linus Walleij	totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
94999310d4445697da39f22dff35457c75e35e97171Linus Walleij	propitr = proplist;
95099310d4445697da39f22dff35457c75e35e97171Linus Walleij	while (propitr != NULL && noitems < MAX_MTP_PROPS) {
9516c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		/* Object Handle */
95239b9374f23451201dece736db13f0f648584dc32Linus Walleij		packedobjecthandles[noitems]=propitr->ObjectHandle;
95399310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint32_t); /* Object ID */
95499310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Metadata type */
95599310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropsids[noitems]=propitr->property;
95699310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
95799310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Data type */
95899310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropstypes[noitems]= propitr->datatype;
95999310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
96099310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Add each property to be sent. */
96199310d4445697da39f22dff35457c75e35e97171Linus Walleij	        packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
96299310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += packedpropslens[noitems];
96399310d4445697da39f22dff35457c75e35e97171Linus Walleij		noitems ++;
96499310d4445697da39f22dff35457c75e35e97171Linus Walleij		propitr = propitr->next;
96599310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
96699310d4445697da39f22dff35457c75e35e97171Linus Walleij
96799310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Allocate memory for the packed property list */
96899310d4445697da39f22dff35457c75e35e97171Linus Walleij	opldata = malloc(totalsize);
96999310d4445697da39f22dff35457c75e35e97171Linus Walleij
97099310d4445697da39f22dff35457c75e35e97171Linus Walleij	htod32a(&opldata[bufp],noitems);
97199310d4445697da39f22dff35457c75e35e97171Linus Walleij	bufp += 4;
97299310d4445697da39f22dff35457c75e35e97171Linus Walleij
97399310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Copy into a nice packed list */
97499310d4445697da39f22dff35457c75e35e97171Linus Walleij	for (i = 0; i < noitems; i++) {
97599310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Object ID */
9766c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		htod32a(&opldata[bufp],packedobjecthandles[i]);
97799310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint32_t);
97899310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropsids[i]);
97999310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
98099310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropstypes[i]);
98199310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
98299310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* The copy the actual property */
98399310d4445697da39f22dff35457c75e35e97171Linus Walleij		memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
98499310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += packedpropslens[i];
98599310d4445697da39f22dff35457c75e35e97171Linus Walleij		free(packedprops[i]);
98699310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
98799310d4445697da39f22dff35457c75e35e97171Linus Walleij	*opldataptr = opldata;
98899310d4445697da39f22dff35457c75e35e97171Linus Walleij	return totalsize;
989eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
990eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
9918d82d2f4b0794e41ec26289045867eebb3496b8cRichard Lowstatic inline int
9928d82d2f4b0794e41ec26289045867eebb3496b8cRichard Lowptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPPropList **proplist, unsigned int len)
9938d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low{
994277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	uint32_t prop_count = dtoh32a(data);
995277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	MTPPropList *prop = NULL;
996277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	int offset = 0, i;
997277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
998277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	if (prop_count == 0) {
999277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		*proplist = NULL;
1000277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		return 0;
1001277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
1002277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	data += sizeof(uint32_t);
1003277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	*proplist = malloc(sizeof(MTPPropList));
1004277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	prop = *proplist;
1005277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	for (i = 0; i < prop_count; i++) {
10066c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		prop->ObjectHandle = dtoh32a(data);
1007277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint32_t);
1008277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint32_t);
1009277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
10106c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		prop->property = dtoh16a(data);
1011277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1012277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1013277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
10146c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		prop->datatype = dtoh16a(data);
1015277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1016277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1017277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1018277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		offset = 0;
1019277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		ptp_unpack_DPV(params, data, &offset, len, &prop->propval, prop->datatype);
1020277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += offset;
1021277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= offset;
1022277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1023277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		if (i != prop_count - 1) {
1024277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij			prop->next = malloc(sizeof(MTPPropList));
1025277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij			prop = prop->next;
1026277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		} else
1027277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij			prop->next = NULL;
1028277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
1029277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	return prop_count;
10308d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low}
10318d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low
1032eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1033eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP USB Event container unpack
1034eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1035eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1036eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1037eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Length		0
1038eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Type		4
1039eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Code		6
1040eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_TransId		8
1041eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param1		12
1042eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param2		16
1043eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param3		20
1044eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1045b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1046b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_EC (PTPParams *params, unsigned char* data, PTPUSBEventContainer *ec, unsigned int len)
1047eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1048eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1049eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
1050eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->length=dtoh32a(&data[PTP_ec_Length]);
1051eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->type=dtoh16a(&data[PTP_ec_Type]);
1052eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->code=dtoh16a(&data[PTP_ec_Code]);
1053eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->trans_id=dtoh32a(&data[PTP_ec_TransId]);
1054b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1055eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (ec->length>=(PTP_ec_Param1+4))
1056eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param1=dtoh32a(&data[PTP_ec_Param1]);
1057eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	else
1058eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param1=0;
1059eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (ec->length>=(PTP_ec_Param2+4))
1060eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param2=dtoh32a(&data[PTP_ec_Param2]);
1061eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	else
1062eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param2=0;
1063eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (ec->length>=(PTP_ec_Param3+4))
1064eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param3=dtoh32a(&data[PTP_ec_Param3]);
1065eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	else
1066eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param3=0;
1067eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1068eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1069eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1070eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP Canon Folder Entry unpack
1071eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1072eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1073eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectHandle		0
1074eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectFormatCode	4
1075eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Flags			6
1076eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectSize		7
1077eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Time			11
1078eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Filename		15
1079eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1080b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1081b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1082eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1083eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
1084eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1085eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
1086eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
1087eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
1088eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
1089b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
1090eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
1091eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1092b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
1093b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
1094b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1095b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/*
1096f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij    PTP EOS Changes Entry unpack
1097f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij*/
1098f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Size		0
1099f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Type		4
1100f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1101f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Subtype	8	/* only for properties */
1102f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Val_Data	0xc	/* only for properties */
1103f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Type	0xc	/* only for property descs */
1104f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Count	0x10	/* only for property descs */
1105f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Data	0x14	/* only for property descs */
1106f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1107f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_OI_ObjectID	8	/* only for objectinfos */
1108f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_OI_OFC		0x0c	/* only for objectinfos */
1109f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_OI_Size		0x14	/* only for objectinfos */
1110f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_OI_Name		0x1c	/* only for objectinfos */
1111f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1112f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijstatic inline int
1113f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **ce)
1114f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij{
1115f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	int	i = 0, entries = 0;
1116f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	unsigned char	*curdata = data;
1117f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1118f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (data==NULL)
1119f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		return 0;
1120f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1121f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1122f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1123f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1124f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
1125f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		if ((size == 8) && (type == 0))
1126f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1127f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		entries++;
1128f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
1129f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	*ce = malloc (sizeof(PTPCanon_changes_entry)*entries);
1130f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (!*ce) return 0;
1131f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1132f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	curdata = data;
1133f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1134f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1135f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1136f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1137f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		switch (type) {
1138f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		case  0xc186: {	/* objectinfo from capture */
1139f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
1140f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
1141f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OI_OFC]);
1142f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
1143f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OI_Name]));
1144f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1145f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1146f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		case  0xc18a: {	/* property desc */
1147f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1148f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
1149f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
1150f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			unsigned char	*data = &curdata[PTP_ece_Prop_Desc_Data];
1151f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			int		j;
1152f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			PTPDevicePropDesc	*dpd;
1153f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
11545d533bb85ccfc1bafa8df94570e87f3daf3d5e85Linus Walleij			/*fprintf (stderr, "Adding EOS property %04x desc record, datasize is %d\n", proptype, size-PTP_ece_Prop_Desc_Data);*/
1155f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			for (j=0;j<params->nrofcanon_props;j++)
1156f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (params->canon_props[j].proptype == proptype)
1157f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1158f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (j==params->nrofcanon_props) {
11595d533bb85ccfc1bafa8df94570e87f3daf3d5e85Linus Walleij				/*fprintf (stderr, "should have received default value for %x first!\n", proptype);*/
1160f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1161f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1162f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			dpd = &params->canon_props[j].dpd;
1163f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (propxtype != 3) {
11645d533bb85ccfc1bafa8df94570e87f3daf3d5e85Linus Walleij				/*fprintf (stderr, "propxtype is %x for %x, unhandled.\n", propxtype, proptype);*/
1165f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1166f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1167f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (propxcnt) {
1168f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				dpd->FormFlag = PTP_DPFF_Enumeration;
1169f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				dpd->FORM.Enum.NumberOfValues = propxcnt;
1170f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
1171f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<propxcnt;j++) {
1172f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					switch (dpd->DataType) {
1173f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					case PTP_DTC_UINT16:
1174f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						dpd->FORM.Enum.SupportedValue[j].u16	= dtoh16a(data);
11755d533bb85ccfc1bafa8df94570e87f3daf3d5e85Linus Walleij						/*fprintf (stderr,"suppvalue[%d] of %x is %x\n", j, proptype, dtoh16a(data));*/
1176f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						break;
1177f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					case PTP_DTC_UINT8:
1178f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						dpd->FORM.Enum.SupportedValue[j].u8	= dtoh8a(data);
11795d533bb85ccfc1bafa8df94570e87f3daf3d5e85Linus Walleij						/*fprintf (stderr,"suppvalue[%d] of %x is %x\n", j, proptype, dtoh8a(data));*/
1180f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						break;
1181f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					default:
11825d533bb85ccfc1bafa8df94570e87f3daf3d5e85Linus Walleij						/*fprintf(stderr,"data type 0x%04x of %x unhandled, fill in (val=%x).\n", dpd->DataType, proptype, dtoh32a(data));*/
1183f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						break;
1184f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					}
1185f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					data += 4; /* might only be for propxtype 3 */
1186f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1187f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1188f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1189f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1190f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		case  0xc189:	/* property value */
1191f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (size >= 0xc) {	/* property info */
1192f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				int j;
1193f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1194f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				unsigned char	*data = &curdata[PTP_ece_Prop_Val_Data];
1195f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				PTPDevicePropDesc	*dpd;
1196f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1197f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<params->nrofcanon_props;j++)
1198f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (params->canon_props[j].proptype == proptype)
1199f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						break;
1200f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (j<params->nrofcanon_props) {
1201f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (	(params->canon_props[j].size != size) ||
1202f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						(memcmp(params->canon_props[j].data,data,size-PTP_ece_Prop_Val_Data))) {
1203f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
1204f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						memcpy (params->canon_props[j].data,data,size-PTP_ece_Prop_Val_Data);
1205f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					}
1206f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				} else {
1207f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (j)
1208f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
1209f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					else
1210f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = malloc(sizeof(params->canon_props[0]));
1211f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].type = type;
1212f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].proptype = proptype;
1213f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].size = size;
1214f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
1215f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					memcpy(params->canon_props[j].data, data, size-PTP_ece_Prop_Val_Data);
1216f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
1217f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.GetSet = 1;
1218f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
1219f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->nrofcanon_props = j+1;
1220f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1221f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				dpd = &params->canon_props[j].dpd;
1222f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (proptype) {
1223ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DPC_CANON_EOS_CameraTime:
1224ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
1225ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
1226f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Aperture:
1227f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ShutterSpeed:
1228f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ISOSpeed:
1229f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
1230f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1231f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_PictureStyle:
1232f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalance:
1233f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_MeteringMode:
1234f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ExpCompensation:
1235f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT8;
1236f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1237f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Owner:
1238f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_STR;
1239f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1240f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
12415d533bb85ccfc1bafa8df94570e87f3daf3d5e85Linus Walleij					/*fprintf (stderr, "Unknown EOS property %04x, datasize is %d\n", proptype, size-PTP_ece_Prop_Val_Data);*/
1242f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1243f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1244f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (dpd->DataType) {
1245ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DTC_UINT32:
1246ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					dpd->FactoryDefaultValue.u32	= dtoh32a(data);
1247ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					dpd->CurrentValue.u32		= dtoh32a(data);
1248ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					/*fprintf (stderr,"currentvalue of %x is %x\n", proptype, dpd->CurrentValue.u16);*/
1249ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
1250f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT16:
1251f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->FactoryDefaultValue.u16	= dtoh16a(data);
1252f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->CurrentValue.u16		= dtoh16a(data);
1253f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					/*fprintf (stderr,"currentvalue of %x is %x\n", proptype, dpd->CurrentValue.u16);*/
1254f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1255f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT8:
1256f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->FactoryDefaultValue.u8	= dtoh8a(data);
1257f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->CurrentValue.u8		= dtoh8a(data);
1258f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					/*fprintf (stderr,"currentvalue of %x is %x\n", proptype, dpd->CurrentValue.u8);*/
1259f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1260f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_STR: {
1261f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					uint8_t len = 0;
1262f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->FactoryDefaultValue.str	= ptp_unpack_string(params, data, 0, &len);
1263f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->CurrentValue.str		= ptp_unpack_string(params, data, 0, &len);
1264f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1265f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1266f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
1267f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					/* debug is printed in switch above this one */
1268f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1269f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1270f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1271f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1272f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		default:
12735d533bb85ccfc1bafa8df94570e87f3daf3d5e85Linus Walleij			/* fprintf (stderr, "unknown EOS property type %04x\n", type); */
1274f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1275f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1276f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1277f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
1278f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		i++;
1279f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
1280f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1281f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	return entries;
1282f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij}
1283f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1284f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij/*
1285b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij    PTP USB Event container unpack for Nikon events.
1286b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij*/
1287b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Length		0
1288b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Code		2
1289b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Param1		4
1290b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Size		6
1291b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1292b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPUSBEventContainer **ec, int *cnt)
1293b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij{
1294b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i;
1295b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1296b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = NULL;
1297b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (data == NULL)
1298b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1299b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (len < PTP_nikon_ec_Code)
1300b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1301b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
1302b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
1303b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1304b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = malloc(sizeof(PTPUSBEventContainer)*(*cnt));
1305b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1306b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<*cnt;i++) {
1307b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset(&(*ec)[i],0,sizeof(PTPUSBEventContainer));
1308b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		(*ec)[i].code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
1309b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		(*ec)[i].param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
1310b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1311eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1312eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1313eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1314b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
1315b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
1316b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i, len = 0;
1317b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint8_t	retlen;
1318b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char *curdata;
1319b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1320b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	len =	2*(strlen(text->title)+1)+1+
1321b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[0])+1)+1+
1322b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[1])+1)+1+
1323b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[2])+1)+1+
1324b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[3])+1)+1+
1325b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[4])+1)+1+
1326b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		4*2+2*4+2+4+2+5*4*2;
1327b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*data = malloc(len);
1328b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!*data) return 0;
1329b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1330b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	curdata = *data;
1331b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,100);curdata+=2;
1332b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1);curdata+=2;
1333b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0);curdata+=2;
1334b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1000);curdata+=2;
1335b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1336b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1337b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1338b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1339b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,6);curdata+=2;
1340b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1341b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1342b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1343b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0x10);curdata+=2;
1344b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1345b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<5;i++) {
1346b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1347b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x10);curdata+=2;
1348b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x01);curdata+=2;
1349b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x02);curdata+=2;
1350b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x06);curdata+=2;
1351b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1352b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return len;
1353b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
13547347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
13557347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_version	0x00
13567347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_ofc	0x02
13577347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk1	0x04
13587347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_objectid	0x08
13597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_parentid	0x0c
13607347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_previd	0x10	/* in same dir */
13617347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextid	0x14	/* in same dir */
13627347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextchild	0x18	/* down one dir */
13637347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_storageid	0x1c	/* only in storage entry */
13647347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_name	0x20
13657347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_flags	0x2c
13667347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_size	0x30
13677347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unixtime	0x34
13687347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_year	0x38
13697347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_month	0x39
13707347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_mday	0x3a
13717347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_hour	0x3b
13727347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_minute	0x3c
13737347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_second	0x3d
13747347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk2	0x3e
13757347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_thumbsize	0x40
13767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_width	0x44
13777347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_height	0x48
13787347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
13797347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijstatic inline uint16_t
13807347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijptp_unpack_canon_directory (
13817347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPParams		*params,
13827347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned char		*dir,
13837347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		cnt,
13847347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectHandles	*handles,
13857347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectInfo		**oinfos,	/* size(handles->n) */
13867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		**flags		/* size(handles->n) */
13877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij) {
13887347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned int	i, j, nrofobs = 0, curob = 0;
13897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
13907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
13917347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++)
13927347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(dir+i*0x4c)) nrofobs++;
13937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->n = nrofobs;
13947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs);
13957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!handles->Handler) return PTP_RC_GeneralError;
13967347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*oinfos = calloc(sizeof((*oinfos)[0]),nrofobs);
13977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*oinfos) return PTP_RC_GeneralError;
13987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*flags  = calloc(sizeof((*flags)[0]),nrofobs);
13997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*flags) return PTP_RC_GeneralError;
14007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
14017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Migrate data into objects ids, handles into
14027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the object handler array.
14037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 */
14047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	curob = 0;
14057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
14067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
14077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		PTPObjectInfo	*oi = (*oinfos)+curob;
14087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
14097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!ISOBJECT(cur))
14107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
14117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
14127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
14137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->StorageID		= 0xffffffff;
14147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectFormat	= dtoh16a(cur + ptp_canon_dir_ofc);
14157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ParentObject	= dtoh32a(cur + ptp_canon_dir_parentid);
14167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->Filename		= strdup((char*)(cur + ptp_canon_dir_name));
14177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
14187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ThumbCompressedSize	= dtoh32a(cur + ptp_canon_dir_thumbsize);
14197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixWidth	= dtoh32a(cur + ptp_canon_dir_width);
14207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixHeight	= dtoh32a(cur + ptp_canon_dir_height);
14217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->CaptureDate		= oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
14227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*flags)[curob]		= dtoh32a(cur + ptp_canon_dir_flags);
14237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		curob++;
14247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
14257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over Storage ID entries and distribute the IDs to
14267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the parent objects. */
14277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
14287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
14297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
14307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
14317347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(cur))
14327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
14337347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
14347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (j == handles->n) continue;
14357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
14367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
14377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over all objects and distribute the storage ids */
14387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	while (1) {
14397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		int changed = 0;
14407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (i=0;i<cnt;i++) {
14417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			unsigned char	*cur = dir+i*0x4c;
14427347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	oid = dtoh32a(cur + ptp_canon_dir_objectid);
14437347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
14447347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
14457347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	storageid;
14467347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
14477347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (!ISOBJECT(cur))
14487347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
14497347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
14507347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (j == handles->n) {
14517347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				/*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
14527347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
14537347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
14547347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 		storageid = (*oinfos)[j].StorageID;
14557347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (storageid == 0xffffffff) continue;
14567347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextoid != 0xffffffff) {
14577347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
14587347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
14597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
14607347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
14617347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
14627347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
14637347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
14647347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
14657347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
14667347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
14677347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextchild != 0xffffffff) {
14687347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
14697347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
14707347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
14717347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
14727347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
14737347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
14747347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
14757347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
14767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
14777347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
14787347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		}
14797347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		/* Check if we:
14807347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed no entry (nothing more to do)
14817347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed all of them at once (usually happens)
14827347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * break if we do.
14837347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 */
14847347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!changed || (changed==nrofobs-1))
14857347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			break;
14867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
14877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#undef ISOBJECT
14887347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	return PTP_RC_OK;
14897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij}
14907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
1491