ptp-pack.c revision d9ee8cd37f0704a501b62a185c3305d236c7c8df
1a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij/* ptp-pack.c
2a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij *
3a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
4a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Copyright (C) 2003-2012 Marcus Meissner <marcus@jet.franken.de>
5a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Copyright (C) 2006-2008 Linus Walleij <triad@df.lth.se>
6a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Copyright (C) 2007 Tero Saarni <tero.saarni@gmail.com>
7a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Copyright (C) 2009 Axel Waggershauser <awagger@web.de>
8a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij *
9a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * This library is free software; you can redistribute it and/or
10a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * modify it under the terms of the GNU Lesser General Public
11a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * License as published by the Free Software Foundation; either
12a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * version 2 of the License, or (at your option) any later version.
13a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij *
14a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * This library is distributed in the hope that it will be useful,
15a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * but WITHOUT ANY WARRANTY; without even the implied warranty of
16a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Lesser General Public License for more details.
18a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij *
19a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * You should have received a copy of the GNU Lesser General Public
20a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * License along with this library; if not, write to the
21a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Boston, MA 02111-1307, USA.
23a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij */
24a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij
25b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/* currently this file is included into ptp.c */
26eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
276db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#ifdef HAVE_ICONV
28a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij#include <iconv.h>
296db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#endif
30a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
31b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
32eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod16p (PTPParams *params, uint16_t var)
33eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
34eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
35eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
36eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
37b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
38eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod32p (PTPParams *params, uint32_t var)
39eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
40eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
41eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
42eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
43b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
44eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod16ap (PTPParams *params, unsigned char *a, uint16_t val)
45eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
46eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (params->byteorder==PTP_DL_LE)
47b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htole16a(a,val);
48e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	else
49eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		htobe16a(a,val);
50eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
51eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
52b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
53eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod32ap (PTPParams *params, unsigned char *a, uint32_t val)
54eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
55eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (params->byteorder==PTP_DL_LE)
56b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htole32a(a,val);
57e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	else
58eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		htobe32a(a,val);
59eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
60eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
61abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijstatic inline void
62abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijhtod64ap (PTPParams *params, unsigned char *a, uint64_t val)
63abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij{
64abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	if (params->byteorder==PTP_DL_LE)
65abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htole64a(a,val);
66e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	else
67abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htobe64a(a,val);
68abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij}
69abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
70b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
71eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh16p (PTPParams *params, uint16_t var)
72eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
73eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
74eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
75eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
76b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
77eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh32p (PTPParams *params, uint32_t var)
78eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
79eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
80eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
81eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
82abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijstatic inline uint64_t
83abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijdtoh64p (PTPParams *params, uint64_t var)
84abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij{
85abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	return ((params->byteorder==PTP_DL_LE)?le64toh(var):be64toh(var));
86abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij}
87abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
88b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijdtoh16ap (PTPParams *params, const unsigned char *a)
90eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
91eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
92eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
93eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
94b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijdtoh32ap (PTPParams *params, const unsigned char *a)
96eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
97eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
98eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
99eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
100b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint64_t
1011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijdtoh64ap (PTPParams *params, const unsigned char *a)
102eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
103abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a));
104eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
105eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
106b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod8a(a,x)	*(uint8_t*)(a) = x
107b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16a(a,x)	htod16ap(params,a,x)
108b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32a(a,x)	htod32ap(params,a,x)
109abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define htod64a(a,x)	htod64ap(params,a,x)
110b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16(x)	htod16p(params,x)
111b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32(x)	htod32p(params,x)
112abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define htod64(x)	htod64p(params,x)
113b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
114b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh8a(x)	(*(uint8_t*)(x))
115b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16a(a)	dtoh16ap(params,a)
116b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32a(a)	dtoh32ap(params,a)
117b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh64a(a)	dtoh64ap(params,a)
118b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16(x)	dtoh16p(params,x)
119b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32(x)	dtoh32p(params,x)
120abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define dtoh64(x)	dtoh64p(params,x)
121b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
122b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
123b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline char*
124b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
125eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
126a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	uint8_t length;
127a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	uint16_t string[PTP_MAXSTRLEN+1];
128a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* allow for UTF-8: max of 3 bytes per UCS-2 char, plus final null */
129e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	char loclstr[PTP_MAXSTRLEN*3+1];
130a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	size_t nconv, srclen, destlen;
131a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	char *src, *dest;
132a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
133a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	length = dtoh8a(&data[offset]);	/* PTP_MAXSTRLEN == 255, 8 bit len */
134a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*len = length;
135a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (length == 0)		/* nothing to do? */
136a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		return(NULL);
137a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
138a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* copy to string[] to ensure correct alignment for iconv(3) */
139a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(string, &data[offset+1], length * sizeof(string[0]));
140a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	string[length] = 0x0000U;   /* be paranoid!  add a terminator. */
141a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[0] = '\0';
142e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij
143a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* convert from camera UCS-2 to our locale */
144a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	src = (char *)string;
145a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	srclen = length * sizeof(string[0]);
146a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	dest = loclstr;
147a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	destlen = sizeof(loclstr)-1;
1486db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	nconv = (size_t)-1;
1496db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#ifdef HAVE_ICONV
150d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij	if (params->cd_ucs2_to_locale != (iconv_t)-1)
151d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij		nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen, &dest, &destlen);
1526db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#endif
153a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (nconv == (size_t) -1) { /* do it the hard way */
154a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		int i;
155a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		/* try the old way, in case iconv is broken */
156a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		for (i=0;i<length;i++) {
157a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			if (dtoh16a(&data[offset+1+2*i])>127)
158a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = '?';
159a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			else
160a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = dtoh16a(&data[offset+1+2*i]);
161eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
162a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		dest = loclstr+length;
163eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
164a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*dest = '\0';
165a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[sizeof(loclstr)-1] = '\0';   /* be safe? */
166a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	return(strdup(loclstr));
167a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
168a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
169a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline int
170a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijucs2strlen(uint16_t const * const unicstr)
171a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
17296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int length = 0;
173a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
174a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Unicode strings are terminated with 2 * 0x00 */
175a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	for(length = 0; unicstr[length] != 0x0000U; length ++);
176a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return length;
177eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
178eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
179a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
180b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
181b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
182eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
18396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int packedlen = 0;
184a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	uint16_t ucs2str[PTP_MAXSTRLEN+1];
185a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	char *ucs2strp = (char *) ucs2str;
186a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t convlen = strlen(string);
187a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
188a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
189a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memset(ucs2strp, 0, sizeof(ucs2str));  /* XXX: necessary? */
1906db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#ifdef HAVE_ICONV
191d000c371601fafcf75d2de2d1060ee11be2007d6Linus Walleij	if (params->cd_locale_to_ucs2 != (iconv_t)-1) {
1926db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		size_t nconv;
1936db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
1946db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		char *stringp = string;
1956db174f4d18af574fab991309e11010aa0eb4543Linus Walleij
1966db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
1976db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			&ucs2strp, &convmax);
1986db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		if (nconv == (size_t) -1)
1996db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			ucs2str[0] = 0x0000U;
200d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij	} else
201d000c371601fafcf75d2de2d1060ee11be2007d6Linus Walleij#endif
2026db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	{
2036db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		int i;
2046db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		for (i=0;i<convlen;i++) {
2056db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			ucs2str[i] = string[i];
2066db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		}
2076db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		ucs2str[convlen] = 0;
2086db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	}
209a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/*
210a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
211a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 *      why do we need ucs2strlen()?
212a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 */
213a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packedlen = ucs2strlen(ucs2str);
214a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (packedlen > PTP_MAXSTRLEN-1) {
215a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		*len=0;
216a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return;
217a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	}
218958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
2197f2343824550452974d78f5dbd94e64844355c33Linus Walleij	/* number of characters including terminating 0 (PTP standard confirmed) */
220a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	htod8a(&data[offset],packedlen+1);
221a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
222a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
223958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
224958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* The returned length is in number of characters */
225048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij	*len = (uint8_t) packedlen+1;
226eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
227eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
228a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline unsigned char *
229735f41692934a716158cf051d76e988febeca7eeLinus Walleijptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
230a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
2318b42ca3d3baeb7c8f3e5eca88c613adb612e4ec0Richard Low	uint8_t packed[PTP_MAXSTRLEN*2+3], len;
232a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t plen;
233a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	unsigned char *retcopy = NULL;
234d47b9218023a6b943a93faa743712ae072cba85cRichard Low
235d47b9218023a6b943a93faa743712ae072cba85cRichard Low	if (string == NULL)
236d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
237d47b9218023a6b943a93faa743712ae072cba85cRichard Low	else
238d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
239d47b9218023a6b943a93faa743712ae072cba85cRichard Low
240958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* returned length is in characters, then one byte for string length */
241958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	plen = len*2 + 1;
242048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij
243a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	retcopy = malloc(plen);
244735f41692934a716158cf051d76e988febeca7eeLinus Walleij	if (!retcopy) {
245735f41692934a716158cf051d76e988febeca7eeLinus Walleij		*packed_size = 0;
246a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return NULL;
247735f41692934a716158cf051d76e988febeca7eeLinus Walleij	}
248a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	memcpy(retcopy, packed, plen);
249735f41692934a716158cf051d76e988febeca7eeLinus Walleij	*packed_size = plen;
250a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return (retcopy);
251a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
252a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
253b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
254b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t **array)
255eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
256eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
257eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
258eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
259eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint32_t));
260eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
261eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
262eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
263eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
264eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
265eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
266eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
267b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
268f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
269f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij{
270f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	uint32_t i=0;
271f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
272f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	*data = malloc ((arraylen+1)*sizeof(uint32_t));
273f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	htod32a(&(*data)[0],arraylen);
274f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	for (i=0;i<arraylen;i++)
275f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
276f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	return (arraylen+1)*sizeof(uint32_t);
277f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij}
278f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
279f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijstatic inline uint32_t
280b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, uint16_t offset, uint16_t **array)
281eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
282eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
283eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
284eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
285eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint16_t));
286eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	while (n>i) {
287eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
288eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		i++;
289eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
290eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
291eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
292eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
293eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* DeviceInfo pack/unpack */
294eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
295eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_StandardVersion		 0
296eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionID	 2
297eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionVersion	 6
298eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionDesc	 8
299eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_FunctionalMode		 8
300eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_OperationsSupported	10
301eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
302b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
303b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
304eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
305eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t len;
306eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	unsigned int totallen;
3077e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
308d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij	if (!data) return;
309d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij	if (datalen < 12) return;
3107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
311eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionID =
312eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh32a(&data[PTP_di_VendorExtensionID]);
313eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionVersion =
314eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
315eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionDesc =
316eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_string(params, data,
317eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_VendorExtensionDesc, &len);
318eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=len*2+1;
319eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->FunctionalMode =
320eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
321eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
322eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
323eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->OperationsSupported);
324eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
325eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
326eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
327eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->EventsSupported);
328eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
329eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DevicePropertiesSupported_len =
330eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_uint16_t_array(params, data,
331eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
332eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->DevicePropertiesSupported);
333eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
334eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
335eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
336eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->CaptureFormats);
337eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
338eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
339eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
340eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->ImageFormats);
341eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
342eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Manufacturer = ptp_unpack_string(params, data,
343eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
344eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
345eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
346eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Model = ptp_unpack_string(params, data,
347eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
348eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
349eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
350eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DeviceVersion = ptp_unpack_string(params, data,
351eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
352eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
353eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
354eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->SerialNumber = ptp_unpack_string(params, data,
355eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
356eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
357eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
358a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
359e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleijstatic void inline
360a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleijptp_free_DI (PTPDeviceInfo *di) {
361a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->SerialNumber) free (di->SerialNumber);
362a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->DeviceVersion) free (di->DeviceVersion);
363a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->Model) free (di->Model);
364a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->Manufacturer) free (di->Manufacturer);
365a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->ImageFormats) free (di->ImageFormats);
366a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->CaptureFormats) free (di->CaptureFormats);
367a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->VendorExtensionDesc) free (di->VendorExtensionDesc);
368a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->OperationsSupported) free (di->OperationsSupported);
369a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->EventsSupported) free (di->EventsSupported);
370a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (di->DevicePropertiesSupported) free (di->DevicePropertiesSupported);
371a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij}
3727e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij/* EOS Device Info unpack */
3747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijstatic inline void
3757e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
3767e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij{
3777e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int totallen = 4;
37896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
37996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	memset (di,0, sizeof(*di));
3807e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (datalen < 8) return;
3817e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3827e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	/* uint32_t struct len - ignore */
3837e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
3847e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		totallen, &di->EventsSupported);
3857e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->EventsSupported) return;
3867e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
3877e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (totallen >= datalen) return;
3887e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3897e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
3907e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		totallen, &di->DevicePropertiesSupported);
3917e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->DevicePropertiesSupported) return;
3927e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
3937e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (totallen >= datalen) return;
3947e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
3957e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->unk_len = ptp_unpack_uint32_t_array(params, data,
3967e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		totallen, &di->unk);
3977e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->unk) return;
3987e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->unk_len*sizeof(uint32_t)+4;
3997e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	return;
4007e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij}
4010d762ccc39331608119dd0267021b165e22de499Linus Walleij
4020d762ccc39331608119dd0267021b165e22de499Linus Walleijstatic inline void
4030d762ccc39331608119dd0267021b165e22de499Linus Walleijptp_free_EOS_DI (PTPCanonEOSDeviceInfo *di)
4040d762ccc39331608119dd0267021b165e22de499Linus Walleij{
4050d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->EventsSupported);
4060d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->DevicePropertiesSupported);
4070d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->unk);
4080d762ccc39331608119dd0267021b165e22de499Linus Walleij}
409eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
410eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectHandles array pack/unpack */
411eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
412eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oh				 0
413eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
414b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
415b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
416eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
417f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (len) {
418f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, &oh->Handler);
419f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	} else {
420f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = 0;
421f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->Handler = NULL;
422f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
423eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
424eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
425eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StoreIDs array pack/unpack */
426eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
427eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_sids			 0
428eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
429b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
430b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
431eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
43296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij        if (!data && !len) {
43396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		sids->n = 0;
43496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		sids->Storage = NULL;
43596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		return;
43696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij        }
437eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids,
438eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	&sids->Storage);
439eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
440eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
441eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StorageInfo pack/unpack */
442eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
443eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageType		 0
444eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FilesystemType		 2
445eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_AccessCapability		 4
446eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_MaxCapability		 6
447eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInBytes		14
448eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInImages	22
449eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageDescription	26
450eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
451b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
452b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
453eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
454eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t storagedescriptionlen;
455eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
456eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
457eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
458eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
459eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
460eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
461eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
462eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageDescription=ptp_unpack_string(params, data,
463eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription, &storagedescriptionlen);
464eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->VolumeLabel=ptp_unpack_string(params, data,
465eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription+storagedescriptionlen*2+1,
466eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&storagedescriptionlen);
467eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
468eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
469eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectInfo pack/unpack */
470eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
471eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_StorageID		 0
472eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectFormat		 4
473eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ProtectionStatus		 6
474eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectCompressedSize	 8
475eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbFormat		12
476eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbCompressedSize	14
477eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixWidth		18
478eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixHeight		22
479eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixWidth		26
480eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixHeight		30
481eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImageBitDepth		34
482eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ParentObject		38
483eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationType		42
484eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationDesc		44
485eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_SequenceNumber		48
486eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_filenamelen		52
487eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_Filename			53
488eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
489a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* the max length assuming zero length dates. We have need 3 */
490a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* bytes for these. */
491a679b1c4d273f210abb6befc5d9954a25427c329Richard Low#define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
492a679b1c4d273f210abb6befc5d9954a25427c329Richard Low
493b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
494b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
495eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
496b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* oidata;
497eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
498eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen=0;
499a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	/* let's allocate some memory first; correct assuming zero length dates */
5000546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	oidata=malloc(PTP_oi_MaxLen + params->ocs64*4);
5010546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	*oidataptr=oidata;
502eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* the caller should free it after use! */
503eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0
504eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date="20020101T010101"; /* XXX Fake date */
505eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
5060546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	memset (oidata, 0, PTP_oi_MaxLen + params->ocs64*4);
507eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
508eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
509eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
510eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
5110546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (params->ocs64)
5120546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		oidata += 4;
513eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
514eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
515eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
516eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
517eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
518eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
519eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
520eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
521eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
522eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
523eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
524eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
525eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
526eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
527eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	filenamelen=(uint8_t)strlen(oi->Filename);
528eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
529eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
530eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
531eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
532eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
533eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/*
534eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 *XXX Fake date.
535eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * for example Kodak sets Capture date on the basis of EXIF data.
536eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * Spec says that this field is from perspective of Initiator.
537eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
538eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
539eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capturedatelen=strlen(capture_date);
540eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
541eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
542eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
543eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
544eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
545eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
546eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
547eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
548eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
549eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		  capture_date[i];
550eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
551eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
552eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* XXX this function should return dataset length */
5530546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3)+params->ocs64*4;
554eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
555eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
5563bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleijstatic time_t
5576db174f4d18af574fab991309e11010aa0eb4543Linus Walleijptp_unpack_PTPTIME (const char *str) {
5583bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char ptpdate[40];
5593bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char tmp[5];
560a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	size_t  ptpdatelen;
5613bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	struct tm tm;
5623bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
5633bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	if (!str)
5643bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
5653bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	ptpdatelen = strlen(str);
5667e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen >= sizeof (ptpdate)) {
5676db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
5683bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
5697e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
5707e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen<15) {
5716db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
5723bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
5737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
574a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	strncpy (ptpdate, str, sizeof(ptpdate));
575a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	ptpdate[sizeof(ptpdate) - 1] = '\0';
5763bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
5773bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	memset(&tm,0,sizeof(tm));
5783bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate, 4);
5793bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[4] = 0;
5803bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_year=atoi (tmp) - 1900;
5813bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 4, 2);
5823bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5833bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mon = atoi (tmp) - 1;
5843bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 6, 2);
5853bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5863bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mday = atoi (tmp);
5873bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 9, 2);
5883bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5893bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_hour = atoi (tmp);
5903bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 11, 2);
5913bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5923bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_min = atoi (tmp);
5933bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 13, 2);
5943bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
5953bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_sec = atoi (tmp);
596e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	tm.tm_isdst = -1;
5973bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	return mktime (&tm);
5983bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij}
5993bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
600b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
601b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
602eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
603eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
604eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen;
605eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date;
606eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
607eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
608eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
609eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
610eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
6110546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
6120546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	/* Stupid Samsung Galaxy developers emit a 64bit objectcompressedsize */
6130546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if ((data[PTP_oi_filenamelen] == 0) && (data[PTP_oi_filenamelen+4] != 0)) {
6140546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		params->ocs64 = 1;
6150546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		data += 4;
6160546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	}
617eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
618eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
619eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
620eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
621eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
622eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
623eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
624eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
625eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
626eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
627eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
6280546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
629eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
630eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
631eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
632eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
633eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* subset of ISO 8601, without '.s' tenths of second and
634eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * time zone
635eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
6366db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
637eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
638eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
6393bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	/* now the modification date ... */
640eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
641eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2
642eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		+capturedatelen*2+2,&capturedatelen);
6436db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->ModificationDate = ptp_unpack_PTPTIME(capture_date);
644eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
645eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
646eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
647eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Custom Type Value Assignement (without Length) macro frequently used below */
648b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define CTVAL(target,func) {			\
649b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(target))	\
650b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;			\
651b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	target = func(&data[*offset]);		\
652b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(target);		\
653eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
654eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
655b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define RARR(val,member,func)	{			\
656b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int n,j;					\
657b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(uint32_t))		\
658b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;				\
659b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	n = dtoh32a (&data[*offset]);			\
660b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(uint32_t);			\
661b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij							\
662b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.count = n;				\
663b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
664b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!val->a.v) return 0;			\
665b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (j=0;j<n;j++)				\
666b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(val->a.v[j].member, func);	\
667b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
668eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
669b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
670b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPV (
671b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPParams *params, unsigned char* data, int *offset, int total,
672b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPPropertyValue* value, uint16_t datatype
673b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij) {
674eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
675b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
676b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i8,dtoh8a);
677b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
678b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
679b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u8,dtoh8a);
680b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
681b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
682b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i16,dtoh16a);
683b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
684b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
685b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u16,dtoh16a);
686b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
687b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
688b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i32,dtoh32a);
689b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
690b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
691b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u32,dtoh32a);
692b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
693abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
694abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->i64,dtoh64a);
695abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
696abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
697abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->u64,dtoh64a);
698abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
699abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
700037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_UINT128:
701037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
702037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of uint128n");*/
703037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
704037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_INT128:
705037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
706037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of int128n");*/
707037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
708037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
709037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
710037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
711b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
712b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i8,dtoh8a);
713b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
714b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
715b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u8,dtoh8a);
716b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
717b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
718b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u16,dtoh16a);
719b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
720b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
721b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i16,dtoh16a);
722b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
723b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
724b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u32,dtoh32a);
725b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
726b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
727b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i32,dtoh32a);
728b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
729abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
730abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,u64,dtoh64a);
731abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
732abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
733abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,i64,dtoh64a);
734abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
735b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
736b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int arrays are unimplemented also */
737b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
738b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		uint8_t len;
739b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		/* XXX: max size */
740b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		value->str = ptp_unpack_string(params,data,*offset,&len);
741b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		*offset += len*2+1;
742b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!value->str)
743deddc3490b3084b802737017982285bfa58b382fLinus Walleij			return 1;
744b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
745eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
746037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	default:
747037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		return 0;
748b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
749b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
750eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
751eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
752eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Device Property pack/unpack */
753eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DevicePropertyCode	0
754eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DataType		2
755eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_GetSet			4
756eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_FactoryDefaultValue	5
757eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
758b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
759b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
760eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
761b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
762eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
763b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (dpd, 0, sizeof(*dpd));
764eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
765eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
766eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
767deddc3490b3084b802737017982285bfa58b382fLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
768b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
769b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_dpd_FactoryDefaultValue;
770b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
771b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
772deddc3490b3084b802737017982285bfa58b382fLinus Walleij	if ((dpd->DataType == PTP_DTC_STR) && (offset == dpdlen))
773deddc3490b3084b802737017982285bfa58b382fLinus Walleij		return 1;
774b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
775b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
776b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
777b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* if offset==0 then Data Type format is not supported by this
778b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   code or the Data Type is a string (with two empty strings as
779b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
780b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   not present. */
781b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
782b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (offset==PTP_dpd_FactoryDefaultValue)
783b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 1;
784b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
785b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	dpd->FormFlag=dtoh8a(&data[offset]);
786b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
787eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
788eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (dpd->FormFlag) {
789b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Range:
790b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
791b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
792b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
793b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
794b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
795b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
796eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
797b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Enumeration: {
798b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
799eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
800b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
801b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
802b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
803b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
804b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
805b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
806b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
807b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
808b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
809b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
810b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
811b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
812b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
813b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
814b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
815b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
816b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
817b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
818b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
819b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
820eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			}
821b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
822eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
823eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
824b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
825b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
826b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
827b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_devicepropdesc(dpd);
828b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
829eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
830eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
831d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijstatic inline void
832d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijduplicate_PropertyValue (const PTPPropertyValue *src, PTPPropertyValue *dst, uint16_t type) {
833d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	if (type & PTP_DTC_ARRAY_MASK) {
834d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		int i;
835d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
836d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->a.count = src->a.count;
837d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->a.v = malloc (sizeof(src->a.v)*src->a.count);
838d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		for (i=0;i<src->a.count;i++)
839d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij			duplicate_PropertyValue (&src->a.v[i], &dst->a.v[i], type & ~PTP_DTC_ARRAY_MASK);
840d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		return;
841d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	}
842d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	switch (type & ~PTP_DTC_ARRAY_MASK) {
843d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT8:	dst->i8 = src->i8; break;
844d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT8:	dst->u8 = src->u8; break;
845d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT16:	dst->i16 = src->i16; break;
846d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT16:	dst->u16 = src->u16; break;
847d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT32:	dst->i32 = src->i32; break;
848d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT32:	dst->u32 = src->u32; break;
849d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT64:	dst->u64 = src->u64; break;
850d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT64:	dst->i64 = src->i64; break;
851d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij#if 0
852d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT128:	dst->i128 = src->i128; break;
853d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT128:	dst->u128 = src->u128; break;
854d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij#endif
855d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_STR: 	dst->str = strdup(src->str); break;
856d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	default:		break;
857d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	}
858d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	return;
859d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij}
860d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
861d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijstatic inline void
862d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijduplicate_DevicePropDesc(const PTPDevicePropDesc *src, PTPDevicePropDesc *dst) {
863d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	int i;
864d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
865d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->DevicePropertyCode	= src->DevicePropertyCode;
866d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->DataType		= src->DataType;
867d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->GetSet		= src->GetSet;
868d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
869d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	duplicate_PropertyValue (&src->FactoryDefaultValue, &dst->FactoryDefaultValue, dst->DataType);
870d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	duplicate_PropertyValue (&src->CurrentValue, &dst->CurrentValue, dst->DataType);
871d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
872d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->FormFlag		= src->FormFlag;
873d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	switch (src->FormFlag) {
874d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DPFF_Range:
875d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		duplicate_PropertyValue (&src->FORM.Range.MinimumValue, &dst->FORM.Range.MinimumValue, src->DataType);
876d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		duplicate_PropertyValue (&src->FORM.Range.MaximumValue, &dst->FORM.Range.MaximumValue, src->DataType);
877d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		duplicate_PropertyValue (&src->FORM.Range.StepSize,     &dst->FORM.Range.StepSize,     src->DataType);
878d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		break;
879d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DPFF_Enumeration:
880d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->FORM.Enum.NumberOfValues = src->FORM.Enum.NumberOfValues;
881d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->FORM.Enum.SupportedValue = malloc (sizeof(dst->FORM.Enum.SupportedValue[0])*src->FORM.Enum.NumberOfValues);
882d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		for (i = 0; i<src->FORM.Enum.NumberOfValues ; i++)
883d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij			duplicate_PropertyValue (&src->FORM.Enum.SupportedValue[i], &dst->FORM.Enum.SupportedValue[i], src->DataType);
884d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		break;
885d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DPFF_None:
886d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		break;
887d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	}
888d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij}
889d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
890b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_ObjectPropertyCode	0
891b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_DataType		2
892b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_GetSet			4
893b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_FactoryDefaultValue	5
894eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
895b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
896b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
897eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
898b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int offset=0, ret;
899b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
900b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (opd, 0, sizeof(*opd));
901b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
902b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
903b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
904b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
905b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_opd_FactoryDefaultValue;
906b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
907b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
908b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
909b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GroupCode=dtoh32a(&data[offset]);
910b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint32_t);
911b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
912b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->FormFlag=dtoh8a(&data[offset]);
913b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
914b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
915b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	switch (opd->FormFlag) {
916b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Range:
917b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
918b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
919b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
920b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
921b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
922b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
923b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
924b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Enumeration: {
925b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
926b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define N	opd->FORM.Enum.NumberOfValues
927b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
928b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
929b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
930b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!opd->FORM.Enum.SupportedValue)
931b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
932b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
933b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
934b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
935b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
936b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
937b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
938b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
939b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
940b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
941b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
942b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
943b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
944b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
945b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				opd->FORM.Enum.NumberOfValues = i;
946b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
947b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			}
948b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
949b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
950b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
951eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
952b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
953b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
954b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_objectpropdesc(opd);
955b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
956eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
957eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
958eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
959b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
960b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
961eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
962b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* dpv=NULL;
963eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t size=0;
964b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int	i;
965eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
966eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
967b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
968b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int8_t);
969b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
970b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->i8);
971b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
972b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
973b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint8_t);
974b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
975b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->u8);
976b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
977b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
978b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int16_t);
979b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
980b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->i16);
981b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
982b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
983b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint16_t);
984b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
985b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->u16);
986b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
987b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
988b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int32_t);
989b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
990b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->i32);
991b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
992b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
993b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t);
994b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
995b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->u32);
996b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
997abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
998abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(int64_t);
999abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1000abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->i64);
1001abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1002abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
1003abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint64_t);
1004abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1005abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->u64);
1006abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1007b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
1008b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
1009b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1010b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1011b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1012cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
1013b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1014b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
1015b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
1016b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1017b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1018b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1019cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
1020b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1021b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
1022b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
1023b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1024b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1025b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1026cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
1027b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1028b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
1029b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
1030b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1031b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1032b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1033cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
1034b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1035b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
1036b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
1037b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1038b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1039b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1040cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
1041b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1042b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
1043b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
1044b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1045b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1046b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1047cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
1048b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1049abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
1050abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
1051abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1052abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
1053abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
1054cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
1055abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1056abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
1057abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
1058abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1059abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
1060abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
1061cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
1062abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1063b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
1064b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
1065735f41692934a716158cf051d76e988febeca7eeLinus Walleij		dpv=ptp_get_packed_stringcopy(params, value->str, &size);
1066eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
1067b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1068eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
1069eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*dpvptr=dpv;
1070eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return size;
107199310d4445697da39f22dff35457c75e35e97171Linus Walleij}
107299310d4445697da39f22dff35457c75e35e97171Linus Walleij
107399310d4445697da39f22dff35457c75e35e97171Linus Walleij#define MAX_MTP_PROPS 127
107499310d4445697da39f22dff35457c75e35e97171Linus Walleijstatic inline uint32_t
10751e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
107699310d4445697da39f22dff35457c75e35e97171Linus Walleij{
107799310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char* opldata;
10781e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *propitr;
107999310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char *packedprops[MAX_MTP_PROPS];
108099310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t packedpropslens[MAX_MTP_PROPS];
108139b9374f23451201dece736db13f0f648584dc32Linus Walleij	uint32_t packedobjecthandles[MAX_MTP_PROPS];
108299310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropsids[MAX_MTP_PROPS];
108399310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropstypes[MAX_MTP_PROPS];
108499310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t totalsize = 0;
108599310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t bufp = 0;
108699310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t noitems = 0;
108799310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t i;
108899310d4445697da39f22dff35457c75e35e97171Linus Walleij
108999310d4445697da39f22dff35457c75e35e97171Linus Walleij	totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
10901e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	propitr = props;
10911e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	while (nrofprops-- && noitems < MAX_MTP_PROPS) {
10926c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		/* Object Handle */
109339b9374f23451201dece736db13f0f648584dc32Linus Walleij		packedobjecthandles[noitems]=propitr->ObjectHandle;
109499310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint32_t); /* Object ID */
109599310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Metadata type */
109699310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropsids[noitems]=propitr->property;
109799310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
109899310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Data type */
109999310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropstypes[noitems]= propitr->datatype;
110099310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
110199310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Add each property to be sent. */
110299310d4445697da39f22dff35457c75e35e97171Linus Walleij	        packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
110399310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += packedpropslens[noitems];
110499310d4445697da39f22dff35457c75e35e97171Linus Walleij		noitems ++;
11051e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		propitr ++;
110699310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
110799310d4445697da39f22dff35457c75e35e97171Linus Walleij
110899310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Allocate memory for the packed property list */
110999310d4445697da39f22dff35457c75e35e97171Linus Walleij	opldata = malloc(totalsize);
111099310d4445697da39f22dff35457c75e35e97171Linus Walleij
111199310d4445697da39f22dff35457c75e35e97171Linus Walleij	htod32a(&opldata[bufp],noitems);
111299310d4445697da39f22dff35457c75e35e97171Linus Walleij	bufp += 4;
111399310d4445697da39f22dff35457c75e35e97171Linus Walleij
111499310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Copy into a nice packed list */
111599310d4445697da39f22dff35457c75e35e97171Linus Walleij	for (i = 0; i < noitems; i++) {
111699310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Object ID */
11176c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		htod32a(&opldata[bufp],packedobjecthandles[i]);
111899310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint32_t);
111999310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropsids[i]);
112099310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
112199310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropstypes[i]);
112299310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
112399310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* The copy the actual property */
112499310d4445697da39f22dff35457c75e35e97171Linus Walleij		memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
112599310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += packedpropslens[i];
112699310d4445697da39f22dff35457c75e35e97171Linus Walleij		free(packedprops[i]);
112799310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
112899310d4445697da39f22dff35457c75e35e97171Linus Walleij	*opldataptr = opldata;
112999310d4445697da39f22dff35457c75e35e97171Linus Walleij	return totalsize;
1130eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1131eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
11321e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijstatic int
11331e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij_compare_func(const void* x, const void *y) {
11341e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *px = x;
11351e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *py = y;
11361e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
11371e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	return px->ObjectHandle - py->ObjectHandle;
11381e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij}
11391e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
11408d82d2f4b0794e41ec26289045867eebb3496b8cRichard Lowstatic inline int
11411e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
11428d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low{
1143277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	uint32_t prop_count = dtoh32a(data);
11441e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *props = NULL;
1145277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	int offset = 0, i;
1146277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1147277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	if (prop_count == 0) {
11481e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		*pprops = NULL;
1149277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		return 0;
1150277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
1151d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij	ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
1152277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	data += sizeof(uint32_t);
11533bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	len -= sizeof(uint32_t);
11541e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	props = malloc(prop_count * sizeof(MTPProperties));
11551e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	if (!props) return 0;
1156277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	for (i = 0; i < prop_count; i++) {
11573bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		if (len <= 0) {
1158d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
11593bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL", i);
11603bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i);
1161d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			qsort (props, i, sizeof(MTPProperties),_compare_func);
1162d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			*pprops = props;
11633bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			return i;
11643bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		}
11651e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].ObjectHandle = dtoh32a(data);
1166277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint32_t);
1167277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint32_t);
1168277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
11691e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].property = dtoh16a(data);
1170277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1171277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1172277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
11731e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].datatype = dtoh16a(data);
1174277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1175277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1176277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1177277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		offset = 0;
11781e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype);
1179277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += offset;
1180277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= offset;
1181277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
11821e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
11831e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	*pprops = props;
1184277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	return prop_count;
11858d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low}
11868d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low
1187eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1188eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP USB Event container unpack
1189eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1190eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1191eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1192eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Length		0
1193eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Type		4
1194eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Code		6
1195eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_TransId		8
1196eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param1		12
1197eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param2		16
1198eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param3		20
1199eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1200b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
12017e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
1202eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
12037e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int	length;
12047e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int	type;
12057e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
1206eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1207eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
12087e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	memset(ec,0,sizeof(*ec));
12097e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	length=dtoh32a(&data[PTP_ec_Length]);
12107e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	type = dtoh16a(&data[PTP_ec_Type]);
1211b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
12127e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Code=dtoh16a(&data[PTP_ec_Code]);
12137e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
12147e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
12157e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (type!=PTP_USB_CONTAINER_EVENT) {
12167e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ptp_debug (params, "Unknown canon event type %d (code=%x,tid=%x), please report!",type,ec->Code,ec->Transaction_ID);
12177e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		return;
12187e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
12197e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param1+4)) {
12207e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
12217e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=1;
12227e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
12237e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param2+4)) {
12247e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
12257e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=2;
12267e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
12277e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param3+4)) {
12287e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
12297e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=3;
12307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
1231eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1232eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1233eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1234eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP Canon Folder Entry unpack
1235eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1236eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1237eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectHandle		0
1238eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectFormatCode	4
1239eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Flags			6
1240eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectSize		7
1241eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Time			11
1242eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Filename		15
1243eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1244b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1245b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1246eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1247eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
1248eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1249eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
1250eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
1251eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
1252eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
1253b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
1254eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
1255eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1256b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
1257b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
1258b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
125996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij/*
126096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij    PTP Canon EOS Folder Entry unpack
126196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0: 00 00 08 a0     objectid
126296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij4: 01 00 02 00     storageid
126396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij8: 01 30 00 00     ofc
126496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij12: 01 00
126596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij14: 00 00
126696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij16: 11 00 00 00
126796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij20: 00 00 00 00
126896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij24: 00 00 00 80
126996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij28: 00 00 08 a0
127096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij32: 4d 49 53 43-00 00 00 00 00 00 00 00     name
127196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij00 00 00 00
127296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij84 bc 74 46     objectime
127396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
127496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
127596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij(normal PTP GetObjectInfo)
127696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus WalleijObjectInfo for 'IMG_0199.JPG':
127796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  Object ID: 0x92740c72
127896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  StorageID: 0x00020001
127996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ObjectFormat: 0x3801
128096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ProtectionStatus: 0x0000
128196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ObjectCompressedSize: 2217241
128296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbFormat: 0x3808
128396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbCompressedSize: 5122
128496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbPixWidth: 160
128596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbPixHeight: 120
128696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImagePixWidth: 4000
128796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImagePixHeight: 3000
128896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImageBitDepth: 24
128996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ParentObject: 0x92740000
129096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  AssociationType: 0x0000
129196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  AssociationDesc: 0x00000000
129296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  SequenceNumber: 0x00000000
129396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ModificationDate: 0x4d985ff0
129496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  CaptureDate: 0x4d985ff0
129596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
129696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0010  38 00 00 00  Size of this entry
129796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0014  72 0c 74 92  OID
129896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0018  01 00 02 00  StorageID
129996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij001c  01 38 00 00  OFC
130096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0020  00 00 00 00 00 00 00 00  ?
130196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0028  19 d5 21 00  Size
130296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij002c  00 00 74 92  ?
130396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0030  70 0c 74 92  OID
130496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0034  49 4d 47 5f-30 31 39 39 2e 4a 50 47  IMG_0199.JPG
130596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0040  00 00 00 00
130696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0044  10 7c 98 4d Time
130796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
130896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
130996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij*/
131096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectHandle		0
131196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_StorageID		4
131296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectFormatCode	8
131396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Flags			12
131496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectSize		20
131596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Filename		32
131696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Time			48
131796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
131896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleijstatic inline void
131996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleijptp_unpack_Canon_EOS_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
132096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij{
132196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int i;
132296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
132396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cefe_ObjectHandle]);
132496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cefe_ObjectFormatCode]);
132596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->Flags=dtoh8a(&data[PTP_cefe_Flags]);
132696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cefe_ObjectSize]);
132796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cefe_Time]);
132896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
132996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		fe->Filename[i]=(char)data[PTP_cefe_Filename+i];
133096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij}
133196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
133296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
13331a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint16_t
13341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
13351a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
13361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	/*
13370546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  EOS ImageFormat entries (of at least the 5DM2 and the 400D) look like this:
13381a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: number of entries / generated files (1 or 2)
13391a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: size of this entry in bytes (most likely allways 0x10)
13401a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image type (1 == JPG, 6 == RAW)
13410546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		uint32: image size (0 == Large, 1 == Medium, 2 == Small, 0xe == S1, 0xf == S2, 0x10 == S3)
13421a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW)
13430546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  If the number of entries is 2 the last 4 uint32 repeat.
13441a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13451a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  example:
13461a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		0: 0x       1
13471a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		1: 0x      10
13481a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		2: 0x       6
13491a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		3: 0x       1
13501a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		4: 0x       4
13511a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13520546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  The idea is to simply 'condense' these values to just one uint16 to be able to conveniently
13531a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  use the available enumeration facilities (look-up table). The image size and compression
13541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  values fully describe the image format. Hence we generate a uint16 with the four nibles set
13551a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  as follows: entry 1 size | entry 1 compression | entry 2 size | entry 2 compression.
13561a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  The above example would result in the value 0x1400.
13570546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
13580546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  The EOS 5D Mark III (and possibly other high-end EOS as well) added the extra fancy S1, S2
13590546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  and S3 JPEG options. S1 replaces the old Small. -1 the S1/S2/S3 to prevent the 0x10 overflow.
13601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  */
13611a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13621a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	const unsigned char* d = *data;
13631a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = dtoh32a( d );
13641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t l, s1, c1, s2 = 0, c2 = 0;
13651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n != 1 && n !=2) {
13671a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
13681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
13691a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
13701a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	l = dtoh32a( d+=4 );
13721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (l != 0x10) {
13731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
13741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
13751a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
13761a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	d+=4; /* skip type */
13781a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	s1 = dtoh32a( d+=4 );
13791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	c1 = dtoh32a( d+=4 );
13801a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13811a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n == 2) {
13821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		l = dtoh32a( d+=4 );
13831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		if (l != 0x10) {
13841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
13851a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			return 0;
13861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		}
13871a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		d+=4; /* skip type */
13881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		s2 = dtoh32a( d+=4 );
13891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		c2 = dtoh32a( d+=4 );
13901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
13911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13921a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	*data = (unsigned char*) d+4;
13931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
13940546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	/* deal with S1/S2/S3 JPEG sizes, see above. */
13950546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if( s1 >= 0xe )
13960546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		s1--;
13970546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if( s2 >= 0xe )
13980546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		s2--;
13990546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
14011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
14021a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
14031a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint32_t
14041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
14051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
14061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = (value & 0xFF) ? 2 : 1;
14071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t s = 4 + 0x10 * n;
14081a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
14091a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if( !data )
14101a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return s;
14111a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
14120546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner#define PACK_5DM3_SMALL_JPEG_SIZE( X ) (X) >= 0xd ? (X)+1 : (X)
14130546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14141a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=0, n);
14151a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, 0x10);
14161a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, ((value >> 8) & 0xF) == 4 ? 6 : 1);
14170546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 12) & 0xF));
14181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, (value >> 8) & 0xF);
14191a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
14201a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n==2) {
14211a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, 0x10);
14221a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, ((value >> 0) & 0xF) == 4 ? 6 : 1);
14230546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 4) & 0xF));
14241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, (value >> 0) & 0xF);
14251a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
14261a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
14270546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner#undef PACK_5DM3_SMALL_JPEG_SIZE
14280546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14290546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return s;
14300546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner}
14310546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14320546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerstatic inline char*
14330546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerptp_unpack_EOS_CustomFuncEx (PTPParams* params, unsigned char** data )
14340546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner{
14350546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t s = dtoh32a( *data );
14360546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t n = s/4, i;
1437a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	char* str = (char*)malloc( s ); /* n is size in uint32, average len(itoa(i)) < 4 -> alloc n chars */
14380546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (!str)
14390546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		return str;
14400546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	char* p = str;
14410546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14420546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	for (i=0; i < n; ++i)
14430546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		p += sprintf(p, "%x,", dtoh32a( *data + 4*i ));
14440546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14450546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return str;
14460546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner}
14470546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14480546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerstatic inline uint32_t
14490546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerptp_pack_EOS_CustomFuncEx (PTPParams* params, unsigned char* data, char* str)
14500546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner{
14510546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t s = strtoul(str, NULL, 16);
14520546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t n = s/4, i, v;
14530546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14540546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (!data)
14550546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		return s;
14560546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14570546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	for (i=0; i<n; i++)
14580546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	{
14590546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		v = strtoul(str, &str, 16);
1460a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij		str++; /* skip the ',' delimiter */
14610546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		htod32a(data + i*4, v);
14620546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	}
14630546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
14641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return s;
14651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
14661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
1467b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/*
1468f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij    PTP EOS Changes Entry unpack
1469f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij*/
1470f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Size		0
1471f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Type		4
1472f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1473f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Subtype	8	/* only for properties */
1474f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Val_Data	0xc	/* only for properties */
1475f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Type	0xc	/* only for property descs */
1476f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Count	0x10	/* only for property descs */
1477f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Data	0x14	/* only for property descs */
1478f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1479d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_RequestObjectTransfer */
1480d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_ObjectID	8
1481d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_OFC		0x0c
1482d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Size		0x14
1483d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Name		0x1c
1484d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij
1485d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_ObjectAddedEx */
1486d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_ObjectID	8
1487d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_StorageID	0x0c
1488d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_OFC		0x10
1489d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Size		0x1c
1490d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Parent	0x20
1491d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Name		0x28
1492f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1493f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijstatic inline int
1494f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **ce)
1495f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij{
1496f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	int	i = 0, entries = 0;
1497f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	unsigned char	*curdata = data;
1498f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1499f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (data==NULL)
1500f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		return 0;
1501f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1502f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1503f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1504f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1505f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
1506f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		if ((size == 8) && (type == 0))
1507f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1508f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		entries++;
1509f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
15109d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij	*ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
1511f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (!*ce) return 0;
1512f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1513f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	curdata = data;
1514f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1515f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1516f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1517f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1518d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1519d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij		(*ce)[i].u.info = NULL;
1520f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		switch (type) {
1521d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		case  PTP_EC_CANON_EOS_ObjectAddedEx:
1522f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
1523d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
1524d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.StorageID 		= dtoh32a(&curdata[PTP_ece_OA_StorageID]);
1525d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ParentObject	= dtoh32a(&curdata[PTP_ece_OA_Parent]);
1526d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OA_OFC]);
1527d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
1528d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OA_Name]));
1529d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			ptp_debug (params, "event %d: objectinfo added oid %08lx, parent %08lx, ofc %04x, size %d, filename %s", i, (*ce)[i].u.object.oid, (*ce)[i].u.object.oi.ParentObject, (*ce)[i].u.object.oi.ObjectFormat, (*ce)[i].u.object.oi.ObjectCompressedSize, (*ce)[i].u.object.oi.Filename);
1530d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			break;
1531d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		case  PTP_EC_CANON_EOS_RequestObjectTransfer:
1532d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
1533f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
1534d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.StorageID 		= 0; /* use as marker */
1535f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OI_OFC]);
1536d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			(*ce)[i].u.object.oi.ParentObject	= 0; /* check, but use as marker */
1537f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
1538f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OI_Name]));
15393bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
1540d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			ptp_debug (params, "event %d: request object transfer oid %08lx, ofc %04x, size %d, filename %s", i, (*ce)[i].u.object.oid, (*ce)[i].u.object.oi.ObjectFormat, (*ce)[i].u.object.oi.ObjectCompressedSize, (*ce)[i].u.object.oi.Filename);
1541f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
15427e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case  PTP_EC_CANON_EOS_AvailListChanged: {	/* property desc */
1543f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1544f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
1545f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
1546e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij			unsigned char	*xdata = &curdata[PTP_ece_Prop_Desc_Data];
1547f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			int		j;
1548f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			PTPDevicePropDesc	*dpd;
1549f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
15507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype);
1551f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			for (j=0;j<params->nrofcanon_props;j++)
1552f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (params->canon_props[j].proptype == proptype)
1553f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1554f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (j==params->nrofcanon_props) {
15553bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
1556f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1557f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1558f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			dpd = &params->canon_props[j].dpd;
15597e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			/* 1 - uint16 ?
15607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 3 - uint16
15617e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 7 - string?
15627e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 */
1563f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (propxtype != 3) {
15643bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled.", i, propxtype, proptype);
15653bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++)
1566e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					ptp_debug (params, "    %d: %02x", j, xdata[j]);
1567f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1568f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
15691a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			if (! propxcnt)
15701a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
15711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
15731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				   i, propxtype, proptype, dpd->DataType, propxcnt);
15741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FormFlag = PTP_DPFF_Enumeration;
15751a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.NumberOfValues = propxcnt;
15760d762ccc39331608119dd0267021b165e22de499Linus Walleij			if (dpd->FORM.Enum.SupportedValue) free (dpd->FORM.Enum.SupportedValue);
15771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
15781a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			switch (proptype) {
15801a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormat:
15811a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatCF:
15821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatSD:
15831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatExtHD:
15841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* special handling of ImageFormat properties */
1585f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<propxcnt;j++) {
15861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->FORM.Enum.SupportedValue[j].u16 =
1587e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij							dtoh16( ptp_unpack_EOS_ImageFormat( params, &xdata ) );
15881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
15891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
15901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
15911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			default:
15921a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* 'normal' enumerated types */
15931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (dpd->DataType) {
15941a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX( TYPE, CONV )\
15951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<propxcnt;j++) { \
1596e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(xdata); \
1597e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(xdata)); \
1598e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						xdata += 4; /* might only be for propxtype 3 */ \
15991a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					} \
16001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
16011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16021a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_INT16:	XX( i16, dtoh16a );
16031a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT32:	XX( u32, dtoh32a );
16041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT16:	XX( u16, dtoh16a );
16051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT8:	XX( u8,  dtoh8a );
16061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
16071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				default:
1608e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, raw values:", i, dpd->DataType, proptype, dtoh32a(xdata));
1609e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, xdata+=4) /* 4 is good for propxtype 3 */
1610e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %3d: 0x%8x", j, dtoh32a(xdata));
16111a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
1612f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1613f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1614f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1615f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
16167e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case PTP_EC_CANON_EOS_PropValueChanged:
1617f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (size >= 0xc) {	/* property info */
1618f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				int j;
1619f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1620e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij				unsigned char	*xdata = &curdata[PTP_ece_Prop_Val_Data];
1621f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				PTPDevicePropDesc	*dpd;
1622f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
16231a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				ptp_debug (params, "event %d: EOS prop %04x info record, datasize is %d", i, proptype, size-PTP_ece_Prop_Val_Data);
1624f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<params->nrofcanon_props;j++)
1625f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (params->canon_props[j].proptype == proptype)
1626f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						break;
1627f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (j<params->nrofcanon_props) {
1628f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (	(params->canon_props[j].size != size) ||
1629e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						(memcmp(params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data))) {
1630f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
1631e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						memcpy (params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data);
1632f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					}
1633f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				} else {
1634f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (j)
1635f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
1636f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					else
1637f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = malloc(sizeof(params->canon_props[0]));
1638f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].type = type;
1639f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].proptype = proptype;
1640f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].size = size;
1641f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
1642e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					memcpy(params->canon_props[j].data, xdata, size-PTP_ece_Prop_Val_Data);
1643f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
1644f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.GetSet = 1;
1645f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
1646f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->nrofcanon_props = j+1;
1647f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1648f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				dpd = &params->canon_props[j].dpd;
16491a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
1650d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
1651d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				(*ce)[i].u.propid = proptype;
1652d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
16531a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* fix GetSet value */
16541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (proptype) {
16551a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX(x) case PTP_DPC_CANON_##x:
16561a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusMode)
16571a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryPower)
16581a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatterySelect)
16591a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ModelID)
16601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_PTPExtensionVersion)
16611a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DPOFVersion)
16621a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AvailableShots)
16631a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentStorage)
16641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentFolder)
16651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenu)
16661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenuList)
16671a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_HDDirectoryStructure)
16681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryInfo)
16691a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AdapterInfo)
16701a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensStatus)
16711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CardExtension)
16721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_TempStatus)
16731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ShutterCounter)
16741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_SerialNumber)
16751a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfFieldPreview)
16761a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EVFRecordStatus)
16771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LvAfSystem)
16781a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusInfoEx)
16791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfField)
16801a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_Brightness)
16811a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EFComp)
16821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensName)
16831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensID)
16841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
16851a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						dpd->GetSet = PTP_DPGS_Get;
16861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						break;
16871a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
16881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* set DataType */
1690f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (proptype) {
1691ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DPC_CANON_EOS_CameraTime:
1692d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_AvailableShots:
1693d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CaptureDestination:
1694d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXA:
1695d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXB:
1696d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentStorage:
1697d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentFolder:
1698d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ShutterCounter:
1699d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ModelID:
1700d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LensID:
1701d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_StroboFiring:
1702ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
1703ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
17040d762ccc39331608119dd0267021b165e22de499Linus Walleij				/* enumeration for AEM is never provided, but is available to set */
17050d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_AutoExposureMode:
17060d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
17070d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FormFlag = PTP_DPFF_Enumeration;
17080d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FORM.Enum.NumberOfValues = 0;
17090d762ccc39331608119dd0267021b165e22de499Linus Walleij					break;
1710f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Aperture:
1711f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ShutterSpeed:
1712f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ISOSpeed:
17137e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_FocusMode:
17147e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorSpace:
17157e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_BatteryPower:
1716e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BatterySelect:
1717d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_PTPExtensionVersion:
17181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_DriveMode:
17191a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_AEB:
1720e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BracketMode:
1721e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_QuickReviewTime:
17220d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFMode:
17230d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFOutputDevice:
1724a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij				case PTP_DPC_CANON_EOS_AutoPowerOff:
1725f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
1726f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1727f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_PictureStyle:
1728f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalance:
1729f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_MeteringMode:
17307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ExpCompensation: /* actually int8 if you calculate */
1731f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT8;
1732f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1733f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Owner:
17341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Artist:
17351a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Copyright:
17361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_SerialNumber:
17371a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_LensName:
1738f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_STR;
1739f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
17407e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
17417e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
17427e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					dpd->DataType = PTP_DTC_INT16;
17437e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
17447e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
17457e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DPOFVersion:
17461a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
17471a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
17481a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1749e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
17501a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
17517e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc1:
17527e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc2:
17537e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc3:
17547e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc4:
17557e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc5:
17567e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc6:
17577e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc7:
17587e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc8:
17597e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc9:
17607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc10:
17617e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc11:
17621a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT8;
17631a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint8", i ,proptype, size-PTP_ece_Prop_Val_Data);
17647e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1765e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
17661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					/* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */
1767e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					xdata += 4;
17687e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
17697e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* yet unknown 32bit props */
17707e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorTemperature:
17717e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WftStatus:
17727e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_LensStatus:
17737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CardExtension:
17747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_TempStatus:
17757e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_PhotoStudioMode:
17767e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfFieldPreview:
17777e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFSharpness:
17787e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFWBMode:
17797e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
17807e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFColorTemp:
1781d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_EVFRecordStatus:
1782d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ExposureSimMode:
1783d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvAfSystem:
1784d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_MovSize:
1785d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfField:
1786d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvViewTypeSelect:
17870d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
17887e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
17891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
17901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
17911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
1792e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: 0x%8x", j, ((uint32_t*)xdata)[j]);
17937e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
1794d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				/* ImageFormat properties have to be ignored here, see special handling below */
1795d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
1796d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
1797d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
1798d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
17990546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				case PTP_DPC_CANON_EOS_CustomFuncEx:
1800d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
1801f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
18023bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
18033bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
1804e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
1805f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1806f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1807f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (dpd->DataType) {
1808ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DTC_UINT32:
1809e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u32	= dtoh32a(xdata);
1810e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u32		= dtoh32a(xdata);
18113bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
1812ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
1813f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT16:
1814e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= dtoh16a(xdata);
1815e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u16		= dtoh16a(xdata);
18163bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
1817f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1818f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT8:
1819e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u8	= dtoh8a(xdata);
1820e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u8		= dtoh8a(xdata);
18213bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
1822f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1823f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_STR: {
18241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
1825f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					uint8_t len = 0;
1826f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->FactoryDefaultValue.str	= ptp_unpack_string(params, data, 0, &len);
1827f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->CurrentValue.str		= ptp_unpack_string(params, data, 0, &len);
18281a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#else
18290d762ccc39331608119dd0267021b165e22de499Linus Walleij					if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
1830e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.str	= strdup( (char*)xdata );
18310d762ccc39331608119dd0267021b165e22de499Linus Walleij
18320d762ccc39331608119dd0267021b165e22de499Linus Walleij					if (dpd->CurrentValue.str) free (dpd->CurrentValue.str);
1833e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.str		= strdup( (char*)xdata );
18341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#endif
18357e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
1836f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1837f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1838f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
1839f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					/* debug is printed in switch above this one */
1840f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1841f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
18421a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
18430546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				/* ImageFormat and customFuncEx special handling (WARNING: dont move this in front of the dpd->DataType switch!) */
1844d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				switch (proptype) {
1845d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
1846d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
1847d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
1848d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
1849d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
1850e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= ptp_unpack_EOS_ImageFormat( params, &xdata );
1851d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->CurrentValue.u16		= dpd->FactoryDefaultValue.u16;
1852d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					ptp_debug (params,"event %d: decoded imageformat, currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
1853d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
18540546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				case PTP_DPC_CANON_EOS_CustomFuncEx:
18550546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->DataType = PTP_DTC_STR;
18560546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					if (dpd->FactoryDefaultValue.str) free (dpd->FactoryDefaultValue.str);
18570546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					if (dpd->CurrentValue.str)	  free (dpd->CurrentValue.str);
18580546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->FactoryDefaultValue.str	= ptp_unpack_EOS_CustomFuncEx( params, &data );
18590546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->CurrentValue.str		= strdup( (char*)dpd->FactoryDefaultValue.str );
18600546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					ptp_debug (params,"event %d: decoded custom function, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
18610546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					break;
1862d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				}
1863d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
1864f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1865f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1866d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij		case PTP_EC_CANON_EOS_CameraStatusChanged:
1867d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			ptp_debug (params, "event %d: EOS event CameraStatusChanged (size %d)", i, size);
1868d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS;
1869d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			(*ce)[i].u.status =  dtoh32a(curdata+8);
18709e09ad0e32cbdac88637d4ee2cc02ca3b771ca40Linus Walleij			params->eos_camerastatus = dtoh32a(curdata+8);
1871d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			break;
18727e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case 0: /* end marker */
18737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size == 8) /* no output */
18747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				break;
18757e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
18767e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			break;
187796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		case PTP_EC_CANON_EOS_BulbExposureTime:
187896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
187996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			(*ce)[i].u.info = malloc(strlen("BulbExposureTime 123456789"));
188096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			sprintf ((*ce)[i].u.info, "BulbExposureTime %d",  dtoh32a(curdata+8));
188196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			break;
1882f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		default:
1883d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			switch (type) {
1884d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij#define XX(x)		case PTP_EC_CANON_EOS_##x: 								\
1885d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				ptp_debug (params, "event %d: unhandled EOS event "#x" (size %d)", i, size); 	\
1886d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				(*ce)[i].u.info = malloc(strlen("unhandled EOS event "#x" (size 123456789)"));	\
1887d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				sprintf ((*ce)[i].u.info, "unhandled EOS event "#x" (size %d)",  size);		\
1888d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				break;
1889d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetEvent)
1890d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectRemoved)
1891d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetObjectInfoEx)
1892d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageStatusChanged)
1893d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageInfoChanged)
1894d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectInfoChangedEx)
1895d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectContentChanged)
1896d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(WillSoonShutdown)
1897d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ShutdownTimerUpdated)
1898d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransfer)
1899d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferDT)
1900d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransferDT)
1901d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreAdded)
1902d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreRemoved)
1903d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(BulbExposureTime)
1904d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RecordingTime)
1905d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferTS)
1906d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(AfResult)
1907d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#undef XX
1908d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			default:
1909d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
1910d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				break;
1911d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			}
19127e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size >= 0x8) {	/* event info */
19137e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				int j;
1914d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				for (j=8;j<size;j++)
1915d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij					ptp_debug (params, "    %d: %02x", j, curdata[j]);
19167e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			}
1917f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			(*ce)[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
1918f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1919f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
1920f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
1921f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		i++;
19229d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij		if ((size == 8) && (type == 0))
19239d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij			break;
1924f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
19250d762ccc39331608119dd0267021b165e22de499Linus Walleij	if (!entries) {
19260d762ccc39331608119dd0267021b165e22de499Linus Walleij		free (*ce);
19270d762ccc39331608119dd0267021b165e22de499Linus Walleij		*ce = NULL;
19280d762ccc39331608119dd0267021b165e22de499Linus Walleij	}
1929f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	return entries;
1930f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij}
1931f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1932f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij/*
1933b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij    PTP USB Event container unpack for Nikon events.
1934b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij*/
1935b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Length		0
1936b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Code		2
1937b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Param1		4
1938b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Size		6
1939b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
19407e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, int *cnt)
1941b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij{
1942b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i;
1943b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1944b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = NULL;
1945b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (data == NULL)
1946b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1947b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (len < PTP_nikon_ec_Code)
1948b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
1949b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
1950b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
1951b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
19520d762ccc39331608119dd0267021b165e22de499Linus Walleij	if (!*cnt)
19530d762ccc39331608119dd0267021b165e22de499Linus Walleij		return;
19540d762ccc39331608119dd0267021b165e22de499Linus Walleij
19557e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	*ec = malloc(sizeof(PTPContainer)*(*cnt));
1956b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1957b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<*cnt;i++) {
19587e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		memset(&(*ec)[i],0,sizeof(PTPContainer));
19597e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
19607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
19617e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Nparam	= 1;
1962b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1963eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1964eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1965eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1966b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
1967b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
1968b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i, len = 0;
1969b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint8_t	retlen;
1970b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char *curdata;
1971b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1972b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	len =	2*(strlen(text->title)+1)+1+
1973b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[0])+1)+1+
1974b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[1])+1)+1+
1975b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[2])+1)+1+
1976b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[3])+1)+1+
1977b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[4])+1)+1+
1978b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		4*2+2*4+2+4+2+5*4*2;
1979b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*data = malloc(len);
1980b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!*data) return 0;
1981b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1982b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	curdata = *data;
1983b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,100);curdata+=2;
1984b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1);curdata+=2;
1985b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0);curdata+=2;
1986b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1000);curdata+=2;
1987b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1988b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1989b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1990b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1991b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,6);curdata+=2;
1992b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
1993b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1994b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1995b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0x10);curdata+=2;
1996b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1997b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<5;i++) {
1998b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
1999b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x10);curdata+=2;
2000b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x01);curdata+=2;
2001b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x02);curdata+=2;
2002b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x06);curdata+=2;
2003b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
2004b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return len;
2005b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
20067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_version	0x00
20087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_ofc	0x02
20097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk1	0x04
20107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_objectid	0x08
20117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_parentid	0x0c
20127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_previd	0x10	/* in same dir */
20137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextid	0x14	/* in same dir */
20147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextchild	0x18	/* down one dir */
20157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_storageid	0x1c	/* only in storage entry */
20167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_name	0x20
20177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_flags	0x2c
20187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_size	0x30
20197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unixtime	0x34
20207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_year	0x38
20217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_month	0x39
20227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_mday	0x3a
20237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_hour	0x3b
20247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_minute	0x3c
20257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_second	0x3d
20267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk2	0x3e
20277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_thumbsize	0x40
20287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_width	0x44
20297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_height	0x48
20307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20317347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijstatic inline uint16_t
20327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijptp_unpack_canon_directory (
20337347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPParams		*params,
20347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned char		*dir,
20357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		cnt,
20367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectHandles	*handles,
20377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectInfo		**oinfos,	/* size(handles->n) */
20387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		**flags		/* size(handles->n) */
20397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij) {
20407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned int	i, j, nrofobs = 0, curob = 0;
20417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20427347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
20437347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++)
20447347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(dir+i*0x4c)) nrofobs++;
20457347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->n = nrofobs;
20467347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->Handler = calloc(sizeof(handles->Handler[0]),nrofobs);
20477347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!handles->Handler) return PTP_RC_GeneralError;
20487347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*oinfos = calloc(sizeof((*oinfos)[0]),nrofobs);
20497347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*oinfos) return PTP_RC_GeneralError;
20507347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	*flags  = calloc(sizeof((*flags)[0]),nrofobs);
20517347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*flags) return PTP_RC_GeneralError;
20527347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20537347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Migrate data into objects ids, handles into
20547347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the object handler array.
20557347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 */
20567347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	curob = 0;
20577347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
20587347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
20597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		PTPObjectInfo	*oi = (*oinfos)+curob;
20607347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20617347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!ISOBJECT(cur))
20627347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
20637347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20647347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
20657347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->StorageID		= 0xffffffff;
20667347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectFormat	= dtoh16a(cur + ptp_canon_dir_ofc);
20677347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ParentObject	= dtoh32a(cur + ptp_canon_dir_parentid);
20687347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->Filename		= strdup((char*)(cur + ptp_canon_dir_name));
20697347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
20707347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ThumbCompressedSize	= dtoh32a(cur + ptp_canon_dir_thumbsize);
20717347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixWidth	= dtoh32a(cur + ptp_canon_dir_width);
20727347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixHeight	= dtoh32a(cur + ptp_canon_dir_height);
20737347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->CaptureDate		= oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
20747347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*flags)[curob]		= dtoh32a(cur + ptp_canon_dir_flags);
20757347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		curob++;
20767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
20777347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over Storage ID entries and distribute the IDs to
20787347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the parent objects. */
20797347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
20807347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
20817347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
20827347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20837347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(cur))
20847347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
20857347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
20867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (j == handles->n) continue;
20877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
20887347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
20897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over all objects and distribute the storage ids */
20907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	while (1) {
20917347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		int changed = 0;
20927347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (i=0;i<cnt;i++) {
20937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			unsigned char	*cur = dir+i*0x4c;
20947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	oid = dtoh32a(cur + ptp_canon_dir_objectid);
20957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
20967347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
20977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	storageid;
20987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
20997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (!ISOBJECT(cur))
21007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
21017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
21027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (j == handles->n) {
21037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				/*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
21047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
21057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
21067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 		storageid = (*oinfos)[j].StorageID;
21077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (storageid == 0xffffffff) continue;
21087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextoid != 0xffffffff) {
21097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
21107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
21117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
21127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
21137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
21147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
21157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
21167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
21177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
21187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
21197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextchild != 0xffffffff) {
21207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
21217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
21227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
21237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
21247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
21257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
21267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
21277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
21287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
21297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
21307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		}
21317347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		/* Check if we:
21327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed no entry (nothing more to do)
21337347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed all of them at once (usually happens)
21347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * break if we do.
21357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 */
21367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!changed || (changed==nrofobs-1))
21377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			break;
21387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
21397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#undef ISOBJECT
21407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	return PTP_RC_OK;
21417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij}
2142