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