ptp-pack.c revision a679b1c4d273f210abb6befc5d9954a25427c329
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
35b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
36eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh16p (PTPParams *params, uint16_t var)
37eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
38eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
39eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
40eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
41b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
42eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh32p (PTPParams *params, uint32_t var)
43eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
44eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
45eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
46eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
47b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
48eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh16ap (PTPParams *params, unsigned char *a)
49eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
50eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
51eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
52eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
53b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
54eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh32ap (PTPParams *params, unsigned char *a)
55eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
56eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
57eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
58eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
59b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint64_t
60eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh64ap (PTPParams *params, unsigned char *a)
61eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
62b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint64_t tmp = 0;
63b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i;
64b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
65b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (params->byteorder==PTP_DL_LE) {
66b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<8;i++)
67b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			tmp |= (((uint64_t)a[i]) << (8*i));
68b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	} else {
69b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<8;i++)
70b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			tmp |= (((uint64_t)a[i]) << (8*(7-i)));
71b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
72b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return tmp;
73eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
74eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
75b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod8a(a,x)	*(uint8_t*)(a) = x
76b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16a(a,x)	htod16ap(params,a,x)
77b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32a(a,x)	htod32ap(params,a,x)
78b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16(x)	htod16p(params,x)
79b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32(x)	htod32p(params,x)
80b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
81b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh8a(x)	(*(uint8_t*)(x))
82b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16a(a)	dtoh16ap(params,a)
83b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32a(a)	dtoh32ap(params,a)
84b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh64a(a)	dtoh64ap(params,a)
85b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16(x)	dtoh16p(params,x)
86b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32(x)	dtoh32p(params,x)
87b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
88b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
89b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline char*
90b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
91eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
92eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
93a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	uint8_t loclen;
94a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
95a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
96a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	loclen = dtoh8a(&data[offset]);
97a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* This len is used to advance the buffer pointer */
98a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	*len = loclen;
99a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (loclen) {
100a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		uint16_t string[PTP_MAXSTRLEN+1];
101a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		char *stringp = (char *) string;
102a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		char loclstr[PTP_MAXSTRLEN*3+1]; /* UTF-8 encoding is max 3 bytes per UCS2 char. */
103a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		char *locp = loclstr;
104a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		size_t nconv;
105a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		size_t convlen = loclen * 2; /* UCS-2 is 16 bit wide */
106a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		size_t convmax = PTP_MAXSTRLEN*3;
107a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
108a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		for (i=0;i<loclen;i++) {
109a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij			string[i]=dtoh16a(&data[offset+i*2+1]);
110eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
111a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		/* be paranoid! Add a terminator. :( */
112a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		string[loclen]=0x0000U;
113a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		loclstr[0]='\0';
114a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		/* loclstr=ucs2_to_utf8(string); */
115a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		/* Do the conversion.  */
116a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		nconv = iconv (params->cd_ucs2_to_locale, &stringp, &convlen, &locp, &convmax);
117a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		/* FIXME: handle size errors */
118a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		loclstr[PTP_MAXSTRLEN*3] = '\0';
119a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		if (nconv == (size_t) -1)
120a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij			return NULL;
121a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return strdup(loclstr);
122eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
123a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return NULL;
124a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
125a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
126a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
127a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline int
128a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijucs2strlen(uint16_t const * const unicstr)
129a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
130a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	int length;
131a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
132a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Unicode strings are terminated with 2 * 0x00 */
133a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	for(length = 0; unicstr[length] != 0x0000U; length ++);
134a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return length;
135eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
136eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
137a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
138b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
139b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
140eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
141eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
142a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	int packedlen;
143a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	uint16_t ucs2str[PTP_MAXSTRLEN+1];
144a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	char *ucs2strp = (char *) ucs2str;
145a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	char *stringp = string;
146a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t nconv;
147a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t convlen = strlen(string);
148a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
149a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
150a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
151a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	ucs2str[0] = 0x0000U;
152a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	memset(ucs2strp, 0, PTP_MAXSTRLEN*2+2);
153a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	nconv = iconv (params->cd_locale_to_ucs2, &stringp, &convlen, &ucs2strp, &convmax);
1544f40d11374a0ea3c4038f3b18a3601b3bbfe6dcfLinus Walleij	if (nconv == (size_t) -1)
155a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		ucs2str[0] = 0x0000U;
156a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packedlen = ucs2strlen(ucs2str);
157a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (packedlen > PTP_MAXSTRLEN-1) {
158a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		*len=0;
159a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return;
160a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	}
161958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
1627f2343824550452974d78f5dbd94e64844355c33Linus Walleij	/* number of characters including terminating 0 (PTP standard confirmed) */
163a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	htod8a(&data[offset],packedlen+1);
164a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	for (i=0;i<packedlen && i< PTP_MAXSTRLEN; i++) {
165a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		htod16a(&data[offset+i*2+1],ucs2str[i]);
166eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
1676e4499552671f75f23171957823ce4e0b067cac7Linus Walleij	htod16a(&data[offset+i*2+1],0x0000);
168958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
169958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* The returned length is in number of characters */
170048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij	*len = (uint8_t) packedlen+1;
171eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
172eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
173a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline unsigned char *
174735f41692934a716158cf051d76e988febeca7eeLinus Walleijptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
175a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
1768b42ca3d3baeb7c8f3e5eca88c613adb612e4ec0Richard Low	uint8_t packed[PTP_MAXSTRLEN*2+3], len;
177a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t plen;
178a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	unsigned char *retcopy = NULL;
179a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
180a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
181958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* returned length is in characters, then one byte for string length */
182958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	plen = len*2 + 1;
183048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij
184a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	retcopy = malloc(plen);
185735f41692934a716158cf051d76e988febeca7eeLinus Walleij	if (!retcopy) {
186735f41692934a716158cf051d76e988febeca7eeLinus Walleij		*packed_size = 0;
187a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return NULL;
188735f41692934a716158cf051d76e988febeca7eeLinus Walleij	}
189a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	memcpy(retcopy, packed, plen);
190735f41692934a716158cf051d76e988febeca7eeLinus Walleij	*packed_size = plen;
191a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return (retcopy);
192a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
193a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
194b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
195b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
196eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
197eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
198eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
199eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
200eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint32_t));
201eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
202eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
203eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
204eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
205eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
206eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
207eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
208b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
209f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
210f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij{
211f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	uint32_t i=0;
212f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
213f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	*data = malloc ((arraylen+1)*sizeof(uint32_t));
214f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	htod32a(&(*data)[0],arraylen);
215f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	for (i=0;i<arraylen;i++)
216f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
217f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	return (arraylen+1)*sizeof(uint32_t);
218f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij}
219f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
220f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijstatic inline uint32_t
221b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
222eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
223eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
224eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
225eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
226eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint16_t));
227eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
228eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
229eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
230eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
231eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
232eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
233eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
234eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* DeviceInfo pack/unpack */
235eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
236eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_StandardVersion		 0
237eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionID	 2
238eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionVersion	 6
239eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionDesc	 8
240eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_FunctionalMode		 8
241eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_OperationsSupported	10
242eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
243b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
244b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
245eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
246eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t len;
247eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	unsigned int totallen;
248eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
2497347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
250eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionID =
251eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh32a(&data[PTP_di_VendorExtensionID]);
252eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionVersion =
253eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
254eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionDesc =
255eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_string(params, data,
256eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_VendorExtensionDesc, &len);
257eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=len*2+1;
258eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->FunctionalMode =
259eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
260eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
261eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
262eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->OperationsSupported);
263eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
264eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
265eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
266eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->EventsSupported);
267eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
268eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DevicePropertiesSupported_len =
269eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_uint16_t_array(params, data,
270eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
271eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->DevicePropertiesSupported);
272eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
273eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
274eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
275eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->CaptureFormats);
276eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
277eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
278eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
279eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->ImageFormats);
280eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
281eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Manufacturer = ptp_unpack_string(params, data,
282eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
283eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
284eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
285eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Model = ptp_unpack_string(params, data,
286eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
287eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
288eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
289eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DeviceVersion = ptp_unpack_string(params, data,
290eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
291eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
292eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
293eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->SerialNumber = ptp_unpack_string(params, data,
294eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
295eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
296eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
297eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
298eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectHandles array pack/unpack */
299eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
300eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oh				 0
301eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
302b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
303b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
304eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
305eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
306eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
307eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
308eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StoreIDs array pack/unpack */
309eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
310eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_sids			 0
311eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
312b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
313b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
314eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
315eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
316eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	&sids->Storage);
317eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
318eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
319eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StorageInfo pack/unpack */
320eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
321eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageType		 0
322eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FilesystemType		 2
323eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_AccessCapability		 4
324eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_MaxCapability		 6
325eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInBytes		14
326eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInImages	22
327eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageDescription	26
328eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
329b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
330b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
331eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
332eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t storagedescriptionlen;
333eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
334eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
335eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
336eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
337eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
338eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
339eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
340eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageDescription=ptp_unpack_string(params, data,
341eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription, &storagedescriptionlen);
342eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->VolumeLabel=ptp_unpack_string(params, data,
343eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription+storagedescriptionlen*2+1,
344eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&storagedescriptionlen);
345eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
346eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
347eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectInfo pack/unpack */
348eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
349eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_StorageID		 0
350eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectFormat		 4
351eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ProtectionStatus		 6
352eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectCompressedSize	 8
353eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbFormat		12
354eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbCompressedSize	14
355eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixWidth		18
356eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixHeight		22
357eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixWidth		26
358eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixHeight		30
359eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImageBitDepth		34
360eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ParentObject		38
361eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationType		42
362eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationDesc		44
363eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_SequenceNumber		48
364eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_filenamelen		52
365eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_Filename			53
366eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
367a679b1c4d273f210abb6befc5d9954a25427c329Richard Low// the max length assuming zero length dates. We have need 3
368a679b1c4d273f210abb6befc5d9954a25427c329Richard Low// bytes for these.
369a679b1c4d273f210abb6befc5d9954a25427c329Richard Low#define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
370a679b1c4d273f210abb6befc5d9954a25427c329Richard Low
371b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
372b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
373eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
374b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* oidata;
375eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
376eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen=0;
377a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	/* let's allocate some memory first; correct assuming zero length dates */
378a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	oidata=malloc(PTP_oi_MaxLen);
379eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* the caller should free it after use! */
380eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0
381eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date="20020101T010101"; /* XXX Fake date */
382eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
383a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	memset (oidata, 0, PTP_oi_MaxLen);
384eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
385eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
386eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
387eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
388eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
389eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
390eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
391eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
392eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
393eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
394eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
395eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
396eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
397eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
398eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
399eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
400eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
401eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
402eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	filenamelen=(uint8_t)strlen(oi->Filename);
403eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
404eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
405eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
406eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
407eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
408eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/*
409eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 *XXX Fake date.
410eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * for example Kodak sets Capture date on the basis of EXIF data.
411eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * Spec says that this field is from perspective of Initiator.
412eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
413eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
414eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capturedatelen=strlen(capture_date);
415eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
416eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
417eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
418eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
419eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
420eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
421eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
422eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
423eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
424eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		  capture_date[i];
425eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
426eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
427eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* XXX this function should return dataset length */
428eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
429eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*oidataptr=oidata;
430a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3);
431eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
432eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
433b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
434b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
435eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
436eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
437eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen;
438eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date;
439eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char tmp[16];
440eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	struct tm tm;
441eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
442eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	memset(&tm,0,sizeof(tm));
443eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
444eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
445eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
446eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
447eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
448eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
449eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
450eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
451eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
452eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
453eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
454eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
455eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
456eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
457eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
458eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
459eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
460eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
461eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
462eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
463eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* subset of ISO 8601, without '.s' tenths of second and
464eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * time zone
465eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
466eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (capturedatelen>15)
467eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	{
468eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date, 4);
469eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[4] = 0;
470eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_year=atoi (tmp) - 1900;
471eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 4, 2);
472eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
473eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mon = atoi (tmp) - 1;
474eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 6, 2);
475eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
476eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mday = atoi (tmp);
477eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 9, 2);
478eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
479eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_hour = atoi (tmp);
480eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 11, 2);
481eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
482eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_min = atoi (tmp);
483eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 13, 2);
484eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
485eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_sec = atoi (tmp);
486eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		oi->CaptureDate=mktime (&tm);
487eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
488eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
489eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
490eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* now it's modification date ;) */
491eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
492eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2
493eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		+capturedatelen*2+2,&capturedatelen);
494eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (capturedatelen>15)
495eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	{
496eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date, 4);
497eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[4] = 0;
498eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_year=atoi (tmp) - 1900;
499eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 4, 2);
500eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
501eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mon = atoi (tmp) - 1;
502eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 6, 2);
503eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
504eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mday = atoi (tmp);
505eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 9, 2);
506eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
507eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_hour = atoi (tmp);
508eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 11, 2);
509eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
510eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_min = atoi (tmp);
511eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 13, 2);
512eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
513eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_sec = atoi (tmp);
514eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		oi->ModificationDate=mktime (&tm);
515eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
516eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
517eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
518eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
519eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Custom Type Value Assignement (without Length) macro frequently used below */
520b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define CTVAL(target,func) {			\
521b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(target))	\
522b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;			\
523b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	target = func(&data[*offset]);		\
524b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(target);		\
525eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
526eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
527b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define RARR(val,member,func)	{			\
528b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int n,j;					\
529b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(uint32_t))		\
530b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;				\
531b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	n = dtoh32a (&data[*offset]);			\
532b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(uint32_t);			\
533b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij							\
534b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.count = n;				\
535b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
536b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!val->a.v) return 0;			\
537b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (j=0;j<n;j++)				\
538b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(val->a.v[j].member, func);	\
539b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
540eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
541b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
542b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPV (
543b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPParams *params, unsigned char* data, int *offset, int total,
544b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPPropertyValue* value, uint16_t datatype
545b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij) {
546eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
547b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
548b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i8,dtoh8a);
549b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
550b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
551b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u8,dtoh8a);
552b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
553b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
554b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i16,dtoh16a);
555b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
556b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
557b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u16,dtoh16a);
558b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
559b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
560b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i32,dtoh32a);
561b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
562b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
563b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u32,dtoh32a);
564b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
565037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
566037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
567037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
568037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_UINT64:
569037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 8;
570037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of uint64\n");*/
571037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
572037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_INT64:
573037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 8;
574037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of int64\n");*/
575037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
576037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_UINT128:
577037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
578037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of uint128n");*/
579037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
580037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_INT128:
581037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
582037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of int128n");*/
583037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
584037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
585037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
586037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
587b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
588b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i8,dtoh8a);
589b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
590b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
591b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u8,dtoh8a);
592b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
593b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
594b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u16,dtoh16a);
595b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
596b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
597b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i16,dtoh16a);
598b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
599b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
600b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u32,dtoh32a);
601b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
602b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
603b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i32,dtoh32a);
604b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
605b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
606b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int arrays are unimplemented also */
607b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
608b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		uint8_t len;
609b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		/* XXX: max size */
610b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		value->str = ptp_unpack_string(params,data,*offset,&len);
611b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		*offset += len*2+1;
612b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!value->str)
613eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			return 0;
614b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
615eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
616037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	default:
617037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		return 0;
618b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
619b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
620eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
621eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
622eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Device Property pack/unpack */
623eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
624eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DevicePropertyCode	0
625eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DataType		2
626eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_GetSet			4
627eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_FactoryDefaultValue	5
628eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
629b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
630b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
631eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
632b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
633eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
634b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (dpd, 0, sizeof(*dpd));
635eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
636eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
637eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
638b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
639b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_dpd_FactoryDefaultValue;
640b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
641b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
642b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
643b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
644b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
645b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* if offset==0 then Data Type format is not supported by this
646b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   code or the Data Type is a string (with two empty strings as
647b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
648b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   not present. */
649b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
650eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
651b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (offset==PTP_dpd_FactoryDefaultValue)
652b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 1;
653b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
654b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	dpd->FormFlag=dtoh8a(&data[offset]);
655b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
656eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
657eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (dpd->FormFlag) {
658b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Range:
659b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
660b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
661b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
662b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
663b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
664b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
665eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
666b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Enumeration: {
667b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
668eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
669b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
670b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
671b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
672b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
673b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
674b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
675b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
676b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
677b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
678b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
679b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
680b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
681b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
682b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
683b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
684b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
685b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
686b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
687b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
688b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
689eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			}
690b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
691eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
692eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
693b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
694b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
695b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
696b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_devicepropdesc(dpd);
697b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
698eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
699eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
700b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/* (MTP) Object Property pack/unpack */
701b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_ObjectPropertyCode	0
702b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_DataType		2
703b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_GetSet			4
704b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_FactoryDefaultValue	5
705eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
706b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
707b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
708eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
709b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
710b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
711b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (opd, 0, sizeof(*opd));
712b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
713b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
714b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
715b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
716b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_opd_FactoryDefaultValue;
717b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
718b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
719b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
720b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GroupCode=dtoh32a(&data[offset]);
721b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint32_t);
722b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
723b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->FormFlag=dtoh8a(&data[offset]);
724b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
725b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
726b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	switch (opd->FormFlag) {
727b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Range:
728b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
729b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
730b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
731b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
732b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
733b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
734b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
735b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Enumeration: {
736b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
737b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define N	opd->FORM.Enum.NumberOfValues
738b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
739b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
740b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
741b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!opd->FORM.Enum.SupportedValue)
742b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
743b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
744b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
745b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
746b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
747b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
748b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
749b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
750b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
751b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
752b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
753b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
754b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
755b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
756b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				opd->FORM.Enum.NumberOfValues = i;
757b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
758b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			}
759b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
760b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
761b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
762eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
763b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
764b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
765b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_objectpropdesc(opd);
766b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
767eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
768eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
769eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
770b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
771b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
772eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
773b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* dpv=NULL;
774eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t size=0;
775b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int	i;
776eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
777eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
778b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
779b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int8_t);
780b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
781b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->i8);
782b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
783b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
784b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint8_t);
785b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
786b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->u8);
787b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
788b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
789b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int16_t);
790b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
791b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->i16);
792b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
793b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
794b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint16_t);
795b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
796b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->u16);
797b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
798b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
799b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int32_t);
800b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
801b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->i32);
802b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
803b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
804b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t);
805b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
806b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->u32);
807b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
808b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
809b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
810b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
811b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
812b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
813b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod8a(&dpv[4+i],value->a.v[i].u8);
814b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
815b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
816b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
817b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
818b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
819b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
820b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod8a(&dpv[4+i],value->a.v[i].i8);
821b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
822b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
823b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
824b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
825b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
826b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
827b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod16a(&dpv[4+i],value->a.v[i].u16);
828b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
829b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
830b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
831b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
832b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
833b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
834b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod16a(&dpv[4+i],value->a.v[i].i16);
835b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
836b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
837b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
838b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
839b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
840b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
841b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod32a(&dpv[4+i],value->a.v[i].u32);
842b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
843b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
844b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
845b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
846b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
847b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
848b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod32a(&dpv[4+i],value->a.v[i].i32);
849b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
850b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
851b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
852735f41692934a716158cf051d76e988febeca7eeLinus Walleij		dpv=ptp_get_packed_stringcopy(params, value->str, &size);
853eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
854b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
855eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
856eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*dpvptr=dpv;
857eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return size;
85899310d4445697da39f22dff35457c75e35e97171Linus Walleij}
85999310d4445697da39f22dff35457c75e35e97171Linus Walleij
86099310d4445697da39f22dff35457c75e35e97171Linus Walleij#define MAX_MTP_PROPS 127
86199310d4445697da39f22dff35457c75e35e97171Linus Walleijstatic inline uint32_t
8626c0a6ce803cf79802b1c48339adf0964db30ec83Richard Lowptp_pack_OPL (PTPParams *params, MTPPropList *proplist, unsigned char** opldataptr)
86399310d4445697da39f22dff35457c75e35e97171Linus Walleij{
86499310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char* opldata;
86599310d4445697da39f22dff35457c75e35e97171Linus Walleij	MTPPropList *propitr;
86699310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char *packedprops[MAX_MTP_PROPS];
86799310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t packedpropslens[MAX_MTP_PROPS];
86839b9374f23451201dece736db13f0f648584dc32Linus Walleij	uint32_t packedobjecthandles[MAX_MTP_PROPS];
86999310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropsids[MAX_MTP_PROPS];
87099310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropstypes[MAX_MTP_PROPS];
87199310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t totalsize = 0;
87299310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t bufp = 0;
87399310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t noitems = 0;
87499310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t i;
87599310d4445697da39f22dff35457c75e35e97171Linus Walleij
87699310d4445697da39f22dff35457c75e35e97171Linus Walleij	totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
87799310d4445697da39f22dff35457c75e35e97171Linus Walleij	propitr = proplist;
87899310d4445697da39f22dff35457c75e35e97171Linus Walleij	while (propitr != NULL && noitems < MAX_MTP_PROPS) {
8796c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		/* Object Handle */
88039b9374f23451201dece736db13f0f648584dc32Linus Walleij		packedobjecthandles[noitems]=propitr->ObjectHandle;
88199310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint32_t); /* Object ID */
88299310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Metadata type */
88399310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropsids[noitems]=propitr->property;
88499310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
88599310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Data type */
88699310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropstypes[noitems]= propitr->datatype;
88799310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
88899310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Add each property to be sent. */
88999310d4445697da39f22dff35457c75e35e97171Linus Walleij	        packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
89099310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += packedpropslens[noitems];
89199310d4445697da39f22dff35457c75e35e97171Linus Walleij		noitems ++;
89299310d4445697da39f22dff35457c75e35e97171Linus Walleij		propitr = propitr->next;
89399310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
89499310d4445697da39f22dff35457c75e35e97171Linus Walleij
89599310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Allocate memory for the packed property list */
89699310d4445697da39f22dff35457c75e35e97171Linus Walleij	opldata = malloc(totalsize);
89799310d4445697da39f22dff35457c75e35e97171Linus Walleij
89899310d4445697da39f22dff35457c75e35e97171Linus Walleij	htod32a(&opldata[bufp],noitems);
89999310d4445697da39f22dff35457c75e35e97171Linus Walleij	bufp += 4;
90099310d4445697da39f22dff35457c75e35e97171Linus Walleij
90199310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Copy into a nice packed list */
90299310d4445697da39f22dff35457c75e35e97171Linus Walleij	for (i = 0; i < noitems; i++) {
90399310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Object ID */
9046c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		htod32a(&opldata[bufp],packedobjecthandles[i]);
90599310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint32_t);
90699310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropsids[i]);
90799310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
90899310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropstypes[i]);
90999310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
91099310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* The copy the actual property */
91199310d4445697da39f22dff35457c75e35e97171Linus Walleij		memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
91299310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += packedpropslens[i];
91399310d4445697da39f22dff35457c75e35e97171Linus Walleij		free(packedprops[i]);
91499310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
91599310d4445697da39f22dff35457c75e35e97171Linus Walleij	*opldataptr = opldata;
91699310d4445697da39f22dff35457c75e35e97171Linus Walleij	return totalsize;
917eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
918eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
9198d82d2f4b0794e41ec26289045867eebb3496b8cRichard Lowstatic inline int
9208d82d2f4b0794e41ec26289045867eebb3496b8cRichard Lowptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPPropList **proplist, unsigned int len)
9218d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low{
922277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	uint32_t prop_count = dtoh32a(data);
923277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	MTPPropList *prop = NULL;
924277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	int offset = 0, i;
925277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
926277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	if (prop_count == 0) {
927277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		*proplist = NULL;
928277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		return 0;
929277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
930277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	data += sizeof(uint32_t);
931277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	*proplist = malloc(sizeof(MTPPropList));
932277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	prop = *proplist;
933277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	for (i = 0; i < prop_count; i++) {
9346c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		prop->ObjectHandle = dtoh32a(data);
935277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint32_t);
936277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint32_t);
937277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
9386c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		prop->property = dtoh16a(data);
939277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
940277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
941277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
9426c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		prop->datatype = dtoh16a(data);
943277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
944277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
945277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
946277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		offset = 0;
947277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		ptp_unpack_DPV(params, data, &offset, len, &prop->propval, prop->datatype);
948277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += offset;
949277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= offset;
950277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
951277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		if (i != prop_count - 1) {
952277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij			prop->next = malloc(sizeof(MTPPropList));
953277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij			prop = prop->next;
954277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		} else
955277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij			prop->next = NULL;
956277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
957277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	return prop_count;
9588d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low}
9598d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low
960eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
961eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP USB Event container unpack
962eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
963eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
964eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
965eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Length		0
966eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Type		4
967eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Code		6
968eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_TransId		8
969eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param1		12
970eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param2		16
971eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param3		20
972eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
973b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
974b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_EC (PTPParams *params, unsigned char* data, PTPUSBEventContainer *ec, unsigned int len)
975eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
976eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
977eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
978eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->length=dtoh32a(&data[PTP_ec_Length]);
979eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->type=dtoh16a(&data[PTP_ec_Type]);
980eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->code=dtoh16a(&data[PTP_ec_Code]);
981eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->trans_id=dtoh32a(&data[PTP_ec_TransId]);
982b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
983eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (ec->length>=(PTP_ec_Param1+4))
984eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param1=dtoh32a(&data[PTP_ec_Param1]);
985eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	else
986eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param1=0;
987eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (ec->length>=(PTP_ec_Param2+4))
988eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param2=dtoh32a(&data[PTP_ec_Param2]);
989eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	else
990eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param2=0;
991eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (ec->length>=(PTP_ec_Param3+4))
992eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param3=dtoh32a(&data[PTP_ec_Param3]);
993eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	else
994eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param3=0;
995eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
996eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
997eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
998eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP Canon Folder Entry unpack
999eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1000eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1001eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectHandle		0
1002eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectFormatCode	4
1003eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Flags			6
1004eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectSize		7
1005eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Time			11
1006eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Filename		15
1007eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1008b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1009b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1010eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1011eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
1012eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1013eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
1014eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
1015eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
1016eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
1017b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
1018eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
1019eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1020b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
1021b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
1022b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1023b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/*
1024b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij    PTP USB Event container unpack for Nikon events.
1025b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij*/
1026b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Length		0
1027b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Code		2
1028b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Param1		4
1029b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Size		6
1030b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1031b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPUSBEventContainer **ec, int *cnt)
1032b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij{
1033b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i;
1034b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1035b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = NULL;
1036b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (data == NULL)
1037b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1038b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (len < PTP_nikon_ec_Code)
1039b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1040b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
1041b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
1042b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1043b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = malloc(sizeof(PTPUSBEventContainer)*(*cnt));
1044b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1045b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<*cnt;i++) {
1046b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset(&(*ec)[i],0,sizeof(PTPUSBEventContainer));
1047b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		(*ec)[i].code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
1048b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		(*ec)[i].param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
1049b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1050eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1051eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1052eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1053b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
1054b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
1055b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i, len = 0;
1056b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint8_t	retlen;
1057b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char *curdata;
1058b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1059b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	len =	2*(strlen(text->title)+1)+1+
1060b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[0])+1)+1+
1061b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[1])+1)+1+
1062b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[2])+1)+1+
1063b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[3])+1)+1+
1064b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[4])+1)+1+
1065b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		4*2+2*4+2+4+2+5*4*2;
1066b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*data = malloc(len);
1067b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!*data) return 0;
1068b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1069b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	curdata = *data;
1070b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,100);curdata+=2;
1071b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1);curdata+=2;
1072b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0);curdata+=2;
1073b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1000);curdata+=2;
1074b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1075b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1076b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1077b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1078b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,6);curdata+=2;
1079b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1080b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1081b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1082b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0x10);curdata+=2;
1083b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1084b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<5;i++) {
1085b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1086b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x10);curdata+=2;
1087b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x01);curdata+=2;
1088b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x02);curdata+=2;
1089b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x06);curdata+=2;
1090b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1091b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return len;
1092b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
10937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
10947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_version	0x00
10957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_ofc	0x02
10967347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk1	0x04
10977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_objectid	0x08
10987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_parentid	0x0c
10997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_previd	0x10	/* in same dir */
11007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextid	0x14	/* in same dir */
11017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextchild	0x18	/* down one dir */
11027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_storageid	0x1c	/* only in storage entry */
11037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_name	0x20
11047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_flags	0x2c
11057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_size	0x30
11067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unixtime	0x34
11077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_year	0x38
11087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_month	0x39
11097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_mday	0x3a
11107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_hour	0x3b
11117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_minute	0x3c
11127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_second	0x3d
11137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk2	0x3e
11147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_thumbsize	0x40
11157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_width	0x44
11167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_height	0x48
11177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
11187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijstatic inline uint16_t
11197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijptp_unpack_canon_directory (
11207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPParams		*params,
11217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned char		*dir,
11227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		cnt,
11237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectHandles	*handles,
11247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectInfo		**oinfos,	/* size(handles->n) */
11257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		**flags		/* size(handles->n) */
11267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij) {
11277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned int	i, j, nrofobs = 0, curob = 0;
11287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
11297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
11307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++)
11317347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(dir+i*0x4c)) nrofobs++;
11327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->n = nrofobs;
11337347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs);
11347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!handles->Handler) return PTP_RC_GeneralError;
11357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*oinfos = calloc(sizeof((*oinfos)[0]),nrofobs);
11367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*oinfos) return PTP_RC_GeneralError;
11377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*flags  = calloc(sizeof((*flags)[0]),nrofobs);
11387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*flags) return PTP_RC_GeneralError;
11397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
11407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Migrate data into objects ids, handles into
11417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the object handler array.
11427347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 */
11437347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	curob = 0;
11447347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
11457347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
11467347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		PTPObjectInfo	*oi = (*oinfos)+curob;
11477347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
11487347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!ISOBJECT(cur))
11497347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
11507347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
11517347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
11527347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->StorageID		= 0xffffffff;
11537347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectFormat	= dtoh16a(cur + ptp_canon_dir_ofc);
11547347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ParentObject	= dtoh32a(cur + ptp_canon_dir_parentid);
11557347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->Filename		= strdup((char*)(cur + ptp_canon_dir_name));
11567347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
11577347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ThumbCompressedSize	= dtoh32a(cur + ptp_canon_dir_thumbsize);
11587347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixWidth	= dtoh32a(cur + ptp_canon_dir_width);
11597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixHeight	= dtoh32a(cur + ptp_canon_dir_height);
11607347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->CaptureDate		= oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
11617347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*flags)[curob]		= dtoh32a(cur + ptp_canon_dir_flags);
11627347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		curob++;
11637347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
11647347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over Storage ID entries and distribute the IDs to
11657347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the parent objects. */
11667347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
11677347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
11687347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
11697347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
11707347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(cur))
11717347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
11727347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
11737347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (j == handles->n) continue;
11747347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
11757347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
11767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over all objects and distribute the storage ids */
11777347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	while (1) {
11787347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		int changed = 0;
11797347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (i=0;i<cnt;i++) {
11807347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			unsigned char	*cur = dir+i*0x4c;
11817347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	oid = dtoh32a(cur + ptp_canon_dir_objectid);
11827347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
11837347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
11847347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	storageid;
11857347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
11867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (!ISOBJECT(cur))
11877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
11887347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
11897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (j == handles->n) {
11907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				/*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
11917347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
11927347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
11937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 		storageid = (*oinfos)[j].StorageID;
11947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (storageid == 0xffffffff) continue;
11957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextoid != 0xffffffff) {
11967347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
11977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
11987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
11997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
12007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
12017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
12027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
12037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
12047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
12057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
12067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextchild != 0xffffffff) {
12077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
12087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
12097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
12107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
12117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
12127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
12137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
12147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
12157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
12167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
12177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		}
12187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		/* Check if we:
12197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed no entry (nothing more to do)
12207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed all of them at once (usually happens)
12217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * break if we do.
12227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 */
12237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!changed || (changed==nrofobs-1))
12247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			break;
12257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
12267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#undef ISOBJECT
12277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	return PTP_RC_OK;
12287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij}
12297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
1230