ptp-pack.c revision a823a70e892d5eb1f4528679429cb3d9539abbe4
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);
154a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (nconv == (size_t) -1) {
155a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		ucs2str[0] = 0x0000U;
156a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	}
157a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packedlen = ucs2strlen(ucs2str);
158a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (packedlen > PTP_MAXSTRLEN-1) {
159a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		*len=0;
160a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return;
161a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	}
162a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	*len = (uint8_t) packedlen;
163a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
164a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* +1 for the length byte, no zero 0x0000 terminator */
165a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	htod8a(&data[offset],packedlen+1);
166a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	for (i=0;i<packedlen && i< PTP_MAXSTRLEN; i++) {
167a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		htod16a(&data[offset+i*2+1],ucs2str[i]);
168eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
169eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
170eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
171a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline unsigned char *
172a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijptp_get_packed_stringcopy(PTPParams *params, char *string)
173a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
174a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	uint8_t packed[PTP_MAXSTRLEN+3], len;
175a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t plen;
176a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	unsigned char *retcopy = NULL;
177a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
178a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
179a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	plen = len + 1;
180a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Assure proper termination */
181a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packed[plen] = 0x00;
182a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packed[plen+1] = 0x00;
183a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Include terminator */
184a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	plen += 2;
185a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	retcopy = malloc(plen);
186a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (!retcopy)
187a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return NULL;
188a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	memcpy(retcopy, packed, plen);
189a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return (retcopy);
190a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
191a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
192b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
193b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
194eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
195eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
196eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
197eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
198eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint32_t));
199eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
200eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
201eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
202eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
203eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
204eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
205eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
206b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
207f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
208f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij{
209f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	uint32_t i=0;
210f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
211f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	*data = malloc ((arraylen+1)*sizeof(uint32_t));
212f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	htod32a(&(*data)[0],arraylen);
213f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	for (i=0;i<arraylen;i++)
214f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
215f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	return (arraylen+1)*sizeof(uint32_t);
216f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij}
217f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
218f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijstatic inline uint32_t
219b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
220eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
221eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
222eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
223eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
224eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint16_t));
225eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
226eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
227eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
228eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
229eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
230eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
231eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
232eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* DeviceInfo pack/unpack */
233eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
234eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_StandardVersion		 0
235eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionID	 2
236eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionVersion	 6
237eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionDesc	 8
238eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_FunctionalMode		 8
239eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_OperationsSupported	10
240eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
241b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
242b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
243eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
244eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t len;
245eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	unsigned int totallen;
246eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
247eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->StaqndardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
248eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionID =
249eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh32a(&data[PTP_di_VendorExtensionID]);
250eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionVersion =
251eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
252eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionDesc =
253eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_string(params, data,
254eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_VendorExtensionDesc, &len);
255eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=len*2+1;
256eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->FunctionalMode =
257eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
258eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
259eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
260eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->OperationsSupported);
261eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
262eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
263eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
264eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->EventsSupported);
265eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
266eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DevicePropertiesSupported_len =
267eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_uint16_t_array(params, data,
268eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
269eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->DevicePropertiesSupported);
270eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
271eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
272eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
273eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->CaptureFormats);
274eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
275eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
276eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
277eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->ImageFormats);
278eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
279eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Manufacturer = ptp_unpack_string(params, data,
280eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
281eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
282eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
283eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Model = ptp_unpack_string(params, data,
284eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
285eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
286eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
287eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DeviceVersion = ptp_unpack_string(params, data,
288eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
289eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
290eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
291eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->SerialNumber = ptp_unpack_string(params, data,
292eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
293eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
294eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
295eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
296eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectHandles array pack/unpack */
297eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
298eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oh				 0
299eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
300b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
301b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
302eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
303eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
304eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
305eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
306eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StoreIDs array pack/unpack */
307eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
308eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_sids			 0
309eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
310b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
311b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
312eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
313eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
314eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	&sids->Storage);
315eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
316eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
317eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StorageInfo pack/unpack */
318eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
319eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageType		 0
320eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FilesystemType		 2
321eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_AccessCapability		 4
322eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_MaxCapability		 6
323eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInBytes		14
324eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInImages	22
325eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageDescription	26
326eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
327b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
328b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
329eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
330eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t storagedescriptionlen;
331eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
332eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
333eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
334eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
335eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
336eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
337eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
338eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageDescription=ptp_unpack_string(params, data,
339eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription, &storagedescriptionlen);
340eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->VolumeLabel=ptp_unpack_string(params, data,
341eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription+storagedescriptionlen*2+1,
342eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&storagedescriptionlen);
343eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
344eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
345eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectInfo pack/unpack */
346eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
347eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_StorageID		 0
348eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectFormat		 4
349eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ProtectionStatus		 6
350eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectCompressedSize	 8
351eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbFormat		12
352eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbCompressedSize	14
353eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixWidth		18
354eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixHeight		22
355eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixWidth		26
356eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixHeight		30
357eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImageBitDepth		34
358eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ParentObject		38
359eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationType		42
360eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationDesc		44
361eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_SequenceNumber		48
362eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_filenamelen		52
363eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_Filename			53
364eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
365b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
366b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
367eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
368b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* oidata;
369eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
370eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen=0;
371eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* let's allocate some memory first; XXX i'm sure it's wrong */
372eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oidata=malloc(PTP_oi_Filename+(strlen(oi->Filename)+1)*2+4);
373eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* the caller should free it after use! */
374eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0
375eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date="20020101T010101"; /* XXX Fake date */
376eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
377eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	memset (oidata, 0, (PTP_oi_Filename+(strlen(oi->Filename)+1)*2+4));
378eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
379eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
380eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
381eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
382eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
383eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
384eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
385eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
386eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
387eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
388eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
389eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
390eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
391eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
392eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
393eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
394eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
395eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
396eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	filenamelen=(uint8_t)strlen(oi->Filename);
397eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
398eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
399eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
400eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
401eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
402eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/*
403eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 *XXX Fake date.
404eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * for example Kodak sets Capture date on the basis of EXIF data.
405eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * Spec says that this field is from perspective of Initiator.
406eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
407eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
408eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capturedatelen=strlen(capture_date);
409eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
410eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
411eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
412eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
413eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
414eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
415eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
416eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
417eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
418eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		  capture_date[i];
419eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
420eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
421eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* XXX this function should return dataset length */
422eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
423eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*oidataptr=oidata;
424eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return (PTP_oi_Filename+(filenamelen+1)*2+(capturedatelen+1)*4);
425eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
426eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
427b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
428b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
429eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
430eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
431eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen;
432eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date;
433eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char tmp[16];
434eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	struct tm tm;
435eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
436eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	memset(&tm,0,sizeof(tm));
437eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
438eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
439eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
440eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
441eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
442eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
443eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
444eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
445eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
446eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
447eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
448eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
449eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
450eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
451eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
452eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
453eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
454eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
455eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
456eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
457eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* subset of ISO 8601, without '.s' tenths of second and
458eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * time zone
459eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
460eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (capturedatelen>15)
461eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	{
462eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date, 4);
463eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[4] = 0;
464eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_year=atoi (tmp) - 1900;
465eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 4, 2);
466eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
467eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mon = atoi (tmp) - 1;
468eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 6, 2);
469eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
470eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mday = atoi (tmp);
471eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 9, 2);
472eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
473eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_hour = atoi (tmp);
474eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 11, 2);
475eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
476eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_min = atoi (tmp);
477eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 13, 2);
478eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
479eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_sec = atoi (tmp);
480eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		oi->CaptureDate=mktime (&tm);
481eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
482eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
483eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
484eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* now it's modification date ;) */
485eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
486eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2
487eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		+capturedatelen*2+2,&capturedatelen);
488eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (capturedatelen>15)
489eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	{
490eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date, 4);
491eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[4] = 0;
492eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_year=atoi (tmp) - 1900;
493eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 4, 2);
494eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
495eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mon = atoi (tmp) - 1;
496eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 6, 2);
497eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
498eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_mday = atoi (tmp);
499eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 9, 2);
500eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
501eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_hour = atoi (tmp);
502eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 11, 2);
503eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
504eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_min = atoi (tmp);
505eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		strncpy (tmp, capture_date + 13, 2);
506eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tmp[2] = 0;
507eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		tm.tm_sec = atoi (tmp);
508eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		oi->ModificationDate=mktime (&tm);
509eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
510eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
511eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
512eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
513eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Custom Type Value Assignement (without Length) macro frequently used below */
514b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define CTVAL(target,func) {			\
515b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(target))	\
516b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;			\
517b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	target = func(&data[*offset]);		\
518b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(target);		\
519eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
520eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
521b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define RARR(val,member,func)	{			\
522b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int n,j;					\
523b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(uint32_t))		\
524b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;				\
525b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	n = dtoh32a (&data[*offset]);			\
526b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(uint32_t);			\
527b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij							\
528b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.count = n;				\
529b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
530b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!val->a.v) return 0;			\
531b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (j=0;j<n;j++)				\
532b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(val->a.v[j].member, func);	\
533b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
534eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
535b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
536b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPV (
537b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPParams *params, unsigned char* data, int *offset, int total,
538b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPPropertyValue* value, uint16_t datatype
539b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij) {
540eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
541b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
542b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i8,dtoh8a);
543b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
544b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
545b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u8,dtoh8a);
546b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
547b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
548b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i16,dtoh16a);
549b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
550b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
551b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u16,dtoh16a);
552b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
553b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
554b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i32,dtoh32a);
555b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
556b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
557b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u32,dtoh32a);
558b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
559b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
560b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i8,dtoh8a);
561b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
562b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
563b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u8,dtoh8a);
564b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
565b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
566b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u16,dtoh16a);
567b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
568b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
569b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i16,dtoh16a);
570b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
571b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
572b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u32,dtoh32a);
573b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
574b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
575b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i32,dtoh32a);
576b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
577b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
578b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int arrays are unimplemented also */
579b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
580b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		uint8_t len;
581b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		/* XXX: max size */
582b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		value->str = ptp_unpack_string(params,data,*offset,&len);
583b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		*offset += len*2+1;
584b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!value->str)
585eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			return 0;
586b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
587eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
588b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
589b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
590eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
591eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
592eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Device Property pack/unpack */
593eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
594eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DevicePropertyCode	0
595eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DataType		2
596eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_GetSet			4
597eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_FactoryDefaultValue	5
598eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
599b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
600b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
601eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
602b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
603eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
604b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (dpd, 0, sizeof(*dpd));
605eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
606eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
607eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
608b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
609b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_dpd_FactoryDefaultValue;
610b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
611b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
612b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
613b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
614b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
615b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* if offset==0 then Data Type format is not supported by this
616b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   code or the Data Type is a string (with two empty strings as
617b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
618b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   not present. */
619b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
620eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
621b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (offset==PTP_dpd_FactoryDefaultValue)
622b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 1;
623b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
624b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	dpd->FormFlag=dtoh8a(&data[offset]);
625b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
626eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
627eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (dpd->FormFlag) {
628b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Range:
629b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
630b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
631b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
632b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
633b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
634b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
635eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
636b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Enumeration: {
637b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
638eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
639b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
640b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
641b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
642b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
643b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
644b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
645b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
646b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
647b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
648b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
649b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
650b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
651b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
652b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
653b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
654b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
655b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
656b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
657b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
658b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
659eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			}
660b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
661eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
662eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
663b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
664b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
665b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
666b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_devicepropdesc(dpd);
667b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
668eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
669eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
670b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/* (MTP) Object Property pack/unpack */
671b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_ObjectPropertyCode	0
672b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_DataType		2
673b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_GetSet			4
674b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_FactoryDefaultValue	5
675eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
676b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
677b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
678eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
679b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
680b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
681b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (opd, 0, sizeof(*opd));
682b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
683b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
684b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
685b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
686b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_opd_FactoryDefaultValue;
687b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
688b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
689b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
690b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GroupCode=dtoh32a(&data[offset]);
691b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint32_t);
692b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
693b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->FormFlag=dtoh8a(&data[offset]);
694b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
695b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
696b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	switch (opd->FormFlag) {
697b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Range:
698b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
699b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
700b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
701b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
702b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
703b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
704b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
705b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Enumeration: {
706b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
707b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define N	opd->FORM.Enum.NumberOfValues
708b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
709b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
710b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
711b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!opd->FORM.Enum.SupportedValue)
712b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
713b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
714b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
715b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
716b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
717b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
718b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
719b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
720b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
721b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
722b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
723b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
724b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
725b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
726b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				opd->FORM.Enum.NumberOfValues = i;
727b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
728b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			}
729b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
730b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
731b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
732eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
733b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
734b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
735b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_objectpropdesc(opd);
736b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
737eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
738eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
739eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
740b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
741b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
742eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
743b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* dpv=NULL;
744eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t size=0;
745b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int	i;
746eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
747eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
748b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
749b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int8_t);
750b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
751b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->i8);
752b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
753b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
754b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint8_t);
755b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
756b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->u8);
757b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
758b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
759b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int16_t);
760b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
761b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->i16);
762b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
763b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
764b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint16_t);
765b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
766b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->u16);
767b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
768b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
769b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int32_t);
770b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
771b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->i32);
772b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
773b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
774b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t);
775b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
776b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->u32);
777b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
778b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
779b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
780b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
781b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
782b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
783b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod8a(&dpv[4+i],value->a.v[i].u8);
784b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
785b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
786b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
787b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
788b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
789b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
790b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod8a(&dpv[4+i],value->a.v[i].i8);
791b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
792b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
793b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
794b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
795b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
796b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
797b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod16a(&dpv[4+i],value->a.v[i].u16);
798b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
799b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
800b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
801b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
802b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
803b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
804b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod16a(&dpv[4+i],value->a.v[i].i16);
805b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
806b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
807b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
808b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
809b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
810b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
811b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod32a(&dpv[4+i],value->a.v[i].u32);
812b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
813b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
814b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
815b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
816b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
817b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
818b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			htod32a(&dpv[4+i],value->a.v[i].i32);
819b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
820b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
821b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
822a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		dpv=ptp_get_packed_stringcopy(params, value->str);
823eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
824b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
825eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
826eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*dpvptr=dpv;
827eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return size;
828eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
829eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
830eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
831eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP USB Event container unpack
832eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
833eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
834eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
835eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Length		0
836eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Type		4
837eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Code		6
838eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_TransId		8
839eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param1		12
840eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param2		16
841eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param3		20
842eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
843b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
844b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_EC (PTPParams *params, unsigned char* data, PTPUSBEventContainer *ec, unsigned int len)
845eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
846eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
847eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
848eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->length=dtoh32a(&data[PTP_ec_Length]);
849eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->type=dtoh16a(&data[PTP_ec_Type]);
850eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->code=dtoh16a(&data[PTP_ec_Code]);
851eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ec->trans_id=dtoh32a(&data[PTP_ec_TransId]);
852b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
853eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (ec->length>=(PTP_ec_Param1+4))
854eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param1=dtoh32a(&data[PTP_ec_Param1]);
855eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	else
856eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param1=0;
857eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (ec->length>=(PTP_ec_Param2+4))
858eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param2=dtoh32a(&data[PTP_ec_Param2]);
859eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	else
860eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param2=0;
861eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (ec->length>=(PTP_ec_Param3+4))
862eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param3=dtoh32a(&data[PTP_ec_Param3]);
863eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	else
864eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ec->param3=0;
865eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
866eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
867eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
868eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP Canon Folder Entry unpack
869eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
870eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
871eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectHandle		0
872eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectFormatCode	4
873eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Flags			6
874eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectSize		7
875eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Time			11
876eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Filename		15
877eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
878b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
879b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
880eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
881eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
882eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
883eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
884eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
885eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
886eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
887b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
888eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
889eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
890b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
891b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
892b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
893b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/*
894b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij    PTP USB Event container unpack for Nikon events.
895b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij*/
896b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Length		0
897b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Code		2
898b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Param1		4
899b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Size		6
900b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
901b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPUSBEventContainer **ec, int *cnt)
902b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij{
903b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i;
904b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
905b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = NULL;
906b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (data == NULL)
907b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
908b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (len < PTP_nikon_ec_Code)
909b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
910b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
911b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
912b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
913b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = malloc(sizeof(PTPUSBEventContainer)*(*cnt));
914b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
915b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<*cnt;i++) {
916b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset(&(*ec)[i],0,sizeof(PTPUSBEventContainer));
917b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		(*ec)[i].code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
918b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		(*ec)[i].param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
919b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
920eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
921eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
922eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
923b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
924b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
925b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i, len = 0;
926b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint8_t	retlen;
927b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char *curdata;
928b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
929b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	len =	2*(strlen(text->title)+1)+1+
930b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[0])+1)+1+
931b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[1])+1)+1+
932b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[2])+1)+1+
933b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[3])+1)+1+
934b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[4])+1)+1+
935b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		4*2+2*4+2+4+2+5*4*2;
936b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*data = malloc(len);
937b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!*data) return 0;
938b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
939b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	curdata = *data;
940b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,100);curdata+=2;
941b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1);curdata+=2;
942b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0);curdata+=2;
943b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1000);curdata+=2;
944b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
945b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
946b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
947b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
948b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,6);curdata+=2;
949b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
950b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
951b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
952b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0x10);curdata+=2;
953b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
954b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<5;i++) {
955b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
956b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x10);curdata+=2;
957b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x01);curdata+=2;
958b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x02);curdata+=2;
959b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x06);curdata+=2;
960b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
961b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return len;
962b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
963